springboot拦截器过滤token,并返回结果及异常处理操作

yizhihongxing

下面我将为你详细讲解如何使用Spring Boot实现拦截器过滤Token并返回结果及异常处理操作。

什么是拦截器及Token认证

在Spring Boot中,拦截器是一种非常常用的组件,它可以拦截请求,进行一些处理,并执行相应的操作。Token认证是指在用户登录成功后,服务器会生成一个Token并返回给客户端,客户端在以后的请求中携带这个Token用于鉴权,服务器会验证Token的有效性以判断请求是否合法。

前置准备

在使用拦截器过滤Token之前,需要先引入相关的依赖。我们可以在pom.xml文件中添加以下内容:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

其中,spring-boot-starter-web是Spring Boot的Web相关依赖,jjwt是JWT(Java Web Token)的Java实现库,用于Token的生成和校验。

实现拦截器过滤Token

为了实现拦截器过滤Token,我们需要创建一个实现HandlerInterceptor接口的拦截器类,在该类中实现Token的验证和相应的处理逻辑。以下是一个简单的示例:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private TokenConfig tokenConfig;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        String token = request.getHeader("Authorization");
        if (token == null) {
            throw new ApiException("缺少AccessToken");
        }
        Claims claims = Jwts.parser().setSigningKey(tokenConfig.getSecretKey()).parseClaimsJws(token).getBody();
        if (claims == null) {
            throw new ApiException("无效AccessToken");
        }
        // TODO: 进行权限验证
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

其中,TokenConfig是一个封装了Token认证相关配置内容的类;ApiException是一个自定义异常类,用于统一处理异常并返回错误信息。在preHandle方法中,我们首先对OPTIONS请求进行处理,因为它是一个预检请求,不需要进行Token的验证。然后,我们从Authorization请求头中获取Token,如果有Token,就使用jjwt解析出其中的Claims内容,并进行权限验证(这里我们只是简单地验证了Token是否有效),如果验证成功,就返回true;否则,就抛出ApiException异常并返回错误信息。

