在基于 springboot 的管理系统中,将 jwt 集成在系统中,并作为系统前后端分离的认证方式。
什么是 jwt
jwt 全称为 json web token,它是一个开放标准,它是一种基于 json 格式,传递可以被验证和信任的信息。
jwt 由三个部分组成,这三个部分为
- header
- payload (body)
- signature
Header
header 部分是一个 json 对象,描述 jwt 的元数据,通常是下面的样子
1 | { |
alg 属性表示签名的算法,默认是 HMAC SHA256,typ 标识这个令牌的类型,JWT 令牌统一写 JWT。最后,用 Base64 URL 算法转换为字符串。
Payload
payload 也是一个 json 对象,用来存放实际需要传递的数据, JWT 规定了7个官方字段
- iss (issuer) 签发人
- exp (expiration time) 过期时间
- sub (subject) 主题
- aud (audience) 受众
- nbf (Not before) 生效时间
- iat (Issued At) 签发时间
- jti (JWT ID) JWT 编号
除了上述的官方字段,你还可以自定义一些私有字段,通常 payload 部分只用 Base64 进行编码,一般不加密,所以私有字段不要存放敏感信息。
Signature
signature 是对前两个部分进行签名,防止篡改。
Java JWT
JJWT 是用于 Android 和 Java 平台的 JSON Web Token。本系统采用了该包作为 JWT 认证,验证工具。
在 maven 中加入下面的依赖,来使用 JJWT
1 | <dependency> |
封装工具类
参考 jjwt 的使用手册,对 jjwt 进行封装,主要包括,创建 token ,认证,获取 token 中信息等功能。
1 | package github.beginner.noname.util; |
上述代码涉及其他依赖:
- lombok
- spring
spring MVC 集成 jwt 认证 (无框架)
在这里,出于学习的目的,没有使用 shiro 或者 spring security 等框架,而是自己才用相对原生(原始)的手段,来集成 jwt 认证,以便加深对 jwt 认证的理解。
我理解的 jwt 认证的方式大致是如下述图所示。
认证的核心就是要对所有的请求进行验证,查看是否存在 token 并且要验证 token 是否合法。
核心步骤如下:
- 对所有的请求进行验证,这里就需要用到 spring MVC 的 web 拦截器,对请求进行拦截,查看请求是否携带 token。
- 判断该请求是否需要验证 token (存在一些无需认证的 URL), 如果需要验证,执行第三步, 若不需要,进行放行。
- 使用封装好的 jjwt 工具对 token 进行验证,验证通过,放行请求,不通过,返回对应的响应结果。
spring mvc 使用拦截器对所有请求进行拦截,代码如下:
1 | package github.beginner.noname.config.web.interceptor; |
上述代码,首先请求的路径上是否有 @NotCheckJwt 注解。
1 | package github.beginner.noname.annotation; |
如果存在该注解,则直接放行,说明对应的 URL 不需要验证 jwt。其次,从 header 中获取对应的 token 信息 (我这里把 token 放在了 header中),如果为空,抛出异常,如果不为空,进行验证,验证失败的话,抛出异常。这里抛出的异常交给了 spring mvc 的 HandlerExceptionResolver 来进行处理。
1 | package github.beginner.noname.config.web.exception; |
这一步完成后,所以访问的 URL ,如果没有 @NotCheckJwt 注解,都会进行 token 验证。