与传统B/S模式的Web系统不同,移动端APP与服务器之间的接口交互一般是C/S模式,这种情况下如果涉及到用户登录的话,就不能像Web系统那样依赖于Web容器来管理Session了,因为APP每发一次请求都会在服务器端创建一个新的Session。而有些涉及到用户隐私或者资金交易的接口又必须确认当前用户登录的合法性,如果没有登录或者登录已过期则不能进行此类操作。
我见过一种“偷懒”的方式,就是在用户第一次登录之后,保存用户的ID在本地存储中,之后跟服务器交互的接口都通过用户ID来标识用户身份。
这种方式主要有两个弊端:
只要本地存储的用户ID没有被删掉,就始终可以访问以上接口,不需要重新登录,除非增加有效期的判断或者用户主动退出;
接口安全性弱,因为用户ID对应了数据库里的用户唯一标识,别人只要能拿到用户ID或者伪造一个用户ID就可以使用以上接口对该用户进行非法操作。
综上考虑,可以利用缓存在服务器端模拟Session管理机制来解决这个问题,当然这只是目前我所知道的一种比较简单有效的解决APP用户Session的方案。如果哪位朋友有其它好的方案,欢迎在下面留言交流。
这里用的缓存框架是Ehcache,下载地址,当然也可以用Memcached或者其它的。之所以用Ehcache框架,一方面因为它轻量、快速、集成简单等,另一方面它也是Hibernate中默认的CacheProvider,对于已经集成了Hibernate的项目不需要再额外添加Ehcache的jar包了。
有了Ehcache,接着就要在Spring配置文件里添加相应的配置了,配置信息如下:
1 <!-- 配置缓存管理器工厂 --> 2 <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"> 3 <property name="configLocation" value="classpath:ehcache.xml" /> 4 <property name="shared" value="true" /> 5 </bean> 6 <!-- 配置缓存工厂,缓存名称为myCache --> 7 <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheFactoryBean"> 8 <property name="cacheName" value="myCache" /> 9 <property name="cacheManager" ref="cacheManager" /> 10 </bean>
另外,Ehcache的配置文件ehcache.xml里的配置如下:
1 <?xml version="1.0" encoding="gbk"?> 2 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:noNamespaceSchemaLocation="ehcache.xsd"> 4 <diskStore path="java.io.tmpdir" /> 5 6 <!-- 配置一个默认缓存,必须的 --> 7 <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="30" overflowToDisk="false" /> 8 9 <!-- 配置自定义缓存 maxElementsInMemory:缓存中允许创建的最大对象数 eternal:缓存中对象是否为永久的,如果是,超时设置将被忽略,对象从不过期。 10 timeToIdleSeconds:缓存数据的钝化时间,也就是在一个元素消亡之前, 两次访问时间的最大时间间隔值,这只能在元素不是永久驻留时有效, 11 如果该值是 0 就意味着元素可以停顿无穷长的时间。 timeToLiveSeconds:缓存数据的生存时间,也就是一个元素从构建到消亡的最大时间间隔值, 12 这只能在元素不是永久驻留时有效,如果该值是0就意味着元素可以停顿无穷长的时间。 overflowToDisk:内存不足时,是否启用磁盘缓存。 memoryStoreEvictionPolicy:缓存满了之后的淘汰算法。 --> 13 <cache name="myCache" maxElementsInMemory="10000" eternal="true" overflowToDisk="true" memoryStoreEvictionPolicy="LFU" /> 14 </ehcache>
配置好Ehcache之后,就可以直接通过@Autowired或者@Resource注入缓存实例了。示例代码如下: