• spring-security使用-安全防护HttpFirewall(七)


    类图

     默认提供2种实现 defaultfHttpFirewall 看源码可以看出来比较宽松,我们一般使用StrictHttpFirewall

    限制请求方法

    如果需要修改可以自定义StrictHttpFirewall 

    public class StrictHttpFirewall implements HttpFirewall {
        //空的集合
        private static final Set<String> ALLOW_ANY_HTTP_METHOD = Collections.unmodifiableSet(Collections.emptySet());
        private Set<String> allowedHttpMethods = createDefaultAllowedHttpMethods();
        //设置允许的请求方式
        private static Set<String> createDefaultAllowedHttpMethods() {
            Set<String> result = new HashSet();
            result.add(HttpMethod.DELETE.name());
            result.add(HttpMethod.GET.name());
            result.add(HttpMethod.HEAD.name());
            result.add(HttpMethod.OPTIONS.name());
            result.add(HttpMethod.PATCH.name());
            result.add(HttpMethod.POST.name());
            result.add(HttpMethod.PUT.name());
            return result;
        }
        public void setUnsafeAllowAnyHttpMethod(boolean unsafeAllowAnyHttpMethod) {
            //如果是false则设置空的集合
            this.allowedHttpMethods = unsafeAllowAnyHttpMethod ? ALLOW_ANY_HTTP_METHOD : createDefaultAllowedHttpMethods();
        }
    
        private void rejectForbiddenHttpMethod(HttpServletRequest request) {
            if (this.allowedHttpMethods != ALLOW_ANY_HTTP_METHOD) {
                //如果不存在运行的方法里面 则抛出异常
                if (!this.allowedHttpMethods.contains(request.getMethod())) {
                    throw new RequestRejectedException("The request was rejected because the HTTP method "" + request.getMethod() + "" was not included within the whitelist " + this.allowedHttpMethods);
                }
            }
        }
    }

    使用方式

    @Bean
    HttpFirewall httpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        firewall.setUnsafeAllowAnyHttpMethod(true);
        return firewall;
    }

    请求地址不能有分号

    如地址:http://localhost:8080/index;id=ddd

    public class StrictHttpFirewall implements HttpFirewall {
        private Set<String> encodedUrlBlacklist = new HashSet();
        private Set<String> decodedUrlBlacklist = new HashSet();
    
        //;的urlecod和decode的几种
        private static final List<String> FORBIDDEN_SEMICOLON = Collections.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));
        public void setAllowSemicolon(boolean allowSemicolon) {
            //如果是false则删除调
            if (allowSemicolon) {
                this.urlBlacklistsRemoveAll(FORBIDDEN_SEMICOLON);
            } else {
                this.urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
            }
        }
        //加入到校验list
        private void urlBlacklistsAddAll(Collection<String> values) {
            this.encodedUrlBlacklist.addAll(values);
            this.decodedUrlBlacklist.addAll(values);
        }
        //清除到校验list
        private void urlBlacklistsRemoveAll(Collection<String> values) {
            this.encodedUrlBlacklist.removeAll(values);
            this.decodedUrlBlacklist.removeAll(values);
        }
    
        private void rejectedBlacklistedUrls(HttpServletRequest request) {
            Iterator var2 = this.encodedUrlBlacklist.iterator();
    
            String forbidden;
            do {
                if (!var2.hasNext()) {
                    var2 = this.decodedUrlBlacklist.iterator();
    
                    do {
                        if (!var2.hasNext()) {
                            return;
                        }
    
                        forbidden = (String)var2.next();
                    } while(!decodedUrlContains(request, forbidden));
    
                    throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String "" + forbidden + """);
                }
    
                forbidden = (String)var2.next();
            } while(!encodedUrlContains(request, forbidden));
    
            throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String "" + forbidden + """);
        }
    }

    必须是可打印的 ASCII 字符

    private static boolean containsOnlyPrintableAsciiCharacters(String uri) {
        int length = uri.length();
        for (int i = 0; i < length; i++) {
            char c = uri.charAt(i);
            if (c < 'u0020' || c > 'u007e') {
                return false;
            }
        }
        return true;
    }

    不能使用双斜杠

    @Bean
    HttpFirewall httpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        firewall.setAllowUrlEncodedDoubleSlash(true);
        return firewall;
    }

    % 不被允许

    如果需要去掉

    @Bean
    HttpFirewall httpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
    //允许%的配置 firewall.setAllowUrlEncodedPercent(
    true); return firewall; }

    反斜杠不被允许

    如果需要去掉

    @Bean
    HttpFirewall httpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        firewall.setAllowBackSlash(true);
        firewall.setAllowUrlEncodedSlash(true);
        return firewall;
    }

    . 不被允许

    如果需要去掉

    @Bean
    HttpFirewall httpFirewall() {
        StrictHttpFirewall firewall = new StrictHttpFirewall();
        firewall.setAllowUrlEncodedPeriod(true);
        return firewall;
    }

    入口处

      public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
            this.rejectForbiddenHttpMethod(request);
            this.rejectedBlacklistedUrls(request);
            this.rejectedUntrustedHosts(request);
            if (!isNormalized(request)) {
                throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
            } else {
                String requestUri = request.getRequestURI();
                if (!containsOnlyPrintableAsciiCharacters(requestUri)) {
                    throw new RequestRejectedException("The requestURI was rejected because it can only contain printable ASCII characters.");
                } else {
                    return new FirewalledRequest(request) {
                        public void reset() {
                        }
                    };
                }
            }
        }
  • 相关阅读:
    Untiy数据包的输出、加载和卸载
    Line 7.10 : Syntax error
    给力的数学巧算法!
    Unity3d + NGUI 的多分辨率适配
    Linq小记
    (转)为C# Windows服务添加安装程序
    Javamail使用代码整理
    .NET后台访问其他站点代码整理
    (转)2009-05-25 22:12 Outlook2007选择发送帐号
    (转)C#与Outlook交互收发邮件
  • 原文地址:https://www.cnblogs.com/LQBlog/p/14343497.html
Copyright © 2020-2023  润新知