Java:关于拦截器以及JWT令牌的使用

1.JWT工具包

public class JwtUtil {

    /**
     * secretKey jwt秘钥
     */
    private static String secretKey="123456";

    /**
     * ttlMillis jwt过期时间(毫秒)
     * 设置有效期1天
     */
    private static long ttlMillis=1000*3600*24;

    /**
     * 指定令牌名称,前端需要在请求头中携带tokenName
     */
    public static String tokenName="token";
    /**
     * 生成jwt
     * 使用Hs256算法, 私匙使用固定秘钥   此秘钥一定要保留好在服务端, 不能暴露出去, 否则sign就可以被伪造, 如果对接多个客户端建议改造成多个
     * @param claims    设置的信息
     */

    public static String createJWT( Map<String, Object> claims) {
        // 指定签名的时候使用的签名算法,也就是header那部分
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        // 生成JWT的时间
        //System.currentTimeMillis():这是 Java 中用于获取当前时间的方法
        long expMillis = System.currentTimeMillis() + ttlMillis;
        Date exp = new Date(expMillis);

        // 设置jwt的body
        JwtBuilder builder = Jwts.builder()
                // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setClaims(claims)
                // 设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm,secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置过期时间
                .setExpiration(exp);

        return builder.compact();
    }

    /**
     * Token解密
     * @param token     加密后的token
     */
    public static Claims parseJWT(String token) {
        // 得到DefaultJwtParser
        Claims claims = Jwts.parser()
                // 设置签名的秘钥
                .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                // 设置需要解析的jwt
                .parseClaimsJws(token).getBody();
        return claims;
    }

}

2.创建拦截器

@Component
public class JwtInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断当前拦截到的是Controller的方法还是其他资源
        if(!(handler instanceof HandlerMethod)){
            //当前拦截的不是动态方法,直接放行
            return true;
        }

        //从请求头获取令牌
        String token=request.getHeader(JwtUtil.tokenName);
        try {
            //判断是否携带令牌
            if (StringUtils.isEmpty(token)){
                throw new Exception("未携带JWT令牌");
            }
            //判断令牌是否有效
            if (JwtUtil.parseJWT(token)==null){
                throw new Exception("JWT令牌有误");
            }
        }catch (Exception e){
            //出现异常,拦截,设置状态码为401
            response.setStatus(401);
            return false;
        }

        Map<String,Object> map=JwtUtil.parseJWT(token);
        Object id = map.get("id");
        LocalStorageUtil.set(id);
        return true;

    }
}

3.配置JWT拦截器,将拦截器交给WebMVC

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Autowired
    private JwtInterceptor jwtInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                //设置不拦截的请求路径,如登录接口不需要拦截等
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/register")
                //我使用了Knife4j测试文档,如果你没使用,可以不配置下面这行
                .excludePathPatterns("/doc.html","/swagger-resources");
    }

}

4.登录注册

@Autowired
private UserMapper userMapper;
@Override
public void register(String username, String password) {
    //配置查询条件
    //利用Wrapper来创建查找条件,来查找username,并复制给user,不管是null还是有实参
    User user=userMapper.selectOne(new LambdaQueryWrapper<User>()
            .eq(User::getUsername,username)
    );
    
    //然后判断是否为空,是否存在
    if(!Objects.isNull(user)){
        throw new RuntimeException("用户名已经存在");
    }

    //如果为空,重新new一个user对象,然后将注册的username和password赋值给user对象
    user=new User();
    user.setUsername(username);
    user.setPassword(password);
    user.setCreateTime(LocalDateTime.now());
    user.setUpdateTime(LocalDateTime.now());

    //最后将新的user添加进去
    userMapper.insert(user);
}

@Override
public String sigin(String username, String password) {
    if(Objects.isNull(username) || Objects.isNull(password)){
        throw new RuntimeException("账户或密码不能为空");
    }

    //配置查询条件
    LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<User>()
            .eq(User::getUsername,username)
            .eq(User::getPassword,password);
    User user = userMapper.selectOne(lambdaQueryWrapper);

    if(Objects.isNull(user)){
        throw new RuntimeException("用户账号或密码错误");
    }

    //登录成功,生成JWT令牌
    Map<String,Object> map=new HashMap<>();
    map.put("id",user.getId());
    String jwt = JwtUtil.createJWT(map);

    return jwt;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值