SpringBoot通过拦截器和JWT令牌实现登录验证

简介: 该文介绍了JWT工具类、匿名访问注解、JWT验证拦截器的实现以及拦截器注册。使用`java-jwt`库生成和验证JWT,JwtUtil类包含generateToken和verifyToken方法。自定义注解`@AllowAnon`允许接口匿名访问。JwtInterceptor在Spring MVC中拦截请求,检查JWT令牌有效性。InterceptorConfig配置拦截器,注册并设定拦截与排除规则。UserController示例展示了注册、登录(允许匿名)和需要验证的用户详情接口。

1. Jwt 工具类

引入依赖

<dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
  <version>4.4.0</version>
</dependency>
AI 代码解读

JwtUtil 类包含了两个静态方法:generateToken() 用于生成 JWT,verifyToken() 用于验证 JWT

public class JwtUtil {
   

    //密钥
    private static final String SECRET_KEY = "xxxxxxxxx";

    // 过期时间60分钟
    private static final long EXPIRE_TIME = 60 * 60 * 1000;

    /**
     * 生成签名
     *
     * @param claims
     * @return
     */
    public static String generateToken(Map<String, Object> claims) {
   

        var jwtBuilder = JWT.create();

        // 设置传入的字典中的声明
        for (Map.Entry<String, Object> entry : claims.entrySet()) {
   
            jwtBuilder.withClaim(entry.getKey(), entry.getValue().toString());
        }

        //过期时间
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);

        Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);
        return jwtBuilder.withExpiresAt(date).sign(algorithm);


    }

    /**
     * 校验token是否正确
     *
     * @param token
     * @return
     */
    public static boolean verifyToken(String token) {
   
        try {
   
            if (token.startsWith("Bearer ")) {
   
                token = token.replace("Bearer ", "");
                return false;
            }

            Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);
            DecodedJWT jwt = JWT.require(algorithm)
                    .build()
                    .verify(token);
            return true;
        } catch (Exception exception) {
   
            return false;
        }
    }

    /**
     * 获得token中的用户信息(无需secret解密也能获得)
     *
     * @param token
     * @return
     */
    public static String getUsername(String token) {
   
        try {
   
            if (token.startsWith("Bearer ")) {
   
                token = token.replace("Bearer ", "");
            }
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("userName").asString();
        } catch (JWTDecodeException e) {
   
            return null;
        }
    }
}
AI 代码解读

2. 匿名访问注解

自定义匿名访问注解,接口添加该注解,则跳过Jwt权限验证。

/**
 * 自定义注解
 * 允许匿名访问
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowAnon {
   
    boolean required() default true;
}
AI 代码解读

3. Jwt验证拦截器


public class JwtInterceptor implements HandlerInterceptor {
   

    /**
     * 在请求处理之前进行调用(Controller方法调用之前)
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws IOException
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
   

        System.out.println("Jwt Interceptor preHandle");

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        //检查有没有允许匿名访问的注解
        if (method.isAnnotationPresent(AllowAnon.class)) {
   
            AllowAnon allowAnon = method.getAnnotation(AllowAnon.class);
            if (allowAnon.required()) {
   
                //允许匿名访问(无需权限)
                return true;
            }
        }

        String authorizationHeader = request.getHeader("Authorization");
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
   
            ResponseErrorMessage(response);
            return false;
        }
        String token = authorizationHeader.substring(7);
        try {
   
            //验证token
            if (JwtUtil.verifyToken(token)) {
   
                //验证成功
                return true;
            } else {
   
                //验证失败
                ResponseErrorMessage(response);
                return false;
            }
        } catch (Exception e) {
   
            ResponseErrorMessage(response);
            return false;
        }
    }

    /**
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     * preHandle方法处理之后这个方法会被调用,如果控制器Controller出现了异常,则不会执行此方法
     *
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
   
        System.out.println("Jwt Interceptor postHandle");
    }

    /**
     * 不管有没有异常,这个afterCompletion都会被调用
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
   
        System.out.println("Jwt Interceptor afterCompletion");
    }

    /**
     * 响应错误消息
     *
     * @param response
     * @throws IOException
     */
    private void ResponseErrorMessage(HttpServletResponse response) throws IOException {
   
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("application/json; charset=UTF-8");
        response.getWriter().write("{\"success\":false,\"message\":\"授权失败\",\"data\":null}");
    }
}
AI 代码解读

4. 注册拦截器


//注册拦截器配置
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
   

    /**
     * 重写addInterceptors()实现拦截器
     * 配置:要拦截的路径以及不拦截的路径
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
   

        System.out.println("InterceptorConfig addInterceptors");

        registry.addInterceptor(jwtInterceptor())  //配置拦截规则
                .addPathPatterns("/api/**")  // 拦截所有请求,通过判断token是否合法来决定是否需要登录
                .excludePathPatterns(
                        "/api/user/register"  //注册
                );//允许匿名访问放行的请求
    }

    @Bean
    public JwtInterceptor jwtInterceptor() {
   
        return new JwtInterceptor();
    }
}
AI 代码解读

5. 控制器

@RestController
@RequestMapping("/api/user")
public class UserController {
   

    /**
     * 注册(无需jwt验证,InterceptorConfig定义排除JwtInterceptor验证路由)
     *
     * @return
     */
    @PostMapping("register")
    public String register() {
   
        return "注册成功";
    }

    /**
     * 登录(无需jwt验证,添加AllowAnon允许匿名访问注解)
     *
     * @return
     */
    @AllowAnon
    @PostMapping("login")
    public String login() {
   
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", "9");
        claims.put("userName", "usernine");

        //生成token
        var token = JwtUtil.generateToken(claims);

        return token;
    }

    /**
     * 详情(需要验证)
     *
     * @return
     */
    @GetMapping("detail")
    public void getUserDetail(@RequestHeader("Authorization") String token) {
   
        //获取当前用户名
        var username = JwtUtil.getUsername(token);
    }
}
AI 代码解读
kouver
+关注
目录
打赏
0
2
1
0
18
分享
相关文章
什么是JWT?如何使用Spring Boot Security实现它?
什么是JWT?如何使用Spring Boot Security实现它?
1324 5
什么是用于REST API的JWT Bearer令牌以及如何通过代码和工具进行调试
在Web开发中,保护REST API至关重要,而JSON Web令牌(JWT)特别是JWT Bearer令牌,是一种高效方法。它通过紧凑、自包含的结构实现安全信息交换,提升用户体验。本文探讨JWT Bearer的基本概念、结构与实现,包括在Java中的应用步骤,以及使用Apipost和cURL进行测试的方法。JWT优势明显:无状态、互操作性强,适用于分布式系统。掌握JWT Bearer,可助开发者构建更安全、高效的API解决方案。
SpringBoot集成Shiro权限+Jwt认证
本文主要描述如何快速基于SpringBoot 2.5.X版本集成Shiro+JWT框架,让大家快速实现无状态登陆和接口权限认证主体框架,具体业务细节未实现,大家按照实际项目补充。
386 11
|
8月前
|
Spring Boot 应用如何实现 JWT 认证?
Spring Boot 应用如何实现 JWT 认证?
226 8
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
193 0
SpringBoot 手写拦截器
如何手写一个拦截器呢。假设我现在需要一个计时拦截器,我想把每一次调用服务锁花费的时间打印到控制台,我该怎么做呢? 拦截机制有三种: 1. 过滤器(Filter)能拿到http请求,但是拿不到处理请求方法的信息。
1529 0
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
250 1
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
285 7
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
240 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问