日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

springboot中的拦截器interceptor和过滤器filter,多次获取request参数

發布時間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot中的拦截器interceptor和过滤器filter,多次获取request参数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
大家好,我是烤鴨:
????這是一篇關于springboot的攔截器(interceptor)和過濾器(Filter)。

????先說一下過濾器和攔截器。


區別:
1. servlet請求,順序:Filter ——> interceptor。
2. Filter的作用是對所有進行過濾,包括接口或者靜態資源,interceptor 僅攔截 請求。
3. Filter對請求或者資源進行過濾,篩選合適的請求或者資源。interceptor,僅對不符合的請求攔截。
4. Filter基于回調函數,我們需要實現的filter接口中doFilter方法就是回調函數,而interceptor則基于?
? ? java本身的反射機制,這是兩者最本質的區別。
5. Filter是依賴于servlet容器的,即只能在servlet容器中執行,很顯然沒有servlet容器就無法來回調
? ? doFilter方法。而interceptor與servlet容器無關。


后面代碼較多,不太適合看。

提前總結一下,我這里的過濾器和攔截器的使用:

filter: 目的就是可以以流的方式多次獲取請求參數。
Interceptor對回調接口進行統一的驗證簽名。
回調接口都需要驗證簽名,而且簽名規則一樣,所以想拿到攔截器處理。

如果簽名或者ip地址不符合條件,直接就返回了。而具體的接口只要專注業務處理,不需要驗證簽名了。

下面貼一下在springboot中的使用:

1. filter:

InterfaceFilter.java

