前一段给大家分享了下 关于jwt的生成以及使用,今天抽点时间把完整版的给大家分享出来
话不多说直接上代码 ,关于抛出的异常是我自定义的全局捕获,小伙伴们可以不用管它
1.定义一个java Baen 把它交给spring容器去使用,这样在任何地方就可以注入获取登录后的用户ID和名称了 scope 最简单的理解就是单例
@Component
@Scope(scopeName = "request",proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AuthToken implements Serializable {
private Integer adminId;
private String userName;
}
2.修改JwtUtis工具类
private static final String TOKEN_PREFIX = "Bearer-";
JwtBuilder jwtBuilder = Jwts.builder();
jwtBuilder.setId(id); //唯一ID
jwtBuilder.setSubject(subject); //主题信息
jwtBuilder.setIssuer(ISSUER); //签发者
jwtBuilder.setIssuedAt(date); //签发时间
jwtBuilder.setExpiration(expDate); //过期时间
jwtBuilder.signWith(signatureAlgorithm, secretKey); //算法及签名秘钥
return TOKEN_PREFIX + jwtBuilder.compact();
3.解析令牌
public static Claims parseJWT(String jwt){
try{
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}catch (SignatureException exception){
throw new BusinessException(AuthEnum.INVALID_TOKEN.getErrorCode(), AuthEnum.INVALID_TOKEN.getErrorMsg());
}
}
所有的请求必须都带token才能请求 实现拦截器和忽略掉不用token可以请求的方法。比如说登录,注册
4.自定义拦截器bean
@Component
public class JWTInterceptor extends HandlerInterceptorAdapter {
@Autowired
private AuthToken authToken;
/**
*简化获取token数据的代码编写(判断是否登录)
* 1.通过request获取请求token信息
* 2.从token中解析获取claims
* 3.将claims绑定到request域中
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//预请求直接通行
if("OPTIONS".equals(request.getMethod())){
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
//从头部获取token
String authorization = request.getHeader("Authorization");
if (StringUtils.isEmpty(authorization)){
throw new BusinessException(AuthEnum.NO_AUTH.getErrorCode(),AuthEnum.NO_AUTH.getErrorMsg());
}
//去掉token头部,获取完整的jwt信息
String token = authorization.substring(authorization.indexOf("-") + 1);
try{
Claims claims = JwtUtil.parseJWT(token);
if (claims.isEmpty()){
throw new BusinessException(AuthEnum.INVALID_TOKEN.getErrorCode(),AuthEnum.INVALID_TOKEN.getErrorMsg());
}
Map map = JSON.parseObject(claims.getSubject(), Map.class);
//过期时间
long time = claims.getExpiration().getTime();
//当前时间
long currentTimeMillis = System.currentTimeMillis();
if (time < currentTimeMillis){
throw new BusinessException(AuthEnum.EXP_TOKEN.getErrorCode(),AuthEnum.EXP_TOKEN.getErrorMsg());
}
String userName = map.get("username").toString();
Integer userId = (Integer) map.get("user_id");
if (StringUtils.isEmpty(userName)){
throw new BusinessException(AuthEnum.INVALID_TOKEN.getErrorCode(),AuthEnum.INVALID_TOKEN.getErrorMsg());
}
//存储用户信息
authToken.setAdminId(userId);
authToken.setUserName(userName);
// request.setAttribute("currentUser", authToken);
return true;
}catch (ExpiredJwtException e){
System.out.println("Token 以过期");
throw new BusinessException(AuthEnum.EXP_TOKEN.getErrorCode(),AuthEnum.EXP_TOKEN.getErrorMsg());
}
}
}
至于request.setAttribute("currentUser", authToken) 这是另一种获取当前用户信息的方法 不方便就不给大家演示了
5.配置拦截器加入spring容器
@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {
@Autowired
JWTInterceptor jwtInterceptor;
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor).addPathPatterns("/**").
//设置不拦截的请求地址"/register/**
excludePathPatterns("/authorization/user/login");
}
}
excludePathPatterns 就是过滤不拦截的请求,如果有多个就用,逗号隔开就好了
只需要这样就OK了,比如说在添加数据的时候需要获取当前的操作人 ,这个时候就很方便了 只需要在任何想用的时候注入就可以了
@Autowired
private AuthToken authToken