【问题标题】:HDIV + Spring Security 4: HDIV_PARAMETER_DOES_NOT_EXISTHDIV + Spring Security 4:HDIV_PARAMETER_DOES_NOT_EXIST
【发布时间】:2016-11-30 21:36:39
【问题描述】:

我有一个运行良好的 Spring 4 MVC + Security 应用程序。

我正在尝试将 HDIV 与其集成,并且已经通过文档和展示示例:https://github.com/hdiv/hdiv-spring-mvc-showcase/

当我使用 AvoidValidationInUrlsWithoutParams = true 时,一切正常,直到我没有参数(显然)。

当我删除该部分时,它只会将我带到安全错误页面。 我尝试调试,我看到 Spring Security 已成功验证 - 但 HDIV 抛出 HDIV_PARAMETER DOES NOT EXIST 错误 - 这就是我在日志中的内容:

2016-07-27 08:24:34 [http-apr-8080-exec-5] INFO  org.hdiv.logs.Logger - HDIV_PARAMETER_DOES_NOT_EXIST;/EmployeePortal/modules/dashboard.htm;177622190;;;127.0.0.1;127.0.0.1;MALLIKAM;

显然,我知道该页面从那里的数字中找到了 HDIV_STATE,但找不到 CSRF? (我假设这 3 个分号是 HDIV 试图找到的某个参数,而那个参数是 CSRF?)

另外,我可以在索引页面上看到生成的 csrf(这让我怀疑我是否正确设置了 HDIV,因为上次尝试它时,所有隐藏字段都会以不同的方式显示 - 要么是空白或者 0,如果我没记错的话。)

如果是这样,我想知道为什么以及我可以做些什么来解决它?

这是我目前所拥有的:

web.xml

 <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml, /WEB-INF/spring-security.xml, /WEB-INF/hdiv-config.xml, ...</param-value>
</context-param>

<listener>
    <listener-class>
              org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<!-- For HTTPSession events -->
<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

<!-- HDIV Listener -->
<listener>
    <listener-class>org.hdiv.listener.InitListener</listener-class>
</listener>

<filter>
    <filter-name>ValidatorFilter</filter-name>
    <filter-class>org.hdiv.filter.ValidatorFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ValidatorFilter</filter-name>
    <!-- Spring MVC Servlet name-->
    <servlet-name>serv1</servlet-name>
</filter-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

    <servlet>
    <servlet-name>serv1</servlet-name>
    <servlet-class>
                    org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-web-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>serv1</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<session-config>
    <session-timeout>30</session-timeout>
</session-config>

spring-security.xml

<!-- To let spring create login page -->
<http auto-config="false" disable-url-rewriting="true"
    use-expressions="true">

    <access-denied-handler ref="accessDeniedHandler" />

    <!-- CSRF is enabled by default Spring 4 onwards -->

    <!-- check roles -->
    <intercept-url pattern="/modules/favicon.ico" access="isAnonymous()" />
    <intercept-url pattern="/login.htm" access="isAnonymous()" />
    <intercept-url pattern="/login.htm?error" access="isAnonymous()" />
    <intercept-url pattern="/logout" access="isAnonymous()" />
    <intercept-url pattern="/modules/**" access="hasAnyRole('ROLE_y','ROLE_x')" />

    <form-login login-page="/" default-target-url="/modules/dashboard.htm"
        username-parameter="username" password-parameter="password"
        authentication-failure-url="/login.htm?error" />


    <custom-filter after="SECURITY_CONTEXT_FILTER" ref="hdivFilter" />

    <!-- Logout -->
    <logout logout-url="/logout.htm" delete-cookies="JSESSIONID"
        invalidate-session="true" logout-success-url="/login.htm" />

    <!-- Session Management: Invalid Session Url is for SessionTimeout as well 
        as invalid login -->
    <session-management session-fixation-protection="newSession"
        invalid-session-url="/login.htm" session-authentication-error-url="/login.htm">

        <!-- Concurrency control is to check number of sessions and act accordingly. 
            Error If Max exceeded stops a user from logging in if max-sessions have been 
            exceeded. Expired Url is different from invalid url. -->
        <concurrency-control max-sessions="2"
            expired-url="/login.htm" error-if-maximum-exceeded="true" />
    </session-management>

</http>

<!-- Spring security authentication manager -->
<authentication-manager alias="authenticationManager">
    <!-- Custom Auth Provider checks for login with DB and LDAP both -->
    <authentication-provider ref="customAuthenticationProvider">
    </authentication-provider>
</authentication-manager>

<!-- Bean implements AuthenticationProvider and checks if user is valid -->
<beans:bean id="customAuthenticationProvider"
    class="..employeeportal.common.util.CustomAuthenticationProvider">
    <beans:property name="passwordEncoder" ref="encoder" />
</beans:bean>

<!-- BCrypt Password encoder -->
<beans:bean id="encoder"
    class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />

<!-- Access Denied Handler -->
<beans:bean id="accessDeniedHandler"
    class="..employeeportal.common.util.AccessDeniedHandler">
</beans:bean>

<beans:bean id="hdivFilter" class="org.hdiv.filter.ValidatorFilter" />

