当前位置: 首页 > article >正文

基于 Spring 的自定义注解和请求拦截器实现认证机制

基于 Spring 的自定义注解和请求拦截器实现认证机制

  • 一、基于 Spring 的自定义注解和请求拦截器实现认证机制
    • 1. 背景
    • 2. 业务场景
    • 3. 核心实现
      • 3.1 定义自定义注解 `@IgnoreAuth`
      • 3.2 定义请求拦截器 `AuthInterceptor`
      • 3.3 配置拦截器
      • 3.4 登录接口
    • 4. 小结


一、基于 Spring 的自定义注解和请求拦截器实现认证机制

在现代 Web 开发中,用户认证与权限控制是确保应用安全的重要环节。为了简化和统一用户身份验证,很多系统会在请求处理链中引入认证中间件,确保每个请求都经过适当的身份验证。本文将通过一个基于 Spring 框架的实现例子,介绍如何使用自定义注解和请求拦截器来完成认证机制。

1. 背景

随着 Web 应用的复杂性增加,接口的访问权限管理也变得越来越重要。在传统的身份验证中,用户通常会提交用户名和密码,服务器通过验证这些信息来识别用户身份。然而,随着前后端分离架构的流行,接口认证(如 JWT)逐渐成为一种常见的认证方式。为了增强开发的灵活性和可维护性,我们可以通过自定义注解来简化认证逻辑。

在这篇文章中,我们将通过一个具体例子,展示如何使用 Spring 的拦截器和自定义注解来实现认证机制,并控制接口的访问权限。

2. 业务场景

假设我们有一个 Web 应用,用户可以通过提交用户名和密码来登录。如果验证成功,系统将返回一个 Token,前端应用会将 Token 存储起来,在后续的请求中通过 HTTP 请求头携带该 Token。对于需要认证的接口,系统需要验证请求中的 Token 是否有效。

同时,某些接口,如用户注册接口、文件上传接口等,不需要身份认证,可以通过一个自定义注解来标识这些接口。

3. 核心实现

3.1 定义自定义注解 @IgnoreAuth

首先,我们需要定义一个自定义注解,用于标识那些不需要认证的接口。这些接口可以直接放行,无需进行 Token 验证。

@Target(ElementType.METHOD) // 注解作用在方法上
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
@Documented
public @interface IgnoreAuth {
}
  • @Target(ElementType.METHOD):该注解仅能应用于方法上。
  • @Retention(RetentionPolicy.RUNTIME):表示该注解会在运行时保留,可以通过反射机制获取。
  • @Documented:表示该注解会出现在 Javadoc 中。

3.2 定义请求拦截器 AuthInterceptor

接下来,我们实现一个请求拦截器 AuthInterceptor,该拦截器会在请求处理之前执行,检查请求是否需要认证。

public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取请求路径
        String servletPath = request.getServletPath();

        // 放行不需要认证的路径
        if ("/dictionary/page".equals(servletPath) || "/file/upload".equals(servletPath) || "/yonghu/register".equals(servletPath)) {
            return true;
        }

        // 跨域配置
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Token, Origin, Content-Type, Accept, Authorization");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

        // 判断方法是否有 @IgnoreAuth 注解,如果有则跳过认证
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            IgnoreAuth annotation = handlerMethod.getMethodAnnotation(IgnoreAuth.class);
            if (annotation != null) {
                return true; // 如果有 @IgnoreAuth 注解,直接放行
            }
        }

        // 执行 Token 验证(假设我们有一个 TokenService 处理此逻辑)
        String token = request.getHeader("Token");
        if (token == null || !tokenService.validateToken(token)) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 返回未授权状态
            response.getWriter().write("Unauthorized access");
            return false; // 认证失败,拦截请求
        }

        // 认证通过,继续执行请求
        return true;
    }
}

在上面的 AuthInterceptor 中:

  • 我们首先检查请求的路径是否属于不需要认证的接口。如果是,则直接放行。
  • 如果请求的路径需要认证,拦截器会通过 Token 进行身份验证。如果 Token 验证失败,返回 401 状态码(未授权)。
  • 另外,我们还为跨域请求设置了相关的响应头,确保支持跨域资源共享(CORS)。

3.3 配置拦截器

要使拦截器生效,我们需要将其注册到 Spring MVC 的拦截器链中。

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor)
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/login", "/yonghu/register", "/file/upload"); // 排除登录、注册等接口
    }
}

WebConfig 类中,我们通过实现 WebMvcConfigurer 接口,注册了 AuthInterceptor 拦截器,并指定了拦截的路径(这里是所有路径 /**),并排除了登录、注册、文件上传等不需要认证的接口。

3.4 登录接口

假设我们有一个登录接口,用户通过用户名和密码进行登录。登录成功后,我们为用户生成一个 Token,并返回给前端。

@RestController
public class AuthController {

    @Autowired
    private UsersService usersService;

    @Autowired
    private TokenService tokenService;

    @PostMapping("/login")
    public R login(@RequestParam String username, @RequestParam String password) {
        // 验证用户信息
        UsersEntity user = usersService.findByUsername(username);
        if (user == null || !user.getPassword().equals(password)) {
            return R.error("Invalid username or password");
        }

        // 生成 Token
        String token = tokenService.generateToken(user.getId(), user.getUsername());
        return R.ok().put("token", token);
    }
}

login 方法中,用户提交用户名和密码后,我们查询用户信息,如果验证成功,则生成一个 Token,并将其返回给前端。

4. 小结

在本文中,我们通过一个具体的例子展示了如何在 Spring 应用中使用自定义注解和请求拦截器实现认证机制。主要的步骤包括:

  1. 使用 @IgnoreAuth 注解标识不需要认证的接口。
  2. 使用 AuthInterceptor 拦截器,在请求到达控制器之前检查 Token 是否有效。
  3. 配置拦截器生效的路径。
  4. 实现登录接口,并为用户生成 Token。

通过这种方式,我们可以轻松地管理和扩展应用中的认证机制,确保系统的安全性。


http://www.kler.cn/a/468731.html

相关文章:

  • Windows 11 上通过 WSL (Windows Subsystem for Linux) 安装 MySQL 8
  • 安卓漏洞学习(十六):unicorn在逆向中的使用
  • 用opencv实现像素统计
  • 【C++】P2550 [AHOI2001] 彩票摇奖
  • 后台管理系统动态面包屑Breadcrumb组件的实现
  • npm install --global windows-build-tools --save 失败
  • Win32汇编学习笔记05
  • 直接插入排序、折半插入排序、2路插入排序、希尔排序
  • C++软件设计模式之备忘录模式
  • “智能筛查新助手:AI智能筛查分析软件系统如何改变我们的生活
  • 实习第一周笔记
  • Scala 访问修饰符
  • Qt之FFmpeg播放器设计(十七)
  • Kotlin 面向对象与函数式编程
  • 飞书企业消息实践
  • Eclipse 首选项(Preferences)
  • Spring MVC实战指南:构建高效Web应用的架构与技巧(三)
  • C++26 函数契约(Contract)概览
  • 计算机网络 —— 网络编程(TCP)
  • 基于Web的足球青训俱乐部管理后台系统的设计与开发源码(springboot+mysql+vue)
  • JAVA开发中 MyBatis XML 映射文件 的作用
  • LabVIEW语言学习过程是什么?
  • 轻量级通信协议 JSON-RPC 2.0 详解
  • GraalVM:云原生时代的Java虚拟机
  • QPainter
  • 从零开始学TiDB(8) TiFlash 主要架构