Springboot中路徑參數帶 (%2F)的問題徹底解決方案
徹底解決Springboot中路徑參數帶/(%2F)的問題
背景
前兩天突然出現(xiàn)了一個線上問題,有同事反應我提供的接口報400的錯誤。接口路徑如下 PATCH /v1/basic/owners/{owner_code}/skus/{sku}
,經過排查發(fā)現(xiàn)是sku參數中有/
因此springboot轉義后直接報錯了。由于已經有很多團隊對接了相關接口,且有很多的其他接口都使用了類似的傳參方式,因此需要考慮怎么在系統(tǒng)中不讓springboot自動解碼
解決方案
我先列出可用的解決方案,然后在列出網上常見錯誤方案
在項目中添加環(huán)境變量
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
1.關閉spring自動decode url的開關
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper urlPathHelper = new UrlPathHelper(); urlPathHelper.setUrlDecode(false); configurer.setUrlPathHelper(urlPathHelper); } }
1.開啟Spring security中允許url中存在/的功能(如果項目中沒有用到Spring security 可跳過此配置)
@Order(Ordered.LOWEST_PRECEDENCE) @Configuration public class SecurityFirewallConfig extends WebSecurityConfigurerAdapter { @Bean public HttpFirewall allowUrlEncodedSlashHttpFirewall() { DefaultHttpFirewall firewall = new DefaultHttpFirewall(); firewall.setAllowUrlEncodedSlash(true); return firewall; } }
注意大部分項目中都有Spring security相關的設置,所以這里注意一下優(yōu)先級
在項目中配置好這三項后,url中的參數已經可以正常解析了(注意需要讓接口使用法把帶/的參數encode之后再調用我們的接口)
常見的錯誤答案
1.使用正則匹配獲取參數
@PostMapping("/v1/basic/owner-code/{ownerCode}/skus/{sku:.+}/ext-info") public ResponseEntity<String> getInfo(@PathVariable("ownerCode") String ownerCode, @PathVariable("sku") String sku) { // your logic here }
這里的.+只是一個示例,還有很多種正則的寫法。這是很多人的博客中被提及的方案,但并不能解決問題
1.覆蓋Spring MVC默認URL解碼行為的配置類
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { UrlPathHelper urlPathHelper = new UrlPathHelper() { @Override public Map<String, String> decodePathVariables(HttpServletRequest request, Map<String, String> vars) { return vars; } }; urlPathHelper.setUrlDecode(false); configurer.setUrlPathHelper(urlPathHelper); } }
看起來很有效,實際上也不行
1.使用@MatrixVariable接受參數
@PostMapping("/v1/basic/owner-code/{ownerCode}/skus/{sku:.+}/ext-info") public ResponseEntity<String> getInfo(@PathVariable("ownerCode") String ownerCode, @MatrixVariable("sku") String sku) { // your logic here }
1.自定義filter并添加到spring中
public class UrlEncodingFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; String url = request.getRequestURL().toString(); // 如果你的SKU部分總是在URL的特定位置,可以使用這種方式來找到它并進行二次編碼 String encodedUrl = url.replace("skus/", "skus/").replace("/ext-info", "%2Fext-info"); HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) { @Override public StringBuffer getRequestURL() { return new StringBuffer(encodedUrl); } }; chain.doFilter(requestWrapper, res); } }
到此這篇關于徹底解決Springboot中路徑參數帶 (%2F)的問題的文章就介紹到這了,更多相關Springboot路徑參數帶 (%2F)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring?Boot?MQTT?Too?many?publishes?in?progress錯誤的解決方
本文介紹Spring?Boot?MQTT?Too?many?publishes?in?progress錯誤的解決方案,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下2022-07-07Java實現(xiàn)為Word每一頁設置不同圖片水印的效果
Word中設置水印時,可加載圖片設置為水印效果,但通常添加水印效果時,會對所有頁面都設置成統(tǒng)一效果。所以本文為大家介紹了一個方法,可以實現(xiàn)對每一頁或者某個頁面設置不同的水印效果,需要的可以參考一下2022-02-02