今天有个接口打算使用矩阵变量来绑定参数,即使用@MatrixVariable注解来接收参数

调用接口后项目报了如下错误

org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"

完成的异常栈轨迹如下

org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"
at org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlacklistedUrls(StrictHttpFirewall.java:369) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:336) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:194) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108) ~[spring-boot-actuator-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) ~[undertow-core-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) ~[undertow-core-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) ~[undertow-core-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.SessionRestoringHandler.handleRequest(SessionRestoringHandler.java:119) ~[undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99) [undertow-servlet-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376) [undertow-core-2.0.28.Final.jar:2.0.28.Final]
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830) [undertow-core-2.0.28.Final.jar:2.0.28.Final]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]

解决方法

  前提,springmvc默认不能用矩阵变量,所以记得开启,springboot可以用如下方式开启

@Configuration
public class WebMvcAuthConfig implements WebMvcConfigurer { @Override
public void configurePathMatch(PathMatchConfigurer configurer) {
UrlPathHelper urlPathHelper=new UrlPathHelper();
urlPathHelper.setRemoveSemicolonContent(false);
configurer.setUrlPathHelper(urlPathHelper);
}
}

  然后如果出现了标题的异常可以加入如下配置即可解决

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override
public void configure(WebSecurity web) throws Exception {
StrictHttpFirewall firewall = new StrictHttpFirewall();
//去掉";"黑名单
firewall.setAllowSemicolon(true);
//加入自定义的防火墙
web.httpFirewall(firewall);
super.configure(web);
}
}

闲的同学可以看下解决思路

解决思路

通过异常信息大概可以得知是因为url中带入了“;”符号所以请求地址非法,我们看下最近的报错的类StrictHttpFirewall 中369行的方法

private void rejectedBlacklistedUrls(HttpServletRequest request) {
for (String forbidden : this.encodedUrlBlacklist) {
//如果url中有黑名单的符号就报异常
if (encodedUrlContains(request, forbidden)) {
throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\"");
}
}
for (String forbidden : this.decodedUrlBlacklist) {
if (decodedUrlContains(request, forbidden)) {
throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\"");
}
}
}

其中有个encodedUrlBlacklist就是所有的非法字符黑名单了,这儿会过滤所有非法字符,我们debug看下里面有哪些

果然第14个有";"符号,按理说springmvc既然有这个注解应该不至于自己定义为非法,查看该类的包名

package org.springframework.security.web.firewall

看包名也很明确了,项目因为使用了spring security有关的东西,这儿应该是spring security默认url不能带";"符号。有同学会想那我可不可以使用url编码躲开这个过滤?  当然了框架肯定是想到了这点儿,“;”进行url编码后为3b%,就是上图中第8个和第9个  (汗 连大小写都考虑到了  。。),所以我们肯定还是需要看到底那儿使用的这个类,能不能在项目初始化时将";"从黑名单中移除。

我们在StrictHttpFirewall中搜寻,看下哪些地方涉及到了";"符号   发现如下

public class StrictHttpFirewall implements HttpFirewall {
............ private static final List<String> FORBIDDEN_SEMICOLON = Collections.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));
............
public StrictHttpFirewall() {
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
...
} private void urlBlacklistsAddAll(Collection<String> values) {
this.encodedUrlBlacklist.addAll(values);
this.decodedUrlBlacklist.addAll(values);
}
}

可以很明确的看到  该类在初始化的时候就将";" 添加到了encodedUrlBlacklist中,但是该类中还存在一个方法

    public void setAllowSemicolon(boolean allowSemicolon) {
if (allowSemicolon) {
urlBlacklistsRemoveAll(FORBIDDEN_SEMICOLON);
} else {
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
}
}

该方法目的相信已经相当明确了,调用该方法,就能将";"从黑名单中移除。那解决思路就应该有如下的步骤   ,找到使用该类的地方,然后找到创建对象的地方,调用这个移除黑名单方法将其移出黑名单。

那该如何找到调用的地方呢,其实异常轨迹中已经很明确了,截取前面几行和security有关的异常方法轨迹,

