美文网首页springboot
springboot系列——整合jwt

springboot系列——整合jwt

作者: Caooz | 来源:发表于2020-10-14 21:47 被阅读0次

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

请求被拒绝了,提示权限不足。。。

调用用户登录接口进行访问: image.png
登录成功后将token放入header中,再次调用用户详情接口,bingo,成功啦!!! 将返回的token放入用户详情接口header中,再次请求: image.png

至此,jwt的配置和使用我们就已经实操一遍了。

相关文章

网友评论

    本文标题:springboot系列——整合jwt

    本文链接:https://www.haomeiwen.com/subject/zzqgpktx.html