package com.test.test.filter;import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException;@WebFilter(urlPatterns = "/*", filterName = "InterfaceFilter") public class InterfaceFilter implements Filter{private static Logger log = LoggerFactory.getLogger(InterfaceFilter.class);@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse res = (HttpServletResponse) response;try {if ("POST".equals(req.getMethod().toUpperCase())) {// 獲取請求參數byte[] bytes = IOUtils.toByteArray(request.getInputStream());String params = new String(bytes, req.getCharacterEncoding());ThreadCache.setPostRequestParams(params);log.info("filer-post請求參數:[params={}]", params);} else {log.info("非post請求");}chain.doFilter(request, response);} catch (Exception e) {log.error(e.getMessage(), e);}}@Overridepublic void destroy() {} }

ThreadCache.java:

package com.test.test.filter; public class ThreadCache {// ThreadLocal里只存儲了簡單的String對象,也可以自己定義對象,存儲更加復雜的參數private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();public static String getPostRequestParams(){return threadLocal.get();}public static void setPostRequestParams(String postRequestParams){threadLocal.set(postRequestParams);}public static void removePostRequestParams(){threadLocal.remove();} }

說一下WebFilter注解。

urlPatterns指的是過濾哪個路徑。跟在xml中配置是一樣的作用。

簡單說一下,我這個過濾器的作用。目的就是可以以流的方式多次獲取請求參數。
正常requst.getInputStream只能獲取一次。但是我在過濾器中將他的參數放到threadlocal中,
這樣當前請求中就可以獲取到請求參數了。
另外說一下:
有兩種方式實現多次獲取request參數。
1. 創建threadlocal類,將request或者request的參數放進去。
2. 創建wrapper類,類似裝飾者模式,對request對象進行處理。getInputStream之后將流重新set進去。


推薦一篇多次獲取request參數的博客:

https://www.cnblogs.com/endstart/p/6196807.html

2. Interceptor:

PlatformInterceptor.java:

package com.test.test.interceptor;import java.util.Map;import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import com.alibaba.fastjson.JSONObject; import com.test.test.config.ConfigProperties; import com.test.test.constants.IMsgEnum; import com.test.test.filter.ThreadCache; import com.test.test.resp.BaseResp; import com.test.test.security.SignCheck; import com.test.test.utils.DESTools; import com.test.test.utils.JsonUtil; import com.test.test.utils.LogUtils; import com.test.test.utils.NetworkUtil; import com.test.test.utils.ReflectUtil;/*** ClassName: PlatformInterceptor date: 2015年12月30日 下午2:13:24 Description: 攔截器* * @author xiaozhan* @version* @since JDK 1.8*/ @Component public class PlatformInterceptor implements HandlerInterceptor {private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);@Autowiredprivate SignCheck signCheck;@Autowiredprivate ConfigProperties configProperties;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {logger.info(LogUtils.getRequestLog(request));// 獲取自定義注解String allowOrigin = null;String servletPath = request.getServletPath();boolean isDeprecated = false;BaseResp baseResp = new BaseResp();ServletOutputStream out = response.getOutputStream();if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;Deprecated deprecated = handlerMethod.getMethodAnnotation(Deprecated.class);if (deprecated != null) {isDeprecated = true;}}String method = request.getMethod();if (!method.equals(RequestMethod.POST.name())) {baseResp.getMsg().setRstcode(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgCode());baseResp.getMsg().setRsttext(IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText());logger.info("----- " + IMsgEnum.PARAM_REQUEST_METHOD_FALSE.getMsgText() + " -----");out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));return false;}String clientIp = NetworkUtil.getIpAddress(request);logger.info("------ client Ip is ---》" + clientIp);// 判斷是否是ip白名單if (!signCheck.checkIpAddress(clientIp)) {baseResp.getMsg().setRstcode(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgCode());baseResp.getMsg().setRsttext(IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText());logger.info("----- " + IMsgEnum.PARAM_IP_ADDRESS_FALSE.getMsgText() + " -----");out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));return false;}// 驗證簽名String params = ThreadCache.getPostRequestParams();logger.info("interceptor-post請求參數:[params={}]" + params);Map<String, Object> map = ReflectUtil.getDecodeParamMap(params);String sign = (String) map.get("sign");if (map.containsKey("sign")) {map.remove("sign");}// 簽名校驗if (!SignCheck.checkSign(map, sign, configProperties.getPrivateKey())) {baseResp.getMsg().setRstcode(IMsgEnum.PARAM_SIGN_FALSE.getMsgCode());baseResp.getMsg().setRsttext(IMsgEnum.PARAM_SIGN_FALSE.getMsgText());logger.info("----- " + IMsgEnum.PARAM_SIGN_FALSE.getMsgText() + " -----");out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));return false;}try {if (isDeprecated) {logger.error(LogUtils.getCommLog(String.format("該接口已停止使用,%s", servletPath)));}} catch (Exception e) {baseResp.getMsg().setRstcode(IMsgEnum.PARAMETER_INVALID.getMsgCode());baseResp.getMsg().setRsttext(IMsgEnum.PARAMETER_INVALID.getMsgText());logger.info("----- " + IMsgEnum.PARAMETER_INVALID.getMsgText() + " -----");out.write(JSONObject.toJSONString(baseResp).getBytes("UTF-8"));return false;}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {}} 可以針對某些具體的請求進行攔截。我這里沒做限制,所有的請求都走。

如果想攔截 特定的請求,判斷一下request.getContextPath()是否包含某個路徑。(后續更新)

我這里用到攔截器的作用是對回調接口進行統一的驗證簽名。
回調接口都需要驗證簽名,而且簽名規則一樣,所以想拿到攔截器處理。
如果簽名或者ip地址不符合條件,直接就返回了。而具體的接口只要專注業務處理,不需要驗證簽名了。

分享一下用的工具類:ip和簽名校驗:


signCheck.java:

package com.test.test.security;import java.util.Arrays; import java.util.List; import java.util.Map;import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component;import com.alibaba.fastjson.JSONObject; import com.test.test.config.ConfigProperties; import com.test.test.interceptor.PlatformInterceptor; import com.test.test.utils.Signature; import org.springframework.stereotype.Service;/** * @author gmwang E-mail: * @version 創建時間:2018年3月1日 上午10:35:47 * 類說明 :校驗簽名和ip */ @Service(value="signCheck") public class SignCheck{private static final Log logger = LogFactory.getLog(PlatformInterceptor.class);@Autowiredprivate ConfigProperties configProperties;@Beanpublic SignCheck getSignCheck(){return new SignCheck();}/*** 校驗簽名* @Description:* @author:* @throws IllegalAccessException * @time:2018年3月1日 上午10:38:09*/public static Boolean checkSign(Map params, String sign,String privateKey) throws IllegalAccessException {if(StringUtils.isBlank(sign)) {logger.info("*********************sign is null*********************");return false;}else {String signAfter = Signature.getSign(params,privateKey);System.out.println("sign:"+sign);System.out.println("signAfter:"+signAfter);if(!sign.equals(signAfter)) {logger.info("*********************sign is not equal signAfter*********************");return false;}}return true;}/*** 校驗ip* @Description:* @author:* @throws IllegalAccessException * @time:2018年3月1日 上午10:38:09*/public Boolean checkIpAddress(String ip) throws IllegalAccessException {String ipWhite = configProperties.getRequestUrl();System.out.println(ipWhite);String[] ipWhiteArray = ipWhite.split(",");List<String> ipWhiteList = Arrays.asList(ipWhiteArray);if(!ipWhiteList.contains(ip)) {logger.info("*********************ip is not in ipWhiteList*********************");return false;}return true;} } 獲取ip地址工具類:

NetworkUtil.java:

package com.test.test.utils;import java.io.IOException;import javax.servlet.http.HttpServletRequest;import org.apache.log4j.Logger;/** * 常用獲取客戶端信息的工具 * */ public final class NetworkUtil { /** * Logger for this class */ private static Logger logger = Logger.getLogger(NetworkUtil.class); /** * 獲取請求主機IP地址,如果通過代理進來,則透過防火墻獲取真實IP地址; * * @param request * @return * @throws IOException */ public final static String getIpAddress(HttpServletRequest request) throws IOException { // 獲取請求主機IP地址,如果通過代理進來,則透過防火墻獲取真實IP地址 String ip = request.getHeader("X-Forwarded-For"); if (logger.isInfoEnabled()) { logger.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip=" + ip); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); if (logger.isInfoEnabled()) { logger.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip=" + ip); } } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); if (logger.isInfoEnabled()) { logger.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip=" + ip); } } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); if (logger.isInfoEnabled()) { logger.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip=" + ip); } } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); if (logger.isInfoEnabled()) { logger.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip=" + ip); } } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); if (logger.isInfoEnabled()) { logger.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip=" + ip); } } } else if (ip.length() > 15) { String[] ips = ip.split(","); for (int index = 0; index < ips.length; index++) { String strIp = (String) ips[index]; if (!("unknown".equalsIgnoreCase(strIp))) { ip = strIp; break; } } } return ip; } } 加密解密工具類:

Signature.java:

package com.test.test.utils;import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map;import com.alibaba.fastjson.JSONObject;/*** User: * Date: 2015/8/26* Time: 15:23*/ public class Signature {/*** 簽名算法* @param o 要參與簽名的數據對象* @return 簽名* @throws IllegalAccessException*規則:簽名,將篩選的參數按照第一個字符的鍵值ASCII碼遞增排序(字母升序排序),如果遇到相同字符則按照第二個字符的鍵值ASCII碼遞增排序,以此類推,形成key=value& * skey的字符串MD5加密; (必填)*/public static String getSign(Object o) throws IllegalAccessException {ArrayList<String> list = new ArrayList<String>();Class cls = o.getClass();Field[] fields = cls.getDeclaredFields();for (Field f : fields) {f.setAccessible(true);if (f.get(o) != null && f.get(o) != "") {list.add(f.getName() + "=" + f.get(o) + "&");}}int size = list.size();String [] arrayToSort = list.toArray(new String[size]);Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);StringBuilder sb = new StringBuilder();for(int i = 0; i < size; i ++) {sb.append(arrayToSort[i]);}String result = sb.toString();System.out.println(result);result = MD5Util.MD5Encode(result).toUpperCase();System.out.println(result);return result;}public static String getSign(Map<String,Object> map,String privateKey){ArrayList<String> list = new ArrayList<String>();for(Map.Entry<String,Object> entry:map.entrySet()){if(entry.getValue()!=""){list.add(entry.getKey() + "=" + entry.getValue() + "&");}}int size = list.size();String [] arrayToSort = list.toArray(new String[size]);Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);StringBuilder sb = new StringBuilder();for(int i = 0; i < size; i ++) {sb.append(arrayToSort[i]);}sb.append(privateKey);String result = sb.toString();System.out.println(result);result = MD5Util.MD5Encode(result).toUpperCase();return result;}public static void main(String[] args) {/** */Map<String,Object> map=new HashMap();map.put("uuid","PC0000000056");String result= getSign(map,"aaaaa!aaa");System.out.println(result);map.put("sign", result);//signDESTools desTools = new DESTools();String s = JSONObject.toJSONString(map);System.out.println(s);String param= desTools.getEncString(s);String str= HttpUtil.doPost("http://localhost:8111/test/test", param);System.out.println(str);} }

DESTools.java:

package com.test.test.utils; import java.security.Key;import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import org.apache.commons.codec.binary.Base64;public class DESTools {public static DESTools instance;public static DESTools getInstace(){if(instance == null){instance = new DESTools();}return instance;}Key key;/*** 密鑰*/private static byte[] BOSS_SECRET_KEY = { 0x0b, 0x13, (byte) 0xe7,(byte) 0xb2, 0x51, 0x0d, 0x75, (byte) 0xc2, 0x4e, (byte) 0xdd,(byte) 0x4b, (byte) 0x51, 0x24, 0x36, (byte) 0xa8, (byte) 0x28,0x0b, 0x13, (byte) 0xe2, (byte) 0xb2, 0x31, 0x0d, 0x75, (byte) 0xc1 };public DESTools() {setKey(BOSS_SECRET_KEY);}/*** 根據參數生成KEY*/public void setKey(byte[] strKey) {try {DESKeySpec dks = new DESKeySpec(BOSS_SECRET_KEY);SecretKeyFactory keyFactory;keyFactory = SecretKeyFactory.getInstance("DES");this.key = keyFactory.generateSecret(dks);} catch (Exception e) {throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);}}/*** 加密String明文輸入,String密文輸出*/public String getEncString(String strMing) {byte[] byteMi = null;byte[] byteMing = null;String strMi = "";Base64 base64en = new Base64();try {byteMing = strMing.getBytes("UTF8");byteMi = this.getEncCode(byteMing);strMi = base64en.encodeAsString(byteMi);} catch (Exception e) {throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);} finally {base64en = null;byteMing = null;byteMi = null;}return strMi;}/*** 解密 以String密文輸入,String明文輸出* @param strMi* @return*/public String getDesString(String strMi) {Base64 base64De = new Base64();byte[] byteMing = null;byte[] byteMi = null;String strMing = "";try {byteMi = base64De.decode(strMi);byteMing = this.getDesCode(byteMi);strMing = new String(byteMing, "UTF8");} catch (Exception e) {throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);} finally {base64De = null;byteMing = null;byteMi = null;}return strMing;}/*** 加密以byte[]明文輸入,byte[]密文輸出* @param byteS* @return*/private byte[] getEncCode(byte[] byteS) {byte[] byteFina = null;Cipher cipher;try {cipher = Cipher.getInstance("DES");cipher.init(Cipher.ENCRYPT_MODE, key);byteFina = cipher.doFinal(byteS);} catch (Exception e) {throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);} finally {cipher = null;}return byteFina;}/*** 解密以byte[]密文輸入,以byte[]明文輸出* @param byteD* @return*/private byte[] getDesCode(byte[] byteD) {Cipher cipher;byte[] byteFina = null;try {cipher = Cipher.getInstance("DES");cipher.init(Cipher.DECRYPT_MODE, key);byteFina = cipher.doFinal(byteD);} catch (Exception e) {throw new RuntimeException("Error initializing DESTOOLS class. Cause: " + e);} finally {cipher = null;}return byteFina;}}

獲取yml文件的值:
ConfigProperties.java:

package com.test.test.config;import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.stereotype.Component;@Configuration @Component public class ConfigProperties {@Value("${test.test.privateKey}")private String privateKey;@Value("${test.test.requestUrl}")private String requestUrl;public String getPrivateKey() {return privateKey;}public void setPrivateKey(String privateKey) {this.privateKey = privateKey;}public String getRequestUrl() {return requestUrl;}public void setRequestUrl(String requestUrl) {this.requestUrl = requestUrl;}}

yml文件如圖:



2018-07-08 更新:

springboot 2.x 過濾器和攔截器 放行某個路徑(靜態資源):

package xxx.xxxx.config;import java.util.ArrayList; import java.util.List;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import xxx.xxxx.interceptor.PlatformInterceptor;@EnableWebMvc @Configuration @Component public class WebMvcConfig implements WebMvcConfigurer {@AutowiredPlatformInterceptor passportInterceptor;/*** 處理攔截器 攔截路徑(暫時無效)*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 多個攔截器組成一個攔截器鏈registry.addInterceptor(passportInterceptor).addPathPatterns("/**").excludePathPatterns("notify","/static/**");WebMvcConfigurer.super.addInterceptors(registry);}/*** 處理過濾器 靜態資源放行*/@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");WebMvcConfigurer.super.addResourceHandlers(registry);}/*** 利用fastjson替換掉jackson,且解決中文亂碼問題* @param converters*/@Overridepublic void configureMessageConverters(List<HttpMessageConverter<?>> converters) {FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();FastJsonConfig fastJsonConfig = new FastJsonConfig();fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);//處理中文亂碼問題List<MediaType> fastMediaTypes = new ArrayList<>();fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);fastConverter.setSupportedMediaTypes(fastMediaTypes);fastConverter.setFastJsonConfig(fastJsonConfig);converters.add(fastConverter);WebMvcConfigurer.super.configureMessageConverters(converters);}}


總結

以上是生活随笔為你收集整理的springboot中的拦截器interceptor和过滤器filter,多次获取request参数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。