org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"
at org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlacklistedUrls(StrictHttpFirewall.java:369) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:336) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:194) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]

  通过这几行信息可以发现大概是security在执行过滤器的时候FilterChainProxy对象使用了StrictHttpFirewall类的过滤方法,那我们直接从FilterChainProxy最下面的那个doFilter方法开始看

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
if (clearContext) {
try {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
doFilterInternal(request, response, chain);
}
finally {
SecurityContextHolder.clearContext();
request.removeAttribute(FILTER_APPLIED);
}
}
else {
doFilterInternal(request, response, chain);
}
}

  这儿没有找到和StrictHttpFirewall有关的信息,我们接着看下一个doFilterInternal方法

private void doFilterInternal(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//这儿会执行firewall(StrictHttpFirewall)里面的黑名单过滤方法
FirewalledRequest fwRequest = firewall
.getFirewalledRequest((HttpServletRequest) request);
HttpServletResponse fwResponse = firewall
.getFirewalledResponse((HttpServletResponse) response);
...............
}

  这儿我们看到了和firewall有关的东西了,我们看下这个属性

private HttpFirewall firewall = new StrictHttpFirewall();

  看来就是这个FilterChainProxy对象里默认声明了一个StrictHttpFirewall并执行了黑名单过滤方法,那我们需要修改的就是这个属性了,感觉已经成功了一半了。

那我们如何修改这个属性?   还是可以先看下类里面是否有赋值的方法,我们查看FilterChainProxy对象后发现有如下地方的代码可以自己设置firwall

    public void setFirewall(HttpFirewall firewall) {
this.firewall = firewall;
}

看来FilterChainProxy中有自己设置HttpFirewall 地方,那我们现在的目的又变成了   找到FilterChainProxy初始化的地方,自己初始化一个StrictHttpFirewall对象并执行其setAllowSemicolon(true)方法,然后将这个firewall塞到FilterChainProxy中。

springsecutiry既然默认禁止  又提供了消除黑名单方法 ,那说明肯定有能配置的地方。我们使用idea全局搜索下,是否有地方使用了这个setFirewall方法,果然就搜索到了

看到这个相信大家就知道应该怎么办了,使用过spring secutiry的同学相信不会对WebSecurity这个类陌生。这个类保存spring security的一些核心配置。我们看下这个类中setFirewall片段

...........
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (httpFirewall != null) {
filterChainProxy.setFirewall(httpFirewall);
}
filterChainProxy.afterPropertiesSet(); .........

  可以发现就是这儿判断是否有自定义的httpFirewall   如果有就传入自定义的,如果没有那就使用上面的FilterChainProxy对象初始化时的StrictHttpFirewall 。

    private HttpFirewall httpFirewall;
    public WebSecurity httpFirewall(HttpFirewall httpFirewall) {
this.httpFirewall = httpFirewall;
return this;
}

  该类是没有初始化定义防火墙的,但是给了httpFirewall方法可以传入自定义的HttpFirewall 。所以我们到这儿就找到了最终的解决方案了,就是配置WebSecurity 。熟悉spring secutiry的同学都知道spring secutiry有专门的初始化抽象配置类WebSecurityConfigurerAdapter   ,就像springmvc的WebMvcConfigurerAdapter一样。我们来看下WebSecurityConfigurerAdapter

果然在里面找到了可以配置webSecurity的方法 ,所以我们就直接继承这个类  然后重写这个方法

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override
public void configure(WebSecurity web) throws Exception {
StrictHttpFirewall firewall = new StrictHttpFirewall();
//去掉";"黑名单
firewall.setAllowSemicolon(true);
//加入自定义的防火墙
web.httpFirewall(firewall);
super.configure(web);
}
}

这个时候重启项目再调用接口   调用   localhost:8081/api/car/vehicle/test/8008208820;lon=23.203;lat=26.302

已经能够成功获取到了

  

