springBoot搭建JWT
一.登录方法
1.登录方法可以在验证成功后保存用户信息,角色权限等
@RequestMapping("/login")
public Result login(String userName,String passWord){
String jwt = "";
User user = userService.findUserByUsername(userName);
if (null != user){
List<Role> roles = userService.findRoleByUsername(user.getUsername());
StringBuilder sb = new StringBuilder();
for (Role role : roles) {
sb.append(role.getName());
}
Map<String,Object> map = new HashMap<>();
map.put("roles",sb);
map.put("userName",user.getUsername());
jwt = jwtUtils.createJwt(String.valueOf(user.getId()), user.getUsername(), map);
return new Result(ResultCode.SUCCESS,jwt);
}else{
return new Result(ResultCode.MOBILEORPASSWORDERROR);
}
}
二.JWT工具类
@Getter
@Setter
@ConfigurationProperties("jwt.config")
public class JwtUtils {
//签名私钥
private String key;
//签名的失效时间
private Long ttl;
/**
* 设置token
* @param id 登录用户id
* @param name 登录用户名
* @param map
* @return
*/
public String createJwt(String id, String name, Map<String,Object> map){
//设置失效时间
long now = System.currentTimeMillis();
long exp = now + ttl;
//创建 jwtBuilder
JwtBuilder jwtBuilder = Jwts.builder()
.setId(id)
.setSubject(name)
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256,key);
//3.根据map设置claims
for (Map.Entry<String,Object> entry : map.entrySet()){
jwtBuilder.claim(entry.getKey(),entry.getValue());
}
jwtBuilder.setExpiration(new Date(exp));
String token = jwtBuilder.compact();
return token;
}
public Claims parseJwt(String token){
Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
return claims;
}
}
三.自定义拦截器获取token并验证token
关于自定义拦截器
定义拦截器,只需要实现 HandlerInterceptor 接口,HandlerInterceptor 接口是所有自定义拦截
器或者 Spring Boot 提供的拦截器的鼻祖,所以,首先来了解下该接口。该接口中有三个方法:
preHandle(……) 、 postHandle(……) 和 afterCompletion(……) 。
1:preHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某
个方法,且在这个方法执行之前。所以 preHandle(……) 方法可以决定是否将请求放行,这是通
过返回值来决定的,返回 true 则放行,返回 false 则不会向后执行。
2:postHandle(……) 方法:该方法的执行时机是,当某个 url 已经匹配到对应的 Controller 中的某
个方法,且在执行完了该方法,但是在 DispatcherServlet 视图渲染之前。所以在这个方法中有
个 ModelAndView 参数,可以在此做一些修改动作。
3:afterCompletion(……) 方法:顾名思义,该方法是在整个请求处理完成后(包括视图渲染)执
行,这时做一些资源的清理工作,这个方法只有在 preHandle(……) 被成功执行后并且返回 true
才会被执行。
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Resource
private JwtUtils jwtUtils;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1.通过request获取请求token信息
String authorization = request.getHeader("Authorization");
//判断请求头信息是否为空,或者是否已Bearer开头
if (!StringUtils.isEmpty(authorization) && authorization.startsWith("Bearer")){
//获取token数据
String token = authorization.replace("Bearer ","");
//解析token获取claims
Claims claims = jwtUtils.parseJwt(token);
if(claims != null) {
String roles = (String) claims.get("roles");
if (roles.contains("ADMIN")){
request.setAttribute("user_claims",claims);
return true;
}
}
}
throw new CommonException(ResultCode.UNAUTHENTICATED);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
四.配置拦截器
@Configuration
public class MyJwtInterceptorConfig implements WebMvcConfigurer {
@Resource
private JwtInterceptor jwtInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 实现WebMvcConfigurer不会导致静态资源被拦截
registry.addInterceptor(jwtInterceptor).addPathPatterns("/**")
.excludePathPatterns("/sys/login","/frame/register/**");
}
}
数据库
码云