Spring boot 项目(八)——自定义拦截器

Jwt简介

1、Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。
2、JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
3、JWT生成的token是无状态的,服务端不存储,即一旦生成在有效期之前一直可用,无法销毁。
4、如果需要刷新token有效期或者提前失效需要借助缓存、数据库或者redis来自己实现对应逻辑

操作流程

1、新建JwtUtil类

public class JwtUtil {

    //过期时间 30min
    private static final int EXPIRE_TIME = 30;
    //私钥
    private static final String TOKEN_SECRET = "privateKey";
    private static final String USER_NAME = "name";

    /**
     *      签发对象:这个用户的id
     *      签发时间:现在
     *      有效时间:30分钟
     *      载荷内容:暂时设计为:这个人的名字
     *      加密密钥:这个人的id加上一串字符串
     */
    public static String createToken(Long userId, String userName) {
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.MINUTE,EXPIRE_TIME);
        Date expiresDate = nowTime.getTime();

        String token= JWT.create().withAudience(userId+"")   //签发对象
                .withIssuedAt(new Date())    //发行时间
                .withExpiresAt(expiresDate)  //有效时间
                .withClaim(USER_NAME, userName)    //载荷,随便写几个都可以
                .sign(Algorithm.HMAC256(userId+TOKEN_SECRET));   //加密
        return token;
    }
    /**
     * 检验合法性,其中secret参数就应该传入的是用户的id
     */
    public static boolean verifyToken(String token, String secret) {
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret+TOKEN_SECRET)).build();
            verifier.verify(token);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 获取签发对象
     */
    public static String getAudience(String token) throws Exception {
        String audience = null;
        try {
            audience = JWT.decode(token).getAudience().get(0);
        } catch (JWTDecodeException j) {
            //这里是token解析失败

        }
        return audience;
    }

2、新建WebMvcConfig文件

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册自定义拦截器
        registry.addInterceptor(loginInterceptor())
                .addPathPatterns("/**")
                // 那些路径不拦截
                .excludePathPatterns("/login/**","/error"
                        ,"/swagger-ui.html/**","/swagger-resources/**");
    }
    @Bean
    public LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }
}

3、新建NoNeedToken注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoNeedToken {

}

4、新建LoginInterceptor文件

public class LoginInterceptor implements HandlerInterceptor {

    protected Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private SysUserService sysUserService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");

        logger.info("已进入拦截器,当前访问地址为:" + request.getRequestURI());


        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //检查是否有NoNeedToken注释,有则跳过认证
        if (method.isAnnotationPresent(NoNeedToken.class)) {
            return true;
        } else {
            if (token == null) {
                logger.warn("登录失效");
                return false;
            }
            String userId = JwtUtil.getAudience(token);
            SysUser user = sysUserService.getById(Long.valueOf(userId));
            if (user == null) {
                logger.warn("该用户不存在!");
                return false;
            }
            boolean r = JwtUtil.verifyToken(token, userId);
            if (r){
                logger.info("验证成功");
            }else{
                logger.info("验证失败");
                return false;
            }
            return true;
        }
    }
}

5、在controller层上不需要验证token的方法上添加@NoNeedToken

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

--流星。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值