jwt 全称Json web token,翻译为网络中基于JSON传输的一种token。该token是无状态的,特别适合于分布式场景。
jwt的相关介绍,这里不再赘述。理论需要实践来验证,但又抽象于实践。两者相辅相成,jwt的相关理论定义,有的作者已经总结的很到位了,这里主要总结如何快速将jwt整合进springboot。
首先,老样子,引入依赖jar:
<!-- JWT依赖 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
添加请求拦截器WebConfig(实现WebMvcConfigurer重写addInterceptors),对请求url进行token认证
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
private JwtFilter jwtFilter ;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtFilter).addPathPatterns("/**");
}
}
新增拦截器JwtFilter
@Component
public class JwtFilter extends HandlerInterceptorAdapter {
public static final String LOGIN_URL = "/login";
@Resource
private JwtTokenUtil jwtTokenUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws SignatureException {
String uri = request.getRequestURI();
if(uri.contains(LOGIN_URL) || uri.contains("/doc.html") || uri.contains("/swagger-resources") ){
return true;
}
//获取token
String token = request.getHeader(jwtTokenUtil.header);
if(StringUtils.isEmpty(token)){
token = request.getParameter(jwtTokenUtil.header);
}
if(StringUtils.isEmpty(token)){
throw new SignatureException(jwtTokenUtil.header+"不能为空");
}
//判断token是否超时
Claims claims = jwtTokenUtil.getTokenClaim(token);
if(null == claims || jwtTokenUtil.isTokenExpired(claims.getExpiration())){
throw new SignatureException(jwtTokenUtil.header+"失效,请重新登录");
}
return true;
}
}
异常处理类,springAop实现(异常通知)
@RestControllerAdvice
public class SecurityExceptionHandler {
@ExceptionHandler(value = {SignatureException.class})
public Result authorizationException(SignatureException e){
return Result.failedWith(null,CodeEnum.FORBBIDEN.getCode(),"权限不足");
}
}
tokenUtil工具类
@Component
public class JwtTokenUtil {
@Value("${jwt.secret}")
public String secret;
@Value("${jwt.expire}")
public int expire;
@Value("${jwt.header}")
public String header;
/**
* 生成token
* @param subject
* @return
*/
public String createToken (String subject){
Date nowDate = new Date();
Date expireDate = new Date(nowDate.getTime() + expire * 1000);
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setSubject(subject)
.setIssuedAt(nowDate)
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 获取token中注册信息
* @param token
* @return
*/
public Claims getTokenClaim (String token) {
try {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}catch (Exception e){
return null;
}
}
/**
* 验证token是否过期失效
* @param expirationTime
* @return
*/
public boolean isTokenExpired (Date expirationTime) {
return expirationTime.before(new Date());
}
/**
* 获取token失效时间
* @param token
* @return
*/
public Date getExpirationDateFromToken(String token) {
return getTokenClaim(token).getExpiration();
}
/**
* 获取用户名从token中
*/
public String getUsernameFromToken(String token) {
return getTokenClaim(token).getSubject();
}
/**
* 获取jwt发布时间
*/
public Date getIssuedAtDateFromToken(String token) {
return getTokenClaim(token).getIssuedAt();
}
}
类中使用配置添加,application.yml中增加token的有效时间等
jwt:
# 加密密钥
secret: abcdefg1234567
# token有效时长
expire: 3600
# header 名称
header: token
至此,我们的jwt相关的引入配置工作都基本完成。下面我们要对jwt相关的验证进行使用:
登录,获取jwt授权生成token,这里验证用户名和密码的工作我们暂时搁置(后面引入springsecurity来做这项工作)
jwt生成token使用
@Resource
JwtTokenUtil jwtTokenUtil;
@Override
public String login(String userName, String password) {
//验证用户名密码
......
//生成token
return jwtTokenUtil.createToken("admin");
}
其他的接口我们还是沿用之前的查询接口。
按照以前没有加入jwt认证的方式去调用下用户详情接口(不加token请求),我们就会发现下面的情况: image.png请求被拒绝了,提示权限不足。。。
登录成功后将token放入header中,再次调用用户详情接口,bingo,成功啦!!! 将返回的token放入用户详情接口header中,再次请求: image.png
至此,jwt的配置和使用我们就已经实操一遍了。
网友评论