zoukankan      html  css  js  c++  java
  • security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String ";"

    今天有个接口打算使用矩阵变量来绑定参数,即使用@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

     已经能够成功获取到了

      

  • 相关阅读:
    pytorch torchversion标准化数据
    pytorch 中HWC转CHW
    pytorch torchversion自带的数据集
    pytorch Dataset数据集和Dataloader迭代数据集
    pytorch Model Linear实现线性回归CUDA版本
    pytorch实现手动线性回归
    pytorch中的前项计算和反向传播
    pytorch中CUDA类型的转换
    pytorch中tensor的属性 类型转换 形状变换 转置 最大值
    LightOJ 1074 spfa判断负环
  • 原文地址:https://www.cnblogs.com/hetutu-5238/p/12145379.html
Copyright © 2011-2022 走看看