JWT设计
RESTful架构的前后端,天然要求API是无状态的,JWT(JSON Web Token)简单易用,适合在分布式系统中做API无状态的身份认证。
jwt由Header、Payload、Signature三部分组成,使用 . 分割开,一个JWT形式:
Header.Payload.Signature
这三部分分别对应的是加密算法、携带的用户信息、加密后的字符串(签名)。
jwt自带签名,能够防止伪造或篡改,但要防止token被窃取还要配合https使用。
下面我们用jwt开发一个前后端交互系统。
JWT服务端
这里使用jjwt开源库生成token:
Server端基于SpringBoot开发,提供生成token和校验token的接口:
@PostMapping("/login")
Back login(@RequestParam("name") String name,
@RequestParam("pwd") String pwd);
@GetMapping("/user")
Back getUser(@RequestHeader("jwt") String token);
用户名密码和用户信息通过JPA持久化到不同的MySQL数据库表中,通过用户id关联两张表
登录接口:客户端提交用户名密码,服务端返回jwt令牌,如:
eyJhbGciOiJIUzUxMiJ9.eyJyb2xlIjoiYWRtaW4iLCJzdWIiOiI0MDI4Yjg4MTVmN2I0MmQxMDE1ZjdiNDQ4ZTZjMDAwMCIsImV4cCI6MTUxMDQ2NjEyMn0.U3UOe8Jc6HLE3hw8r6BSus8mr2q1mguo3jiFsLkvRf5jsNX2ibZzmJSVgGUmanNSN05Jrv6ZiBMmVbo-R5TYbg
用户信息接口:客户端将token放在请求头,服务端校验是否合法,然后通过JAP从MySQL中查询并返回用户信息
服务端无需存储jwt令牌,通过特定的算法和密钥校验token,同时取出Payload中携带的用户ID,减少不必要的数据库查询
本例中设置JWT有效期为10天,服务端每次都会自动校验token是否过期,如果过期就直接抛出异常,客户端需要重新申请token
JWT客户端
Android客户端使用Retrofit做REST请求。
登录接口:提交用户名密码,服务端返回jwt令牌:
用户信息接口:客户端将token放在请求头,服务端校验通过即返回用户信息
客户端在本地存储token以后就能免登陆
JWT的缺陷
JWT使用起来虽然简单方便,但它存在一个设计缺陷,即服务端无法主动注销token,所以jwt在安全性上不及session,实际开发中应谨慎使用。
如果要让服务端能够注销token,就要在服务端维持token状态,这又回到session机制了,所以在经常需要验证的场景中,建议还是使用session。
JWT这个缺陷决定了它更适合用在一次性token验证场景中,即token只使用一次就立即废弃掉,比如第三方登录授权。
扫一扫关注我的微信公众号