接下来,我们需要将该拦截器注册到Spring Boot的配置中,这可以通过WebMvcConfigurer接口的实现类来实现。例如:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/**");
    }
}

在该类中,我们先注入了上面实现的拦截器类AuthInterceptor,然后在addInterceptors方法中将其添加到InterceptorRegistry中,并配置需要拦截的路径。在这里,我们配置了所有请求都需要经过AuthInterceptor的处理。

返回结果及异常处理操作

在拦截器中,我们可以通过抛出异常来处理请求过程中的错误。但是,在实际应用中,为了更好地返回错误信息并方便客户端处理,我们需要对异常进行统一的处理,以便将错误信息封装到接口响应体中返回给客户端。

以下是一个实现了接口响应统一格式的示例:

import lombok.Data;

@Data
public class ApiResponse<T> {

    private Integer code;
    private String message;
    private T data;

    public static <T> ApiResponse<T> ok(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(200);
        response.setMessage("OK");
        response.setData(data);
        return response;
    }

    public static <T> ApiResponse<T> error(Integer code, String message) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(code);
        response.setMessage(message);
        response.setData(null);
        return response;
    }
}

在该类中,我们定义了接口响应的统一格式,包括状态码、错误信息和响应数据。我们还添加了两个静态方法,用于构建成功和失败的接口响应。

AuthInterceptor中抛出异常时,我们可以在GlobalExceptionHandler中对其进行捕获和处理,并返回相应的错误信息。以下是一个简单的实现示例:

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(ApiException.class)
    public ApiResponse<Void> handleApiException(ApiException e) {
        log.warn("请求发生异常: {}", e.getMessage());
        return ApiResponse.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ApiResponse<Void> handleException(Exception e) {
        log.error("请求发生异常: ", e);
        return ApiResponse.error(500, "服务内部错误,请稍后重试");
    }
}

在该类中,我们定义了两个异常处理方法,一个是处理ApiException异常,用于捕获AuthInterceptor中抛出的异常并返回错误信息;另一个是处理Exception异常,用于捕获其他未处理的异常,并返回服务内部错误的错误信息。

综合示例

以下是一个完整的示例,其中包含了基于Spring Boot的Token认证和拦截器过滤Token,并对Token认证异常进行了统一处理:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.example.demo.exception.ApiException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/**");
    }
}

@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private TokenConfig tokenConfig;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        String token = request.getHeader("Authorization");
        if (token == null) {
            throw new ApiException("缺少AccessToken");
        }
        Claims claims = Jwts.parser().setSigningKey(tokenConfig.getSecretKey()).parseClaimsJws(token).getBody();
        if (claims == null) {
            throw new ApiException("无效AccessToken");
        }
        // TODO: 进行权限验证
        return true;
    }
}

@Data
public class ApiResponse<T> {

    private Integer code;
    private String message;
    private T data;

    public static <T> ApiResponse<T> ok(T data) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(200);
        response.setMessage("OK");
        response.setData(data);
        return response;
    }

    public static <T> ApiResponse<T> error(Integer code, String message) {
        ApiResponse<T> response = new ApiResponse<>();
        response.setCode(code);
        response.setMessage(message);
        response.setData(null);
        return response;
    }
}

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(ApiException.class)
    public ApiResponse<Void> handleApiException(ApiException e) {
        log.warn("请求发生异常: {}", e.getMessage());
        return ApiResponse.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public ApiResponse<Void> handleException(Exception e) {
        log.error("请求发生异常: ", e);
        return ApiResponse.error(500, "服务内部错误,请稍后重试");
    }
}

public class ApiException extends RuntimeException {

    private Integer code;

    public ApiException(String message) {
        this(message, 400);
    }

    public ApiException(String message, Integer code) {
        super(message);
        this.code = code;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}

@ConfigurationProperties(prefix = "jwt")
@Data
public class TokenConfig {

    private String secretKey;
    private Long expireSeconds;
}

@RestController
@RequestMapping("/api")
public class ApiController {

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public ApiResponse<Void> test() {
        return ApiResponse.ok(null);
    }
}

在这个示例中,TokenConfigGlobalExceptionHandler类分别用于配置Token认证和统一异常处理。我们在WebConfig中将AuthInterceptor注册到了Spring Boot的配置中,并配置其拦截所有请求。在ApiController中,我们实现了一个简单的接口 test,它用于测试接口的响应结果。

到这里,我们已经完成了基于Spring Boot的Token认证和拦截器过滤Token,并对Token认证异常进行了统一处理的实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springboot拦截器过滤token,并返回结果及异常处理操作 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 什么是JVM参数?

    JVM参数是用于控制JVM行为的命令行参数。JVM参数可以分为两大类:标准参数和非标准参数。 标准参数 标准参数指的是JVM规范中定义的参数,它们可以在所有的JVM实现中使用。以下是一些常见的标准参数。 -Xmx 用于设置JVM最大可用内存大小。例如,以下命令行将JVM最大内存设置为2G: java -Xmx2g MyApp -Xms 用于设置JVM初始内存…

    Java 2023年5月10日
    00
  • 从零开始Mybatis连接数据库的方法

    以下是从零开始Mybatis连接数据库的方法的完整攻略: 步骤1:下载并安装Mybatis Mybatis是一个优秀的持久层框架,我们需要先在官网下载最新版本的Mybatis。下载完成后,按照Mybatis的安装说明进行安装。 步骤2:创建数据库 我们需要在数据库中创建一个表,作为Mybatis连接的对象。这里以MySQL为例,使用以下SQL创建一个user…

    Java 2023年5月19日
    00
  • Spring Boot集成Java DSL的实现代码

    Spring Boot集成Java DSL的实现代码的攻略如下: 1. Java DSL简介 Java DSL,全称Java Domain Specific Language,是一种特定领域的编程语言,针对某个特定的领域进行优化,使得编程更简单、更直观、更易读。 2. Spring Boot集成Java DSL实现的前提条件 要实现Spring Boot集成…

    Java 2023年5月20日
    00
  • 对JSP(Java Server Pages)的一些理解

            JSP全名为Java Server Pages,java服务器页面。JSP是一种基于文本的程序,其特点就是HTML和Java代码共同存在!JSP是为了简化Servlet的工作出现的替代品,Servlet输出HTML非常困难,JSP就是替代Servlet输出HTML的。JSP本身就是一种Servlet。为什么我说JSP本身就是一种Servlet…

    Java 2023年4月19日
    00
  • 详解java设计模式之六大原则

    详解Java设计模式之六大原则 在软件开发中,设计模式是一种解决特定问题的经验总结,它提供了一种通用的设计思路,可以使我们在编码时更加高效和准确地解决问题。Java设计模式是指在Java程序开发中应用的一种设计方式,它有六大原则,分别是: 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特原则 开闭原则 本文将详细讲解这六大原则。 单一职责原则 …

    Java 2023年5月26日
    00
  • Java与Http协议的详细介绍

    一、Java与HTTP协议的介绍 HTTP协议是一种应用层协议,它是在Web的基础上发展起来的。Java作为一种编程语言,可以通过使用Java的网络库来实现HTTP协议的通信。 Java提供了许多网络相关的库,其中包括: URL和URLConnection:用于向服务器发送HTTP请求并接收响应。 HttpClient库:是开源的第三方库,提供了更多的功能和…

    Java 2023年6月15日
    00
  • SpringMVC KindEditor在线编辑器之文件上传代码实例

    下面我就针对“SpringMVC KindEditor在线编辑器之文件上传代码实例”的完整攻略进行详细的讲解: 具体操作步骤 步骤一:引入相关依赖 在SpringMVC项目的pom.xml文件中加入以下代码: <!– 文件上传依赖 –> <dependency> <groupId>commons-fileupload&…

    Java 2023年6月2日
    00
  • 详解Java中String类的各种用法

    我来为大家详细讲解Java中String类的各种用法。 String类简介 String类是Java程序中最常用的类之一,用于表示字符串类型的数据。在Java中,字符串是以双引号”包围的一组字符序列。 在Java中,String类属于不可变类,一旦创建了一个String对象,它的值就无法被修改。这意味着,当我们对一个String对象的操作进行添加、删除等修改…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部