目标:

经过 登录认证方案的论述 后,我们决定自己研发AppToken方案,来实现登录认证。

AppToken的特性

适用场景:AppToken适用于app,不支持cookie协议的地方。

存储:AppToken在客户端存储,一般使用本地存储( LocalStorage ),也在服务端存储,使用表来存储。

用户信息:AppToken是一个短字符串,其中不包含用户信息存储。计划把用户信息单独使用json来存储在客户端

状态:AppToken有状态

失效:AppToken长期有效,一般是3个月,app登录一次后,3个月内有效。可在服务端控制是否失效,在服务端的表中删除对应的token,客户端的登录就失效了。

续命:客户端每访问服务端一次,就会为AppToken续命,赋予新的有效期。

防盗取:这个没有什么办法,和sessionID一样的。如果有人盗取了你的sessionID,就可顶替你登录系统了。解决:使用https

跨域:AppToken由客户端本地存储( LocalStorage ),请求任何域的http接口都可手工携带jwt。不存在跨域问题。

表结构设计

表名 user_app_token(会员apptoken表)
列名 数据类型 约束条件 默认值 非空 是否索引 备注说明

t_id

NUMBER(19) 主键
主键
u_id NUMBER(19) 外键 会员ID
token NVARCHAR2(64)


令牌(uuid)

type VARCHAR2(4) 0

业务类型:0用户是前台会员,1用户是后台管理员。

shop有两套用户表,目前只给前台会员开发了app,未给后台管理员开发app

status char(1)
1
是否有效(0无效,1有效),如用户退出或修改了密码,应置为无效
create_date

date

sysdate

创建时间

valid_date date
sysdate

有效期的开始时间,如2019-01-01。

如果有效期是90天,那么将于2019-03-01的前一秒到期,由定时任务清理。

当为AppToken续命时, valid _date值被更新.

时序图

服务端返回的数据

app登录成功后,从服务端返回两样东西:AppToken和用户信息json数据, 要存储 在客户端存储,一般使用本地存储( LocalStorage )。

返回的数据json格式请看文档: AppToken方式调用登录接口

用户信息json数据包含以下信息

  1. 用户名
  2. 用户头像
  3. 用户id
  4. 是否是 采购商

注意-防大量创建session消耗内存

咱使用了AppToken,就不需要使用cookie 和session了。但你如何控制服务端不创建session?

每次客户端调用http接口都会创建session吗?连续访问1万次就创建1万个session,会把内存耗光吗?

答:

servlet:

当客户端访问一个servlet时,默认是不创建session的。
只有你调用了request.getSession()方法 或 getSession(boolean create) 时才会创建。

jsp:

当客户端访问一个jsp页面,默认是自动创建session的。
如果想不创建请在jsp顶部加入以下内容:
<%@ page session="false" %>

总结:不要调用 getSession()方法,就不会创建session,就不会把内存耗光。

为什么叫AppToken

app端的token叫AppToken,这是因为token这个名称已经被占用。

目前系统已有的token


已有的token 说明 生命周期 工具类 存储在哪里
1 通用token 目前用于上传图片和用户激活邮箱 一个token只能使用(验证)一次,就作废了 TokenUtils负责生成token验证token 在服务端是存在表里
2 AccessKey 目前用于访问安全图片时要携带AccessKey

AccessKey的有效期是30分钟,过期后将失效。一个AccessKey在有效期内,可被反复使用。

AccessKey是一个加密的字符串,可从中解密出时间有效期。

由com.sicheng.common.fileStorage.AccessKey类负责生成AccessKey、验证AccessKey是否合格 无需要存储,AccessKey是一个加密的字符串,可从中解密出时间有效期。

所在为app专用的token就叫AppToken了。


新的token 说明 生命周期 工具类 存储在哪里
3 AppToken 用于app端用户登录后的身份标识 3个月,可续命
在客户端存储在本地存储中( LocalStorage ),在服务端是存在表里


AppToken的缓存设计

AppToken是存储在数据库表中,每次验证都要查数据库,显得重了些,所以可通过缓存技术来提高性能。

三层存储

1、Request,在一次request请求生命范围内缓存数据;
2、Cache,一般缓存N天,使用Ehcache或Redis实现;
3、数据库,持久存储,有续命与定时清理程序来维护;

当要验证某个AppToken是否合法的过程

1、先尝试从Request中取出UserMain,若没找到则走第二步;
2、再尝试从Cache中取出UserMain,若没找到则走第三步;
3、最后从数据库中取出UserMain用户信息,,若没找到就是非法AppToken;

本缓存的不足

1、当使用合法AppToken时,命中缓存的机率较高;

2、当使用非法AppToken时,会穿透缓存直达数据库,缓存的机率为0; 解决思路:AppToken字符串不再使用uuid,使用能加解密或验签名的字符串,先验证合法性再查数据库。(留作以后升级实现)

定时任务–清理过期的AppToken

com.sicheng.admin.task.utils.TaskJob

使用Ehcache缓存带来的无法跨系统的问题
1、wap系统的appToken缓存的Ehcache中,admin系统的定任务无法清理wap系统的缓存
2、seller系统的shior缓存,当admin系统中操作“权限管理”、“菜单管理”时,无法跨系统清理seller系统缓存。

清理apptoken缓存的定时任务入在admin,无法跨系统清理Wap系统的Ehcache缓存
在wap放一套task定时任务模块,是无法实现的, 因为TaskRunnable依赖sysTimedTaskService

解决:Ehcache缓存中的apptoken设置有效期90天,与库中同时到期。缓存到期自动失效。定时任务只清理apptoken表的过期记录。

AppToken的续命

com.sicheng.wap.utils.AppTokenUtils.touchAppToken() 方法可实现续命。

使用了异步线程池。