security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"的更多相关文章

  1. The request was rejected because the URL contained a potentially malicious String ";"报错解决

    报错信息 浏览器中看到的报错 错误摘要: The request was rejected because the URL contained a potentially malicious Stri ...

  2. SpringBoot整合升级Spring Security 报错 【The request was rejected because the URL was not normalized】

    前言 最近LZ给项目框架升级, 从Spring1.x升级到Spring2.x, 在这里就不多赘述两个版本之间的区别以及升级的原因. 关于升级过程中踩的坑,在其他博文中会做比较详细的记录,以便给读者参考 ...

  3. spring boot The request was rejected because the URL was not normalized

    升级spring boot 1.5.10.RELEASE 版本后,突然发现之前能Nginx代理能请求的地址抛如下异常: org.springframework.security.web.firewal ...

  4. FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (112503036) exceeds the configured

    Message:  FAIL - Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.FileUpload ...

  5. 使用postman模拟上传文件到springMVC的坑:the request was rejected because no multipart boundary was found

    参考该文解决问题:http://blog.csdn.net/sanjay_f/article/details/47407063 报错 threw exception [Request processi ...

  6. org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected be

    1.错误描写叙述 八月 14, 2015 3:03:05 下午 com.opensymphony.xwork2.util.logging.jdk.JdkLogger warn 警告: Request ...

  7. Web开发-Servlet&HTTP&Request

    <!doctype html>02 - JavaEE - Servlet&HTTP&Request figure:first-child { margin-top: -20 ...

  8. Atitit.面向接口的web 原理与设计重写 路由启动绑定配置url router rewriting urlpage  mvc mvp的 java c#.net php js

    Atitit.面向接口的web 原理与设计重写 路由启动绑定配置url router rewriting urlpage  mvc mvp的 java c#.net php js 原理 通过vm带入启 ...

  9. [Security] Web Security Essentials

    In this course, we'll learn how to exploit and then mitigate several common Web Security Vulnerabili ...

随机推荐

  1. 转载:Bass management

    https://kenrockwell.com/audio/bass-management.htm https://www.axiomaudio.com/blog/bassmanagement htt ...

  2. 【C语言】用C语言输出一个吃豆人

    大圆盘减去扇形和小圆盘: #include <math.h> #include <stdio.h> int main() { double x, y; ; y >= -; ...

  3. Unity Coroutine详解(二)

    •        介绍•        Part 1. 同步等待•        Part 2. 异步协程•        Part 3. 同步协程•        Part 4. 并行协程 1.介绍 ...

  4. Windows使用nmake和Makefile编译c++

    今天在本地看到一个lsd_1.6的源文件,不知道什么时候看LSD时下载的,里面只有一个Makefile和源文件. 想到在Linux下可以只用一个make命令就可以得到可执行程序,在Windows下是不 ...

  5. C9300升级-USB

    1.show ver查看设备的版本 2.一些版本信息的参考 3.准备USB查看其具备的镜像命令:dir usbflash0: 4.复制镜像到设备命令:copy usbflash0:cat9k_iosx ...

  6. java读/写文件

    读取文件参考:https://blog.csdn.net/weixin_42129373/article/details/82154471 写入文件参考:https://blog.csdn.net/B ...

  7. P2023 [AHOI2009]维护序列 区间加乘模板

    题意: 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式:N<=1e5(1)把数列中的一段数全部乘一个值;(2)把数列中的一段数全部加一个值;(3)询问数列中的一段数的和,由于 ...

  8. 使用Newtonsoft序列化对象,实现深拷贝

    工作记录 深拷贝:全新创建一个对象,值与复制对象一致,两个对象互不相关,修改一个对象不会影响到另一个对象 浅拷贝:全新创建一个对象,值与复制对象一致,两个对象相关,修改一个对象影响到另一个对象 在工作 ...

  9. oracle创建、删除索引等操作

    1.创建索引 create index 索引名 on 表名(列名); 2.删除索引 drop index 索引名; 3.创建组合索引 create index 索引名 on 表名(列名1,,列名2); ...

  10. cJson 常见用法

    cJson是一个非常轻量级的JSON数据解析和构建的oss. 可以很容易的的在C代码中构建一个JSON格式的字符串.也可以将JSON字符串转成cJson中定义的cJson object. 通常用在,手 ...