JWT(JSON WEB TOKEN)
JWT的组成
header(头部):中主要存储了两个字段 alg,typ。 alg表示加密的算法默认(HMAC SHA256),typ表示这个令牌的类型默认为JWT。
payload(负载):存储了两部分信息
-
- 官方给出的7个字段
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
- 用户自定义字段
- name : 张三
- admin : true
- account :zhangsan
- 官方给出的7个字段
signature(签名):根据规则进行加密 HSA256(BASE64URLEnCode(header)+"."+BSSE64URLEncode(payload),secret)secret 为密钥,只要服务器才知道。算出签名后,header,payload,signature这三部分中间用.分割。
使用JWT的请求流程
- 客户端携带用户名、密码请求服务器,生成token并返回给客户端
- 客户端在header中设置authorization=token访问服务器
- 服务器校验用户身份信息,校验成功处理业务数据返回结果
使用JWTHelper工具
- JWTHelper中的方法
- 生成JWT
- 解析JWT
- 校验JWT是否有效
- 在服务器的登陆拦截器中调用JWT校验方法判断token的有效性,如果token无效则返回错误信息,如果token有效,可根据refresh_token更新access_token的有效时间。
利用JWT实现单点登录(SSO)
场景一:用户发起对业务系统的第一次访问,假设他第一次访问的是系统A的some/page这个页面,它最终成功访问到这个页面的过程是:
在这个过程里面,我认为理解的关键点在于:
1. 它用到了两个cookie(jwt和sid)和三次重定向来完成会话的创建和会话的传递;
1. jwt的cookie是写在systemA.com这个域下的,所以每次重定向到systemA.com的时候,jwt这个cookie只要有就会带过去;
2. sid的cookie是写在cas.com这个域下的,所以每次重定向到cas.com的时候,sid这个cookie只要有就会带过去;
3. 在验证jwt的时候,如何知道当前用户已经创建了sso的会话?因为jwt的payload里面存储了之前创建的sso 会话的session id,所以当cas拿到jwt,就相当于拿到了session id,然后用这个session id去判断有没有的对应的session对象即可。
还要注意的是:CAS服务里面的session属于服务端创建的对象,所以要考虑session id唯一性以及session共享(假如CAS采用集群部署的话)的问题。session id的唯一性可以通过用户名密码加随机数然后用hash算法如md5简单处理;session共享,可以用memcached或者redis这种专门的支持集群部署的缓存服务器管理session来处理。
由于服务端session具有生命周期的特点,到期需自动销毁,所以不要自己去写session的管理,免得引发其它问题,到github里找开源的缓存管理中间件来处理即可。存储session对象的时候,只要用session id作为key,session对象本身作为value,存入缓存即可。session对象里面除了session id,还可以存放登录之后获取的用户信息等业务数据,方便业务系统调用的时候,从session里面返回会话数据。
场景二:用户登录之后,继续访问系统A的其它页面,如some/page2,它的处理过程是:
从这一步可以看出,即使登录之后,也要每次跟CAS校验jwt的有效性以及会话的有效性,其实jwt的有效性也可以放在业务系统里面处理的,但是会话的有效性就必须到CAS那边才能完成了。当CAS拿到jwt里面的session id之后,就能到session 缓存服务器里面去验证该session id对应的session对象是否存在,不存在,就说明会话已经销毁了(退出)。
场景三:用户登录了系统A之后,再去访问其他系统如系统B的资源,比如系统B的some/page,它最终能访问到系统B的some/page的流程是:
这个过程的关键在于第一次重定向的时候,它会把sid这个cookie带回给CAS服务器,所以CAS服务器能够判断出会话是否已经建立,如果已经建立就跳过登录页的逻辑。
场景四:用户继续访问系统B的其它资源,如系统B的some/page2:
这个场景的逻辑跟场景二完全一致。
场景五:退出登录,假如它从系统B发起退出,最终的流程是:
最重要的是要清除sid的cookie,jwt的cookie可能业务系统都有创建,所以不可能在退出的时候还挨个去清除那些系统的cookie,只要sid一清除,那么即使那些jwt的cookie在下次访问的时候还会被传递到业务系统的服务端,由于jwt里面的sid已经无效,所以最后还是会被重定向到CAS登录页进行处理。
方案总结
以上方案两个关键的前提:
1. 整个会话管理其实还是基于服务端的session来做的,只不过这个session只存在于CAS服务里面;
2. CAS之所以信任业务系统的jwt,是因为这个jwt是CAS签发的,理论上只要认证通过,就可以认为这个jwt是合法的。