1、什么是JWT
2、JWT的作用是什么
3、SpringBoot整合JWT
1、什么是jwt
JWT全称是Json Web Token。JWT由三部分组成Header(头)、Payload(有效载荷)和Signature(签名)。
Header:记录令牌类型、签名算法等 例如:{“alg":"HS256","type","JWT}
Payload(有效载荷)作用:携带一些用户信息 例如{"userId":"1","username":"mingzi"};需要注意的是jwt看似是十分复杂的密码,其实可以非常轻松的被破解。所以Payload中存放的用户信息不可以涉及到隐私,比如密码或者手机号等等
Signature(签名)作用:防止JWT被篡改、确保安全性 例如 计算出来的签名,一个字符串
【补充】在我看来JWT其实就是一种类型的token,所以在百度其他问题的时候遇到说token的,不需要发懵,可以把它们两个理解成一类东西
2、JWT的作用
了解了什么是JWT,那它具体是做什么用的呢。其实它的功能也十分简单。网上关于jwt的解释五花八门,而且有的解释非常冗余。其实简单来说jwt就是一串用于验证权限的json串。就好像你要打开一扇上锁的门需要一把钥匙一样,JWT就是那把钥匙。
在日常生活中,我们在浏览网站时就经常会用到JWT。当我们没有登录时,可以进行最基础的浏览,而如果涉及到评论点赞等等功能时,则需要登陆了。这里的登录就相当于为我们的点赞或者评论加上了一个JWT。有了它才能真正意义上的畅通无阻。
3、SpringBoot整合JWT
道理我都懂了,具体操作就不多解释了,直接上代码;
所需依赖:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.5.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Conteoller:
/**
* 生成token
* @param username
* @param password
* @return
*/
@GetMapping("/gg")
public Result gg(String username, String password){
return jwtService.gg(username,password);
}
Service和Impl:
Result gg(String username, String password);
/**
* 测试token
*
* @param username
* @param password
* @return
*/
@Override
public Result gg(String username, String password) {
UserAo gg = jwtMapper.gg(username, password);
if (Objects.isNull(gg)) {
return new Result(400, false, "失败");
}
Map<String, String> map = new HashMap<>();
//token的Payload部分
map.put(username, gg.getUsername());
String token = JwtUtils.getToken(map);
return new Result(200, true, token);
}
Mapper和sql.xml
UserAo gg(String username, String password);
<select id="gg" resultType="com.neusoft.pojo.Ao.UserAo">
select *
FROM user
where username = #{username} and password = #{password}
</select>
Result统一响应格式:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {
private Integer code;
private Boolean bool;
private Object msg;
}
拦截器:
准确的说,拦截器就是之前所说的门,只有携带JWT或者指定被放行的api才可以通过
/**
* 注册拦截器
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
//拦截
.addPathPatterns("/**")
//放行
.excludePathPatterns("/newUser","/ll","/aa","/gg","/sclogin","/async","/openexe");
}
}
jwt的校验配置
/**
* 配置文件
*/
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Map<String, Object> map = new HashMap<>();
//获取请求头中的令牌
String token = request.getHeader("token");
try {
//验证令牌
DecodedJWT verify = JwtUtils.verify(token);
return true;
} catch (SignatureVerificationException e){
e.printStackTrace();
map.put("msg","无效签名");
} catch (TokenExpiredException e){
e.printStackTrace();
map.put("msg","token过期");
} catch (AlgorithmMismatchException e){
e.printStackTrace();
map.put("msg","token算法不一致");
} catch (Exception e){
e.printStackTrace();
map.put("msg","token无效");
}
map.put("state","flase");
//将map转为json
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
}
JWT工具类
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);
}
}
具体需要的权限可以自己重新配置,这里就不详细说明只简单的提一下思路,可以在数据库新建一个字段,里面加上对应的key和value。校验权限的时候取出来转成json看看对应的权限是否存在。