一、什么是JWT
JSON Web Token(缩写 JWT),是目前最流行的一个跨域认证解决方案:客户端发起用户登录请求,服务器端接收并认证成功后,生成一个 JSON 对象(如下所示),然后将其返回给客户端。客户端再次与服务器端通信的时候,把这个 JSON 对象捎带上,作为前后端互相信任的一个凭证。服务器端接收到请求后,通过 JSON 对象对用户身份进行鉴定,这样就不再需要保存任何 session 数据了。
访问JWT官网可对JWT(如同很长的字符串,中间用点(.)分隔成三个部分)进行解码,解码的内容由HEADER、PAYLOAD和VERIFY SIGNATURE三个部分组成。
HEADER : ALGORITHM & TOKEN TYPE
Header 部分是一个 JSON 对象,描述 JWT 的元数据。
alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。
PAYLOAD : DATA
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
VERIFY SIGNATURE
Signature 部分是对前两部分的签名,防止数据篡改。
首先指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。
Base64URL算法
Header 和 Payload 的串型化都是使用的Base64URL算法。
JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符
+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_。这就是 Base64URL 算法。
可参考文档:阮一峰的JSON Web Token 入门教程
二、JWT的简单使用
引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
yml文件配置
# 登录认证 token filter
jwt:
tokenHeader: Authorization #JWT存储的请求头
secret: codingmore-admin-secret #JWT加解密使用的密钥
expiration: 604800 #JWT的超期限时间(60*60*24*7)
tokenHead: 'Bearer ' #JWT负载中拿到开头
JwtTokenUtil
使用JwtTokenUtil工具类完成JWT的生成,以及是否过期的判断
JwtTokenUtil存在三种方法完成主要功能
generateToken(UserDetails userDetails):根据登录用户生成 tokengetUserNameFromToken(String token):从 token 中获取登录用户validateToken(String token, UserDetails userDetails):判断 token 是否仍然有效
每次调用登录接口,后端都可把生成的JWT返回给前端,让前端保存在localStorage中
{
"code": 0,
"message": "操作成功",
"result": {
"tokenHead": "Bearer ",
"token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJzdG9ob3giLCJjcmVhdGVkIjoxNjU0MTQzODYzNDc5LCJleHAiOjE2NTQ3NDg2NjN9.qyZ0_UpKrN6lsX5gxqOeS8AuJdE3hQXeL_GPURbnnD-lG6yTHC-i8xR1GWHNccN0kFDlNXKKXHRo30uye-cbHw"
}
}
JwtAuthenticationTokenFilter
新建JwtAuthenticationTokenFilter过滤器继承OncePerRequestFilter,以保证客户端每发起一次请求,该过滤器只会执行一次。
JWT 和 Session 的根本区别:
- JWT 需要每次请求的时候验证一次,并且只要 JWT 没有过期,哪怕服务器端重启了,认证仍然有效。
- Session 在没有过期的情况下是不需要重新对用户信息进行验证的,当服务器端重启后,用户需要重新登录获取新的 Session。
前端在调取后端接口时,则需要在请求头上增加Authorization,内容为之前保存的JWT,并在JWT前加“Bearer”,用空格隔开。否则请求将会被过滤器过滤。
项目地址: github.com/itwanger/co…