一、HttpServletRequestWrapper代码
package com.vteam.uap.security.httpWrapper; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; /** * @author Miller.Lai * @description: 请求装饰器 * @date 2023-12-18 11:09:46 */ public class RequestWrapper extends HttpServletRequestWrapper { private byte[] bytes; private HttpServletRequest request; /** * @param request */ public RequestWrapper(HttpServletRequest request) { super(request); this.request = request; } public String getRequestBody() throws IOException { try (BufferedInputStream bis = new BufferedInputStream(request.getInputStream()); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) > 0) { baos.write(buffer, 0, len); } bytes = baos.toByteArray(); String body = new String(bytes); return body; } catch (IOException ex) { throw ex; } } public void setRequestBody(String body){ bytes = body.getBytes(); } public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); 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 byteArrayInputStream.read(); } }; } }
二、HttpServletRequestWrapper代码
package com.vteam.uap.security.httpWrapper; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.WriteListener; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponseWrapper; import java.io.*; /** * @author Miller.Lai * @description: 响应装饰器 * @date 2023-12-15 13:29:16 */ public class ResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream outputStream; public byte[] getResponseData(){ try { outputStream.flush(); } catch (IOException e) { e.printStackTrace(); } return outputStream.toByteArray(); } public ResponseWrapper(HttpServletResponse response) { super(response); this.outputStream =new ByteArrayOutputStream(); } @Override public PrintWriter getWriter() throws IOException { return new PrintWriter(outputStream); } @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public boolean isReady() { return false; } @Override public void setWriteListener(WriteListener listener) { } @Override public void write(int b) throws IOException { outputStream.write(b); } }; } }
三、加解密过滤器代码
package com.vteam.uap.core.filter; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.vteam.uap.common.util.*; import com.vteam.uap.security.codec.CodecProperties; import com.vteam.uap.security.httpWrapper.RequestWrapper; import com.vteam.uap.security.httpWrapper.ResponseWrapper; import jakarta.annotation.Resource; import jakarta.servlet.Filter; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.springframework.util.PatternMatchUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.io.IOException; import java.util.Objects; /** * @author Miller.Lai * @description: 加解码过滤器 * @date 2023-12-15 16:46:03 */ @Slf4j public class CodecFilter implements Filter { @Resource protected CodecProperties codecProperties; @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 请求解密 if (codecProperties.isApiEnable() && !isIgnore() && ("POST".equals(((HttpServletRequest)request).getMethod().trim().toUpperCase())) && "application/json".equals(request.getContentType().trim().toLowerCase())){ RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest) request); String bodyStr = requestWrapper.getRequestBody(); if(StringUtils.isNotBlank(bodyStr)){ JSONObject bodyJson = JSONObject.parseObject(bodyStr); Object data = bodyJson.get("data"); if(data != null && data instanceof String && ((String)data).trim().length () !=0 ){ if (log.isDebugEnabled()) { log.debug("解密 API 请求消息:type={}, requestBody={}",requestWrapper.getMethod(), bodyJson.toJSONString()); } String plainText = AesUtils.decrypt((String) data, AesUtils.Mode.API,codecProperties.getAesKey(),codecProperties.getAesIv(),codecProperties.isDbEnable()); bodyJson.put("data",JSONObject.parseObject(plainText)); requestWrapper.setRequestBody(bodyJson.toJSONString()); } } // 包装响应对象 ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response); chain.doFilter(requestWrapper, responseWrapper); // 拿到响应对象 byte[] responseData = responseWrapper.getResponseData(); if("application/json".equals(responseWrapper.getContentType().trim().toLowerCase())){ String originalResulet = new String(responseData); JSONObject jsonObject =JSONObject.parseObject(originalResulet); // 拿到响应对象中的data Object data = jsonObject.get("data"); if(data != null){ String encText = AesUtils.encrypt(JSON.toJSONString(data), AesUtils.Mode.API,codecProperties.getAesKey(),codecProperties.getAesIv(),codecProperties.isDbEnable()); jsonObject.put("data", encText); } responseData = jsonObject.toJSONString().getBytes("utf-8"); } HttpServletResponse httpServletResponse = (HttpServletResponse) response; response.setContentLength(responseData.length); httpServletResponse.getOutputStream().write(responseData); httpServletResponse.getOutputStream().flush(); }else{ // 处理业务逻辑 chain.doFilter(request, response); } } @Override public void destroy() { } protected boolean isIgnore() { boolean isIgnore = false; String[] ignoreUrl = codecProperties.getIgnoreUrl(); if (ArrayUtils.isNotEmpty(ignoreUrl)) { HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull( RequestContextHolder.getRequestAttributes())).getRequest(); for (String s : ignoreUrl) { if (PatternMatchUtils.simpleMatch(s, request.getRequestURI())) { isIgnore = true; break; } } } return isIgnore; } }
四、国际化过滤器代码
package com.vteam.uap.core.filter; import com.alibaba.fastjson2.JSONObject; import com.vteam.uap.common.constant.CommonConstants; import com.vteam.uap.common.util.GlobalConstants; import com.vteam.uap.common.util.I18NUtils; import com.vteam.uap.common.util.StringUtils; import com.vteam.uap.common.util.UuidUtil; import com.vteam.uap.security.httpWrapper.ResponseWrapper; import jakarta.servlet.*; import jakarta.servlet.Filter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.PatternMatchUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.io.IOException; import java.util.Objects; /** * @author Miller.Lai * @description: * @date 2023-12-15 16:46:03 */ @Slf4j public class I18NFilter implements Filter { @Value("${uap.i18n.enable:false}") private boolean i18nEnable; @Value("${uap.i18n.language:zh_CN}") private String language; @Value("${uap.i18n.ignore-url:/doc.html,/webjars/**,/v3/api-docs/**,/actuator**,/favicon.ico}") private String ignoreUrl; @Value("${uap.response.msg.include-request-id:false}") private boolean msgIncludeRequestId; public I18NFilter() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 如果开启了国际化则进行国际化处理 if (i18nEnable && !isIgnore()) { // 包装响应对象 ResponseWrapper customResponseWrapper = new ResponseWrapper((HttpServletResponse) response); // 处理业务逻辑 chain.doFilter(request, customResponseWrapper); // 拿到响应对象 byte[] responseData = customResponseWrapper.getResponseData(); if("application/json".equals(customResponseWrapper.getContentType().trim().toLowerCase())){ String originalResulet = new String(responseData); JSONObject jsonObject =JSONObject.parseObject(originalResulet); // 拿到响应对象中的msg String msg = (String)jsonObject.get("msg"); String i18nMsg = null; if ( StringUtils.isNotBlank(msg) ) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String languageInheader = httpServletRequest.getHeader("Language"); // 优先使用请求头里的国际化语言 if (languageInheader != null) { i18nMsg = I18NUtils.getI18N(msg, languageInheader); } else { i18nMsg = I18NUtils.getI18N(msg, language); } }else if( StringUtils.isNotBlank(msg) ){// 不进行国际化也要清除相关缓存 I18NUtils.getActualContainBraceMsgParamMap().remove(msg+GlobalConstants.Symbol.UNDERLINE+Thread.currentThread().getId()); I18NUtils.getActualContainBraceMsgMap().remove(msg+GlobalConstants.Symbol.UNDERLINE+Thread.currentThread().getId()); } if(i18nMsg != null ){ msg = i18nMsg; } if(msg == null){ msg = ""; } // 如果线程号不存在,则进行设置 if(StringUtils.isEmpty(MDC.get("UUID"))){ MDC.put("UUID", UuidUtil.getShortUuid()); } // msg中携带请求id返回 if(msgIncludeRequestId ){ msg = MDC.get("UUID") + GlobalConstants.Symbol.SPACE + msg ; } jsonObject.put("msg", msg); responseData = jsonObject.toJSONString().getBytes("utf-8"); } HttpServletResponse httpServletResponse = (HttpServletResponse) response; response.setContentLength(responseData.length); httpServletResponse.getOutputStream().write(responseData); httpServletResponse.getOutputStream().flush(); }else{ // 处理业务逻辑 chain.doFilter(request, response); } } @Override public void destroy() { } protected boolean isIgnore() { boolean isIgnore = false; if(StringUtils.isEmpty(ignoreUrl)){ return false; } String[] ignoreUrls = ignoreUrl.split(CommonConstants.Symbol.COMMA); if (ArrayUtils.isNotEmpty(ignoreUrls)) { HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull( RequestContextHolder.getRequestAttributes())).getRequest(); for (String s : ignoreUrls) { if (PatternMatchUtils.simpleMatch(s, request.getRequestURI())) { isIgnore = true; break; } } } return isIgnore; } }
五、过滤器注册
/** * 国际化过滤器 * @return */ @Bean public I18NFilter i18NFilter() { return new I18NFilter(); } @Bean public FilterRegistrationBean i18NFilterRegistrationBean() { // 新建过滤器注册类 FilterRegistrationBean registration = new FilterRegistrationBean(); // 添加自定义 过滤器 registration.setFilter(i18NFilter()); // 设置过滤器的URL模式 registration.addUrlPatterns("/*"); //设置过滤器顺序 registration.setOrder(4); return registration; } /** * 请求加解密过滤器 * @return */ @Bean public CodecFilter codecFilter() { return new CodecFilter(); } @Bean public FilterRegistrationBean codecFilterRegistrationBean() { // 新建过滤器注册类 FilterRegistrationBean registration = new FilterRegistrationBean(); // 添加自定义 过滤器 registration.setFilter(codecFilter()); // 设置过滤器的URL模式 registration.addUrlPatterns("/*"); //设置过滤器顺序 registration.setOrder(3); return registration; }
本人近十年JAVA架构设计经验,长期从事IT技术资源整合。有志于自我技术提升、需要最新IT技术课程的小伙伴,可私信联系我 ,粉丝一律友情价