Springboot如何使用filter对response内容进行加密方式
发表于:2025-01-18 作者:千家信息网编辑
千家信息网最后更新 2025年01月18日,这篇文章主要介绍Springboot如何使用filter对response内容进行加密方式,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!使用filter对response内容进
千家信息网最后更新 2025年01月18日Springboot如何使用filter对response内容进行加密方式
这篇文章主要介绍Springboot如何使用filter对response内容进行加密方式,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
使用filter对response内容进行加密
编写加密类(AES)
/** * aes加密解密 */public class AesEncryptUtils { //参数分别代表 算法名称/加密模式/数据填充方式 private static String algorithmstr = "AES/ECB/PKCS5Padding"; public static String getAlgorithmstr() { return algorithmstr; } /** * 加密 * @param content 加密的字符串 * @param encryptKey key值 * @return * @throws Exception */ public static String encrypt(String content, String encryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); Cipher cipher = Cipher.getInstance(algorithmstr); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES")); byte[] b = cipher.doFinal(content.getBytes("utf-8")); return Base64.encodeBase64String(b); } /** * 解密 * @param encryptStr 解密的字符串 * @param decryptKey 解密的key值 * @return * @throws Exception */ public static String decrypt(String encryptStr, String decryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); Cipher cipher = Cipher.getInstance(algorithmstr); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES")); byte[] encryptBytes = Base64.decodeBase64(encryptStr); byte[] decryptBytes = cipher.doFinal(encryptBytes); return new String(decryptBytes); } public static void main(String[] args) throws Exception{ String str = "pp2bQLjabobRWp2T5Ro5/GlqWCigmkwHYnrOK11VZkTkIA2hSwnEi1sijfTV6Ozd/"; System.out.println(decrypt(str,"f8db034bda44rtkb")); }}
编写Filter类
/** * 过滤器拦截请求,实现加密解密功能 * * @Component 将此Filter交给Spring容器管理 * @WebFilter 通过WebFilter进行Filter声明,这样容器在进行部署的时候就会处理该Filter * */@Componentpublic class EncryptFilter implements Filter { Logger log = LoggerFactory.getLogger(this.getClass()); @Value("${admin.encrypt.excludeUrl}") private String ignoreStr; private String[] ignoreArr; @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } /** * 有错误相应返回-44 * * @param response * @throws IOException */ private void getFailResponse(HttpServletResponse response) throws IOException { response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); PrintWriter out = null; out = response.getWriter();// out.write("{\n" +// " \"status\":"+ Constant.ENCRYPT_FAIL +",\n" +// " \"message\": null,\n" +// " \"data\": []\n" +// "}"); //加密后的错误消息 out.write("+D+JO8tuwkrNbxnTTLdqStifmQceT+LlYETnIG/JZKrbAn+gIiqIp3VbzBV1y6R8B7aY53VM2xHa7cY3Osbnqw=="); out.flush(); out.close(); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { if(ignoreArr==null){ ignoreArr = ignoreStr.split(","); } HttpServletRequest HttpRequest=(HttpServletRequest)request; HttpServletResponse HttpResponse=(HttpServletResponse)response; boolean flag=isIgnore(HttpRequest,ignoreArr); if(flag) { try { chain.doFilter(HttpRequest, HttpResponse); } catch (IOException e) { e.printStackTrace(); } catch (ServletException e) { e.printStackTrace(); } }else{ try{ //响应处理 包装响应对象 res 并缓存响应数据 ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response); //执行业务逻辑 交给下一个过滤器或servlet处理 chain.doFilter(request, responseWrapper); byte[] resData = responseWrapper.getResponseData(); //设置响应内容格式,防止解析响应内容时出错// responseWrapper.setContentType("text/plain;charset=UTF-8"); //加密响应报文并响应 String encryptBASE64 = AesEncryptUtils.encrypt(new String(resData),Constant.ENCRYPT_STR); PrintWriter out = response.getWriter(); out.print(encryptBASE64); out.flush(); out.close(); }catch(Exception e){ try { getFailResponse((HttpServletResponse)response); } catch (IOException ioException) { ioException.printStackTrace(); } e.printStackTrace(); } }} @Override public void destroy() { // TODO Auto-generated method stub } /** * 哪些路径不处理 * @param request * @param strArr * @return */ public boolean isIgnore(HttpServletRequest request,String[] strArr) { String path=request.getRequestURI(); for(String ignore:strArr) { if(path.contains(ignore)) { return true; } } return false; }}
下图是对应的application.properties中的配置
其中用到了两个工具类
RequestWrapper
/** * @Description: 请求包装类 * @Date: 2020/5/26 16:29 */public class RequestWrapper extends HttpServletRequestWrapper { private String requestBody = null; //请求体 private HttpServletRequest req = null; // private final byte[] body;//保存流的字节数组 private final MapreqHeaders=new HashMap<>(); public RequestWrapper(HttpServletRequest request) throws IOException { super(request); this.req = request;// this.reqHeaders = new HashMap ();// String sessionStream = getRequestBodyStr(request);//读取流中的参数// body = sessionStream.getBytes(Charset.forName("UTF-8")); } public RequestWrapper(HttpServletRequest request, String requestBody) { super(request); this.requestBody = requestBody; this.req = request;// this.reqHeaders = request.get; } /** * @Description: 获取请求body * @Date: 2020/5/26 10:31 * @Param: [request] * @Return: java.lang.String */ public String getRequestBodyStr(final ServletRequest request) throws IOException { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = cloneInputStream(request.getInputStream()); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { inputStream.close(); } if (reader != null) { reader.close(); } } return sb.toString(); } /** * @Description: 复制输入流 * @Param: [inputStream] * @Return: java.io.InputStream */ public InputStream cloneInputStream(ServletInputStream inputStream) throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) > -1) { byteArrayOutputStream.write(buffer, 0, len); } byteArrayOutputStream.flush(); InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); return byteArrayInputStream; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody.getBytes(req.getCharacterEncoding())); return new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return bais.read(); } }; } /** * 添加header的名称和值 * * @param name * @param value */ public void addHeader(String name, String value) { reqHeaders.put(name, value); } @Override public String getHeader(String name) {// log.info("getHeader --->{}", name); String headerValue = super.getHeader(name); if (reqHeaders.containsKey(name)) { headerValue = reqHeaders.get(name); } return headerValue; } /** * 得到headers的名称 */ @Override public Enumeration getHeaderNames() { List names = Collections.list(super.getHeaderNames()); for (String name : reqHeaders.keySet()) { names.add(name); } return Collections.enumeration(names); } @Override public Enumeration getHeaders(String name) {// log.info("getHeaders name --->>>>>>{}", name); List values = Collections.list(super.getHeaders(name));// log.info("getHeaders value --->>>>>>{}", values); if (reqHeaders.containsKey(name)) { values = Arrays.asList(reqHeaders.get(name)); } return Collections.enumeration(values); }}
ResponseWrapper
/** * @Description: 响应包装类 * @Date: 2020/5/26 16:29 */public class ResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream buffer = null; private ServletOutputStream out = null; private PrintWriter writer = null; public ResponseWrapper(HttpServletResponse response) throws IOException { super(response); buffer = new ByteArrayOutputStream();// 真正存储数据的流 out = new WapperedOutputStream(buffer); writer = new PrintWriter(new OutputStreamWriter(buffer,this.getCharacterEncoding())); } /** 重载父类获取outputstream的方法 */ @Override public ServletOutputStream getOutputStream() throws IOException { return out; } /** 重载父类获取writer的方法 */ @Override public PrintWriter getWriter() throws UnsupportedEncodingException { return writer; } /** 重载父类获取flushBuffer的方法 */ @Override public void flushBuffer() throws IOException { if (out != null) { out.flush(); } if (writer != null) { writer.flush(); } } @Override public void reset() { buffer.reset(); } /** 将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据 */ public byte[] getResponseData() throws IOException { flushBuffer(); return buffer.toByteArray(); } /** 内部类,对ServletOutputStream进行包装 */ private class WapperedOutputStream extends ServletOutputStream { private ByteArrayOutputStream bos = null; public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException { bos = stream; } @Override public void write(int b) throws IOException { bos.write(b); } @Override public void write(byte[] b) throws IOException { bos.write(b, 0, b.length); } @Override public boolean isReady() { return false; } @Override public void setWriteListener(WriteListener writeListener) { } }}
写配置类
@Configurationpublic class WebConfiguration { @Autowired private EncryptFilter encryptFilter; @Bean public FilterRegistrationBean registFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(encryptFilter); registration.addUrlPatterns("/*"); registration.setName("EncryptFilter"); registration.setOrder(1);// registration.setEnabled(false); return registration; } //做跨域处理,跟这个filter没关系 @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowCredentials(true) .allowedMethods("*") .allowedHeaders("*") .maxAge(3600); } }; }}
Springboot数据加密传输
创建加解密注解注解
对于拦截路径上全部采用数据加解密处理,如果有部分接口不需要加解密处理的话,在方法上或者类上加上此注解即可不做加解密处理
package com.hars.common.infrastructure.validation.security;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 加解密注解 * * @author Huangbigao * @date 2020/8/29 11:02 */@Documented@Target({ElementType.METHOD, ElementType.TYPE,})@Retention(RetentionPolicy.RUNTIME)public @interface CryptoDecryptionSecurity { /** * 是否加解密,默认加解密 * * @return */ boolean cryptoDecryption() default true; /** * 是否进行request 解密,默认进行解密 * * @return */ boolean requestDecryption() default true; /** * 是否对输出结果进行加密,默认进行加密 * * @return */ boolean responseCrypto() default true;}
ps:注解使用
@CryptoDecryptionSecurity(responseCrypto = false) @ApiOperation(value = "微信公众号验证业务处理接口") @GetMapping(value = "/handle/{appid}", produces = "text/plain;charset=utf-8") public String authHandle(@PathVariable String appid, @RequestParam(name = "signature", required = false) String signature, @RequestParam(name = "timestamp", required = false) String timestamp, @RequestParam(name = "nonce", required = false) String nonce, @RequestParam(name = "echostr", required = false) String echostr, HttpServletRequest request) { return weChatMpService.authHandle(appid, signature, timestamp, nonce, echostr, request); }
创建request解密类
package com.hars.common.infrastructure.utils.filter;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.TypeReference;import com.hars.common.infrastructure.utils.aes.AesUtil;import com.hars.common.infrastructure.utils.http.HttpContextUtil;import com.hars.common.infrastructure.utils.string.StringUtil;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.util.Collections;import java.util.Enumeration;import java.util.HashMap;import java.util.LinkedHashSet;import java.util.Map;import java.util.Set;import javax.servlet.ReadListener;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import org.springframework.util.Assert;/** * @author Huangbigao * @date 2020/8/29 10:12 */public class DecryptionRequestUtil extends HttpServletRequestWrapper { private static final String APPLICATION_JSON = "application/json"; /** * 所有参数的Map集合 */ private MapparameterMap; /** * 输入流 */ private InputStream inputStream; private final boolean valueValid = true; public DecryptionRequestUtil(HttpServletRequest request, String password) { super(request); String encrypt; String contentType = request.getHeader("Content-Type"); if (contentType != null && contentType.contains(APPLICATION_JSON)) { //json String bodyStr = HttpContextUtil.getBodyString(request); if (StringUtil.isBlank(bodyStr)){ return; } encrypt = (String) JSON.parseObject(bodyStr).get("encrypt"); } else { // url encrypt = request.getParameter("encrypt"); } String jsonData = AesUtil.decrypt(encrypt, password); if (StringUtil.isBlank(jsonData)){ return; } if (contentType != null && contentType.contains(APPLICATION_JSON)) { if (this.inputStream == null) { this.inputStream = new DecryptionInputStream(new ByteArrayInputStream(jsonData.getBytes())); } } parameterMap = buildParams(jsonData); } private Map buildParams(String src) { Map map = new HashMap<>(); Map params = JSONObject.parseObject(src, new TypeReference
创建response加密类
package com.hars.common.infrastructure.utils.filter;import java.io.ByteArrayOutputStream;import java.io.IOException;import javax.servlet.ServletOutputStream;import javax.servlet.WriteListener;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServletResponseWrapper;/** * @author Huangbigao * @date 2020/8/29 13:11 */public class ResponseWrapperUtil extends HttpServletResponseWrapper { private ByteArrayOutputStream buffer; private ServletOutputStream out; public ResponseWrapperUtil(HttpServletResponse httpServletResponse) { super(httpServletResponse); buffer = new ByteArrayOutputStream(); out = new WrapperOutputStream(buffer); } @Override public ServletOutputStream getOutputStream() throws IOException { return out; } @Override public void flushBuffer() throws IOException { if (out != null) { out.flush(); } } public byte[] getContent() throws IOException { flushBuffer(); return buffer.toByteArray(); } private static class WrapperOutputStream extends ServletOutputStream { private ByteArrayOutputStream bos; WrapperOutputStream(ByteArrayOutputStream bos) { this.bos = bos; } @Override public void write(int b) throws IOException { bos.write(b); } @Override public boolean isReady() { // TODO Auto-generated method stub return false; } @Override public void setWriteListener(WriteListener arg0) { // TODO Auto-generated method stub } }}
创建AES加密工具类
package com.hars.common.infrastructure.utils.aes;import com.hars.common.infrastructure.utils.string.StringUtil;import java.nio.charset.StandardCharsets;import java.util.Base64;import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;import lombok.extern.slf4j.Slf4j;/** * AES 加解密 工具类 * * @author Huangbigao * @date 2020/8/28 15:17 */@Slf4jpublic class AesUtil { /** * AES解密 * * @param content 密文 * @param password 秘钥,必须为16个字符组成 * @return 明文 */ public static String decrypt(String content, String password) { try { if (StringUtil.isBlank(content) || StringUtil.isBlank(password)) { return null; } byte[] encryptByte = Base64.getDecoder().decode(content); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(password.getBytes(), "AES")); byte[] decryptBytes = cipher.doFinal(encryptByte); return new String(decryptBytes); } catch (Exception e) { log.error(e.getMessage(), e); return null; } } /** * AES加密 * * @param content 明文 * @param password 秘钥,必须为16个字符组成 * @return 密文 */ public static String encrypt(String content, String password) { try { if (StringUtil.isBlank(content) || StringUtil.isBlank(password)) { return null; } Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(password.getBytes(), "AES")); byte[] encryptStr = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(encryptStr); } catch (Exception e) { log.error(e.getMessage(), e); return null; } }
创建加解密Filter类
package com.hars.user.infrastructure.filter;import com.alibaba.fastjson.JSON;import com.hars.common.infrastructure.utils.aes.AesUtil;import com.hars.common.infrastructure.utils.filter.DecryptionRequestUtil;import com.hars.common.infrastructure.utils.filter.ResponseWrapperUtil;import com.hars.common.infrastructure.validation.security.CryptoDecryptionSecurity;import com.hars.result.infrastructure.advice.Response;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Map;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.BeanFactoryUtils;import org.springframework.context.ApplicationContext;import org.springframework.core.annotation.AnnotationAwareOrderComparator;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.HandlerExecutionChain;import org.springframework.web.servlet.HandlerMapping;/** * @author Huangbigao * @date 2020/8/28 16:26 */public class CryptoDecryptionFilter implements Filter { //方法映射集 private ListhandlerMappings; public CryptoDecryptionFilter(ApplicationContext applicationContext) { Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, HandlerMapping.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerMappings = new ArrayList<>(matchingBeans.values()); AnnotationAwareOrderComparator.sort(this.handlerMappings); } } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpServletResponse httpServletResponse = (HttpServletResponse) response; //判断方法上是否存在注解,如果不存在,默认加解密 //类上的注解 CryptoDecryptionSecurity classFlag = null; //方法上的注解 CryptoDecryptionSecurity methodFlag = null; try { HandlerExecutionChain handlerExecutionChain = getHandler(httpServletRequest); Object handler = handlerExecutionChain != null ? handlerExecutionChain.getHandler() : null; if (handler instanceof HandlerMethod) { HandlerMethod method = (HandlerMethod) handler; classFlag = method.getBeanType().getAnnotation(CryptoDecryptionSecurity.class); methodFlag = method.getMethodAnnotation(CryptoDecryptionSecurity.class); //如果方法注解存在,且不加密,则直接返回 if (methodFlag != null && !methodFlag.cryptoDecryption()) { chain.doFilter(request, response); return; } //如果类注解存在,且不加密,则直接返回 if (classFlag != null && !classFlag.cryptoDecryption()) { chain.doFilter(request, response); return; } } } catch (Exception e) { response.setContentType("application/json; charset=UTF-8"); response.getWriter().write(JSON.toJSONString(Response.error("该请求无效", 601))); return; } CryptoDecryptionSecurity currentFlag = null; if (methodFlag != null) { currentFlag = methodFlag; } else if (classFlag != null) { currentFlag = classFlag; } //加解密密码 String password = "Hbg584782648!@hb"; ResponseWrapperUtil responseWrapper = null; //加解密处理 if (currentFlag == null || (currentFlag.requestDecryption() && currentFlag.responseCrypto())) { ServletRequest requestWrapper = new DecryptionRequestUtil(httpServletRequest, password); responseWrapper = new ResponseWrapperUtil(httpServletResponse); chain.doFilter(requestWrapper, responseWrapper); } else if (currentFlag.requestDecryption() && !currentFlag.responseCrypto()) { ServletRequest requestWrapper = new DecryptionRequestUtil(httpServletRequest, password); chain.doFilter(requestWrapper, response); } else if (!currentFlag.requestDecryption() && currentFlag.responseCrypto()) { responseWrapper = new ResponseWrapperUtil(httpServletResponse); chain.doFilter(request, responseWrapper); } else { chain.doFilter(request, response); } if (responseWrapper != null) { byte[] content = responseWrapper.getContent();//获取返回值 //判断是否有值 if (content.length > 0) { String result = new String(content, "UTF-8"); //加密 String encryptStr = AesUtil.encrypt(result, password); //把返回值输出到客户端 ServletOutputStream out = response.getOutputStream(); out.write(encryptStr.getBytes()); out.flush(); } } } /** * 获取访问目标方法 * * @param request * @return HandlerExecutionChain * @throws Exception */ private HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { for (HandlerMapping hm : this.handlerMappings) { HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } } return null; }}
定义过滤器的拦截路径
@Autowired private ApplicationContext applicationContext; /** * 添加加解密过滤器 * * @return */ @Bean public FilterRegistrationBean encryptionDataFilterRegistration() { FilterRegistrationBeanregistration = new FilterRegistrationBean<>(); registration.setFilter(new CryptoDecryptionFilter(applicationContext)); registration.addUrlPatterns("/*"); registration.setName("cryptoDecryptionFilter"); registration.setOrder(2); return registration; }
以上是"Springboot如何使用filter对response内容进行加密方式"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!
加密
注解
处理
方法
内容
数据
字符
过滤器
UTF-8
包装
方式
参数
名称
工具
路径
输出
业务
加密解密
字符串
容器
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
技术派数据库方案
php 链接数据库类下载
教务信息管理系统 数据库
tsc标签打印机设置数据库
软件开发游戏编程入门
软件开发外包专业
商业银行软件开发管理办法
戴尔服务器一小时多少度电
网络技术不平等 隐私受损
乡镇网络安全主题班会
台式电脑服务器
wos数据库收录论文
服务器玩剑灵
简单登录界面如何读数据库
电脑设置服务器登录
什么是服务器程序
采购20万台服务器
优蜜互联网科技有限公司
数据库不能录入英文
维护网络安全手抄报图片
本地服务器外网登录设置
教务信息管理系统 数据库
襄阳软件开发工作
生态家网络技术有限公司
防服务器检测app
网络安全教育课件ppt
数据库idx文件
龙岩天气预报软件开发
手机版远古服务器
oppo登录服务器超时