从Spring Security不允许接收403方法

时间:2015-12-04 17:16:39

标签: angularjs spring spring-mvc spring-security

我正在使用AngularJS前端和Spring后端构建应用程序。我在前端和后端都有CSRF的所有设置,并且在我做出改变之前它工作正常。

当我登录我的应用程序时一切顺利,我登录/rest/user处的端点。当我注销403错误时,它就会被抛出。我在调试模式下将Spring Security打印到日志文件,我发现它在尝试验证CSRF令牌时失败了。我会继续解释我做了什么导致这种情况发生。

我作为Spring调度程序servlet的静态内容提供AngularJS应用程序,我不希望Spring Security保护该静态内容。我认为它在服务器上的负载更大。因此,我已将Spring Security Filter Chain入口点设置为我的其他服务映射到的位置,而不是应用程序的根目录。

这是我的web.xml的部分显示:

<servlet>
    <servlet-name>gravytrack</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

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

<servlet-mapping>
    <servlet-name>gravytrack</servlet-name>
    <url-pattern>*.*</url-pattern>
</servlet-mapping>

<!-- Security entry point -->
<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>/rest/*</url-pattern>
</filter-mapping>

由于此更改,我必须将我的退出网址映射到/rest/logout,而不是默认情况下Spring安全性将其映射到的普通/logout。这是我的安全配置显示:

<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:util="http://www.springframework.org/schema/util"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/util
                    http://www.springframework.org/schema/util/spring-util.xsd
                    http://www.springframework.org/schema/security
                    http://www.springframework.org/schema/security/spring-security.xsd">
    <global-method-security pre-post-annotations="enabled"
                            secured-annotations="enabled"/>

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/rest/**" requires-channel="https"/>
        <access-denied-handler error-page="/"/>
        <http-basic entry-point-ref="gtBasicAuthenticationEntryPoint"/>

        <!-- CRSF FILTER CONFIG -->
        <custom-filter ref="csrfHeaderFilter" after="CSRF_FILTER"/>
        <csrf token-repository-ref="csrfTokenRepository" />

        <!-- LOGOUT CONFIG -->
        <logout logout-url="/rest/logout" invalidate-session="true" delete-cookies="JSESSIONID"/>

        <!--<session-management invalid-session-url="/">-->
            <!--<concurrency-control max-sessions="10" error-if-maximum-exceeded="true" />-->
        <!--</session-management>-->

    </http>

    <!--<beans:bean id="gtBasicAuthenticationEntryPoint" class="com.gbsolutions.gravytrack.security.GtBasicAuthenticationEntryPoint">-->
        <!--<beans:property name="realmName" value="gravytrack" />-->
    <!--</beans:bean>-->

    <beans:bean id="csrfTokenRepository" class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository">
        <beans:property name="headerName" value="X-XSRF-TOKEN" />
    </beans:bean>


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

    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <!--<password-encoder ref="passwordEncoder"/>-->
            <!--<jdbc-user-service data-source-ref="dataSource"-->
                <!--users-by-username-query="SELECT email as username, password, enabled FROM user_account-->
                                            <!--WHERE email = ?" />-->
            <user-service>
                <user name="admin@admin.com" password="admin" authorities="ROLE_USER"/>
            </user-service>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

我有一个自定义过滤器,你可以在安全配置的这一行看到:

<custom-filter ref="csrfHeaderFilter" after="CSRF_FILTER"/>

这是我修改返回的cookie以获取为Angular定制的CSRF令牌的地方。这是csrfHeaderFilter类:

@Service("csrfHeaderFilter")
public class CsrfHeaderFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());

        if (csrf != null) {
            Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
            String token = csrf.getToken();
            if (cookie==null || token!=null && !token.equals(cookie.getValue())) {
                cookie = new Cookie("XSRF-TOKEN", token);
                cookie.setPath("/");
                response.addCookie(cookie);
            }
        }
        filterChain.doFilter(request, response);
    }
}

我认为问题与这一行有关:

cookie.setPath("/");

之前我遇到过类似的问题,我通过改变应用路径的路径修复了它。但是现在我的应用程序的路径是tomcat的根目录,因为我已经设置了tomcat。因此,https://localhost:8443/gravytrack只是https://localhost:8443/而不是/rest

我也尝试将路径更改为{{1}}(我的Spring Security的入口点),但这并没有帮助。可能导致403错误的原因是什么?

0 个答案:

没有答案