spring-web-config.xml

<mvc:annotation-driven validator="hdivEditableValidator"/>

...

applicationContext.xml

...拥有所有service/dao层组件扫描线:

<context:component-scan
    base-package="..common.service, ..common.dao" />

hdiv-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:hdiv="http://www.hdiv.org/schema/hdiv"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.1.xsd 
   http://www.hdiv.org/schema/hdiv http://www.hdiv.org/schema/hdiv/hdiv.xsd">

<hdiv:config excludedExtensions="css,ico,js,woff,woff2,ttf,jpg,jpeg,png,gif,eot"
    errorPage="/security-error" randomName="true" confidentiality="true" debugMode="true">
    <hdiv:startPages method="get">/,/login.htm</hdiv:startPages>
    <hdiv:startPages method="post">/logout, /logout.htm</hdiv:startPages>
    <hdiv:startParameters>_csrf</hdiv:startParameters>
</hdiv:config>

<!-- Accepted pattern within the application for all editable parameters (generated from textbox and textarea) -->
<hdiv:validation id="safeText">
    <hdiv:acceptedPattern><![CDATA[^[a-zA-Z0-9@.\-_]*$]]></hdiv:acceptedPattern>
</hdiv:validation>

<!-- Finally, it's necessary to define editable data validation list for 
    the application -->
<hdiv:editableValidations>
    <hdiv:validationRule url="/modules/.*"></hdiv:validationRule>
    <hdiv:validationRule url="/modules/.*"  enableDefaults="false">safeText</hdiv:validationRule>
</hdiv:editableValidations>

index.jsp

<form:form name='loginForm' modelAttribute="loginForm"
                    action="login" method='POST'>

                    <div class="form-group">
                        <div class="input-group">
                            <span class="input-group-addon"><i class="fa fa-user"></i></span>

                            <form:input path="username" name="username" id="username"/>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="input-group">

                            <form:input path="password" id="password" name="password"/>
                        </div>
                    </div>
                    <div class="form-group no-border margin-top-20">
                        <input type="submit"
                            class="btn btn-success btn-block" value="Submit" />
                    </div>
                </form:form>

任何帮助将不胜感激。

【问题讨论】:

    标签: spring-mvc spring-security csrf hdiv


    【解决方案1】:

    看来问题与CSRF无关。

    Hdiv 验证所有传入的请求,为了做到这一点,所有 URL 和参数都必须使用一些受支持的技术(例如 Spring MVC 标签)在服务器端呈现。

    您是否使用 Spring MVC URL 标签来呈现包含在错误文件中的 URL?

    一旦您为此使用 Spring MVC 标记,Hdiv 将在 URL 中包含一个附加参数 (HDIV_STATE),您将避免该问题。

    此参数可以防止对已定义 URL 的任何篡改攻击。

    其他可能的解决方案是使用 URL 排除项消除对特定 URL 或 URls 类型的验证,其中 Hdiv 不会验证这些 URL。

    见这个例子:https://github.com/hdiv/hdiv-spring-mvc-showcase-jc/blob/master/src/main/java/org/hdiv/samples/mvc/config/HdivSecurityConfig.java 在 addExclusions 方法中定义了不同的排除项。

    问候,

    罗伯托·贝拉斯科

    Hdiv 安全

    【讨论】:

    • 我也有同样的问题,但我不知道你对 MVC URL Tag 的含义以及我需要更改的内容。您可以添加更多详细信息吗?谢谢
    【解决方案2】:

    我找到了解决方案。 HDIV 要求所有链接都在其 URL 中使用“_HDIV_STATE_”参数进行丰富。为了实现这一点,您必须使用 HDIV 中的 taglib 而不是原始的 JSTL taglib。

    另请参考HDIV的reference documentation

    例如在你的 POM 中

        <dependency>
            <groupId>org.hdiv</groupId>
            <artifactId>hdiv-jstl-taglibs-1.2</artifactId>
            <version>${org.hdiv-version}</version>
        </dependency>
    

    例如在您的 JSP 中(注意 taglib 语句中的“www.hdiv.org”)

    <%@ taglib prefix="c" uri="http://www.hdiv.org/jsp/jstl/core"%> <c:url value="/messages/messages" var="url" /> <li><a href="${url}">Messages</a></li>

    因此,您需要通过 &lt;c:url&gt; 实用程序标签呈现 URL。这会呈现带有所需 HDIV 参数的 URL,即

    localhost:8080/spring-security-example/messages/message?_HDIV_STATE_=26-0-830046F08D66980D1B35F52F2D6677E0
    

    另一个选项可能是使用 HDIV 中的实用程序类, 另请参阅 hdiv 的 github 存储库中的 class LinkUrlProcessor

    LinkUrlProcessor urlProcessor = HDIVUtil.getLinkUrlProcessor(servletContext);
    String processUrl = urlProcessor.processUrl(request, "/messages/messages");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-16
      • 2015-10-22
      • 2012-12-05
      • 1970-01-01
      • 2017-05-30
      • 2015-11-26
      • 2016-09-12
      • 1970-01-01
      相关资源
      最近更新 更多