SpringBoot集成JWT
一、JWT的简述
JWT 是Json Web Token的简称;JWT由头部(header)、载荷(payload)、签证(signature)三部分组成;其三部分之间用.分隔,例如:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEiLCJleHAiOjE2NTkxMDU0MTIsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ.ciurjE4dS3CBckl25Df6eaQvzJIuiM5Wk-LD_gfoEBs
1. 头部-header
jwt的头部承载两部分信息
- 声明类型,这里时jwt
- 声明加密的算法,通常直接使用 HMAC SHA256
如:
{
'typ': 'JWT',
'alg': 'HS256'
}
使用base64加密,构成第一部分:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
2.载荷-payload
载荷就是存放有效信息的地方,包含三个部分
标准中注册的声明
公共的声明
私有的声明
这其中标准中注册的声明(建议但不强制使用)包括如下部分
iss : jwt签发者
sub: jwt面向的用户
aud: 接收方
exp: jwt过期时间
nbf: 定义在什么时间之前,jwt都是不可用的
iat: jwt签发时间
jwt唯一身份标识
公共声明存放用户或业务等相关信息
私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息
如:
{
"sub": "18700000000",
"name": "songweipeng",
"admin": true
}
BASE64 加密
1 2 3 4 5 | eyJpZCI6IjEiLCJleHAiOjE2NTkxMDU0MTIsInVzZXJuYW1lIjoiemhhbmdzYW4ifQ var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload); var signature = HMACSHA256(encodedString, '密钥' ); |
加密之后,得到signature签名信息。
ciurjE4dS3CBckl25Df6eaQvzJIuiM5Wk-LD_gfoEBs
3.签证-signature
jwt的第三部分是一个签证信息,这个签证信息由三部分组成
二、SpringBoot 集成
2.1 jwt依赖
1 2 3 4 5 6 7 | <!-- jwt依赖 --> <!-- https: //mvnrepository.com/artifact/com.auth0/java-jwt --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version> 3.18 . 2 </version> </dependency> |
2.2 获取token的工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | import com.auth0.jwt.JWT; import com.auth0.jwt.JWTCreator; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import java.util.Calendar; import java.util.Map; /** * @Project: * @Description: * @Auther: songwp * @Date: 2022/7/22 22:23 **/ public class JWTUtils { private static final String SING = "@#%$^&lu123456" ; /** * 生成token */ public static String getToken(Map<String,String> map){ Calendar instance = Calendar.getInstance(); //默认7天过期 instance.add(Calendar.DATE, 7 ); //创建jwt builder JWTCreator.Builder builder = JWT.create(); map.forEach((k,v)->{ builder.withClaim(k,v); }); String token = builder.withExpiresAt(instance.getTime()) .sign(Algorithm.HMAC256(SING)); return token; } /** * 验证token合法性 */ public static DecodedJWT verify(String token){ return JWT.require(Algorithm.HMAC256(SING)).build().verify(token); } /** * 根据token获取载荷信息 * @param token * @return */ public static Map<String, Claim> getPayloadByToken(String token) { return verify(token).getClaims(); } |
2.3 创建拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.SignatureVerificationException; import com.auth0.jwt.exceptions.TokenExpiredException; import com.auth0.jwt.interfaces.DecodedJWT; import com.fasterxml.jackson.databind.ObjectMapper; import com.songwp.hutooldemo.untils.JWTUtils; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map; /** * @Project: * @Description: * @Auther: songwp * @Date: 2022/7/22 22:31 **/ public class JWTInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader( "Authorization" );<br> Result<T> result = new Result<T>();<br> try {<br> //验证令牌<br> DecodedJWT verify = JwtUtils.verify(token);<br> UserTokenInfoHolder.setUserTokenInfo(verify.getClaims());<br> return true;<br> } catch (SignatureVerificationException e) {<br> e.printStackTrace();<br> result.setCode(-1);<br> result.setMessage("无效签名");<br> } catch (TokenExpiredException e) {<br> e.printStackTrace();<br> result.setCode(-1);<br> result.setMessage("token过期");<br> } catch (AlgorithmMismatchException e) {<br> e.printStackTrace();<br> result.setCode(-1);<br> result.setMessage("token算法不一致");<br> } catch (JWTDecodeException e) {<br> e.printStackTrace();<br> result.setCode(-1);<br> result.setMessage("token不合法");<br> } catch (NullPointerException e) {<br> e.printStackTrace();<br> result.setCode(-1);<br> result.setMessage("token不能为空");<br> } catch (Exception e) {<br> e.printStackTrace();<br> result.setCode(-1);<br> result.setMessage("token无效");<br> }<br> //将返回值result转为json<br> String json = new ObjectMapper().writeValueAsString(result);<br> response.setContentType("application/json;charset=UTF-8");<br> response.getWriter().println(json);<br> return false;<br> }<br><br>} |
2.4 拦截器注册
/**
* @Project:
* @Description:
* @Auther: songwp
* @Date: 2022/7/22 22:33
**/
import com.songwp.hutooldemo.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 注册拦截器
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 配置跨域访问
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")//项目中的所有接口都支持跨域
.allowedOrigins("*")//所有地址都可以访问,也可以配置具体地址
.allowCredentials(true)
.allowedMethods("*")//"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"
.maxAge(3600);// 跨域允许时间
}
/**
* 注册拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
//拦截
.addPathPatterns("/user/test")
//放行
.excludePathPatterns("/user/login");
}
@Bean
public JWTInterceptor tokenInterceptor(){
return new JWTInterceptor();
}
}
古今成大事者,不唯有超世之才,必有坚韧不拔之志!
分类:
java
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)