拦截器(springboot)

1、拦截器介绍

在SpringBoot中,拦截器是一种用于拦截请求并在处理请求之前或之后执行特定操作的机制。

拦截器可以用于实现一些通用的功能,例如身份验证、日志记录、性能监控等。

Springboot中的拦截器是通过实现HandlerInterceptor接口来实现的,该接口定义了三个方法:

(1)preHandle:在请求处理之前调用,可以进行一些前置处理逻辑,如果该方法返回false,则请求将被中断,不再继续处理;

(2)postHandle:在请求处理之后调用,但在试图渲染之前。可以对请求的结果进行进一步的处理或修改;

(3)afterCompletion:在整个请求完成之后调用,包括试图渲染完成,可以进行一些资源清理操作。

2、使用拦截器的基本思路

创建一个类,并实现HandlerInterceptor接口,并重写上述的三个方法,然后再配置类中注册该拦截器。基本代码如下:

(1)拦截器

java 复制代码
@Component  //该注解是将该拦截器声明为一个Spring组件,以便Springboot能够自动扫描并将其纳入管理。
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在请求处理之前进行拦截处理
        return true; // 返回true表示继续执行请求,返回false表示中断请求
    }

    @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 {
        // 在整个请求完成之后进行拦截处理,包括视图渲染完成
    }
}

(2)配置类中注册该拦截器

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {

	//导入拦截器
    @Autowired
    private MyInterceptor myInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    //        添加拦截器
//        registry.addInterceptor(interceptor):该方法用来添加拦截器
//        .addPathPatterns("/**"):该方法指定需要拦截的请求路径
//        .excludePathPatterns("/login","/register"):该方法可以配置排除路径
        registry.addInterceptor(myInterceptor)
                .addPathPatterns("/**"); // 拦截所有请求
    }
}

********解密拦截器

java 复制代码
为了构建这样一个管理系统,并确保登录密码和后续请求数据的加密,你需要考虑以下几点:

1. **选择加密算法**:选择一个安全的加密算法,如AES或RSA,用于数据的加密和解密。

2. **密钥管理**:确保密钥的安全存储和传输。对于对称加密算法(如AES),需要确保前后端使用相同的密钥;对于非对称加密算法(如RSA),需要分别使用公钥和私钥进行加密和解密。

3. **前端加密**:在前端实现一个加密方法,用于在发送数据前对数据进行加密。

4. **后端解密拦截器**:在后端实现一个拦截器,用于在接收请求时自动解密数据。

以下是一个简化的示例,展示如何实现这些功能:

### 前端(JavaScript,使用CryptoJS库)

首先,安装CryptoJS库:

```bash
npm install crypto-js

然后,在前端代码中实现加密和解密方法:

javascript 复制代码
import CryptoJS from 'crypto-js';

const secretKey = 'your-secret-key'; // 用于AES加密的密钥

// 加密方法
function encryptData(data) {
    const ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), secretKey).toString();
    return ciphertext;
}

// 解密方法(通常不需要在前端解密,除非有特殊需求)
function decryptData(ciphertext) {
    const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey);
    const originalText = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
    return originalText;
}

// 发送请求时调用加密方法
async function sendEncryptedData(url, data) {
    const encryptedData = encryptData(data);
    // 使用fetch或其他HTTP客户端发送请求,将encryptedData作为请求体
}

后端(Java,使用Spring Boot和Java Cryptography Extension)

在后端,你需要实现一个拦截器来解密请求体中的数据:

java 复制代码
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Component
public class DecryptionInterceptor implements HandlerInterceptor {

    private static final String SECRET_KEY = "your-secret-key"; // 用于AES解密的密钥

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String encryptedBody = request.getReader().readLine(); // 读取请求体中的加密数据

        // Base64解码
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedBody);

        // 解密
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

        // 将解密后的数据放回请求体,以便后续控制器处理
        request.setAttribute("decryptedData", new String(decryptedBytes, StandardCharsets.UTF_8));

        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 {
        // 清理资源或执行其他后处理操作
    }
}

接下来,注册拦截器:

java 复制代码
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 DecryptionInterceptor decryptionInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(decryptionInterceptor)
                .addPathPatterns("/**"); // 拦截所有请求路径

加密

java 复制代码
在Java后端管理系统中,实现对每个接口的出参数据进行加密,通常意味着你需要在数据返回给前端之前,在控制器的某个地方进行加密处理。下面是一个基本的实现步骤,使用AES加密作为例子:

1. 创建加密工具类
首先,你需要一个加密工具类,该类封装了加密的逻辑。这个类可以包含多种加密方法,比如加密字符串或加密对象(转换成JSON字符串后加密)。

java
import com.fasterxml.jackson.databind.ObjectMapper;  
import javax.crypto.Cipher;  
import javax.crypto.spec.SecretKeySpec;  
import java.nio.charset.StandardCharsets;  
import java.util.Base64;  
  
public class EncryptionUtils {  
  
    private static final String SECRET_KEY = "your-256-bit-secret"; // 256位AES密钥  
    private static final String ALGORITHM = "AES";  
    private static final String TRANSFORMATION = ALGORITHM + "/CBC/PKCS5Padding";  
  
    public static String encrypt(String data) throws Exception {  
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);  
        byte[] keyValue = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM).getEncoded();  
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyValue, ALGORITHM), cipher.getParameters());  
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));  
        return Base64.getEncoder().encodeToString(encrypted);  
    }  
  
    public static String encryptJson(Object data) throws Exception {  
        ObjectMapper objectMapper = new ObjectMapper();  
        String json = objectMapper.writeValueAsString(data);  
        return encrypt(json);  
    }  
}
2. 在Controller中使用加密工具类
在你的Controller中,你可以创建一个通用的方法来封装加密逻辑,或者直接在每个需要加密的接口方法中使用加密工具类。

java
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class MyController {  
  
    @GetMapping("/some-endpoint")  
    public String getSomeData() throws Exception {  
        // 假设这是你的原始数据  
        Map<String, String> data = new HashMap<>();  
        data.put("key1", "value1");  
        data.put("key2", "value2");  
        data.put("key3", "value3");  
  
        // 加密数据  
        String encryptedData = EncryptionUtils.encryptJson(data);  
  
        // 返回加密后的数据  
        return encryptedData;  
    }  
}
3. 前端解密处理
前端在接收到加密后的数据后,需要使用相同的算法和密钥进行解密,并将解密后的JSON字符串转换回对象。这通常意味着你需要将密钥和加密算法安全地分享给前端,或者使用某种密钥交换机制。

注意事项:
密钥管理:密钥的安全性至关重要。不要在代码中硬编码密钥,使用环境变量、配置文件或密钥管理服务来存储密钥。
错误处理:在加密和解密过程中添加适当的错误处理逻辑,以确保系统稳定性和安全性。
性能:加密和解密操作可能会对性能产生影响,特别是在处理大量数据时。确保在生产环境中测试性能影响,并根据需要进行优化。
安全审计:在实现加密功能后,建议进行安全审计以确保没有引入新的安全漏洞。
最后,请注意,虽然加密可以提高数据的安全性,但它并不是万无一失的。在实施加密的同时,还应考虑其他安全措施,如HTTPS、身份验证和授权等,以构建一个全面的安全体系。
相关推荐
葫芦和十三38 分钟前
图解 MongoDB 22|读写关注:持久性与一致性的档位选择
后端·mongodb·agent
葫芦和十三7 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp8 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑8 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯9 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan11 小时前
多Agent之间的区别
后端
青石路13 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充13 小时前
1.面向对象设计思想
后端
IT_陈寒14 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro14 小时前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端