gpt4 book ai didi

当要发送的请求是多部分请求时,Spring CSRF token 不起作用

转载 作者:行者123 更新时间:2023-12-04 08:52:27 32 4
gpt4 key购买 nike

我用,

  • Spring Framework 4.0.0发行(GA)
  • Spring Security 3.2.0 RELEASE(GA)
  • Struts 2.3.16

  • 其中,我使用内置的安全 token 来防御CSRF攻击。

    Struts表单如下所示。
    <s:form namespace="/admin_side"
    action="Category"
    enctype="multipart/form-data"
    method="POST"
    validate="true"
    id="dataForm"
    name="dataForm">

    <s:hidden name="%{#attr._csrf.parameterName}"
    value="%{#attr._csrf.token}"/>
    </s:form>

    生成的HTML代码如下。
    <form id="dataForm"
    name="dataForm"
    action="/TestStruts/admin_side/Category.action"
    method="POST"
    enctype="multipart/form-data">

    <input type="hidden"
    name="_csrf"
    value="3748c228-85c6-4c3f-accf-b17d1efba1c5"
    id="dataForm__csrf">
    </form>

    正常工作,除非请求是多部分,在这种情况下,请求以状态码403结束。

    HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

    type Status report

    message Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

    description Access to the specified resource has been forbidden.


    spring-security.xml文件如下。
    <?xml version="1.0" encoding="UTF-8"?>
    <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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <http pattern="/Login.jsp*" security="none"></http>

    <http auto-config='true' use-expressions="true" disable-url-rewriting="true" authentication-manager-ref="authenticationManager">
    <session-management session-fixation-protection="newSession">
    <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
    </session-management>

    <csrf/>

    <headers>
    <xss-protection />
    <frame-options />
    <!--<cache-control />-->
    <!--<hsts />-->
    <content-type-options /> <!--content sniffing-->
    </headers>

    <intercept-url pattern="/admin_side/**" access="hasRole('ROLE_ADMIN')" requires-channel="any"/>
    <form-login login-page="/admin_login/Login.action" authentication-success-handler-ref="loginSuccessHandler" authentication-failure-handler-ref="authenticationFailureHandler"/>
    <logout logout-success-url="/admin_login/Login.action" invalidate-session="true" delete-cookies="JSESSIONID"/>
    </http>

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

    <beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>
    <beans:property name="passwordEncoder" ref="encoder" />
    </beans:bean>

    <beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <beans:property name="providers">
    <beans:list>
    <beans:ref bean="daoAuthenticationProvider" />
    </beans:list>
    </beans:property>
    </beans:bean>

    <authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
    </authentication-provider>
    </authentication-manager>

    <beans:bean id="loginSuccessHandler" class="loginsuccesshandler.LoginSuccessHandler"/>
    <beans:bean id="authenticationFailureHandler" class="loginsuccesshandler.AuthenticationFailureHandler" />

    <global-method-security secured-annotations="enabled" proxy-target-class="false" authentication-manager-ref="authenticationManager">
    <protect-pointcut expression="execution(* admin.dao.*.*(..))" access="ROLE_ADMIN"/>
    </global-method-security>
    </beans:beans>

    那么,当请求是多部分时,在哪里寻找该 token ? (这根本不应该与Struts相关。)

    如果需要,可以在我的 this早期问题中找到 UserDetailsService的实现。

    Placing MultipartFilter before Spring Security也无济于事。
    web.xml文件如下所示。
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

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

    <filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
    </filter>

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

    <filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <servlet-name>/*</servlet-name>
    </filter-mapping>

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

    <filter>
    <filter-name>AdminLoginNocacheFilter</filter-name>
    <filter-class>filter.AdminLoginNocacheFilter</filter-class>
    </filter>

    <filter-mapping>
    <filter-name>AdminLoginNocacheFilter</filter-name>
    <url-pattern>/admin_login/*</url-pattern>
    </filter-mapping>

    <filter>
    <filter-name>NoCacheFilter</filter-name>
    <filter-class>filter.NoCacheFilter</filter-class>
    </filter>

    <filter-mapping>
    <filter-name>NoCacheFilter</filter-name>
    <url-pattern>/admin_side/*</url-pattern>
    </filter-mapping>

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

    <listener>
    <description>Description</description>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

    <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>

    <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    <init-param>
    <param-name>struts.devMode</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>

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

    <session-config>
    <session-timeout>
    30
    </session-timeout>
    </session-config>
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    </web-app>

    仅当将 token 作为如下的查询字符串参数附加时才有效,但不鼓励这样做。
    <s:form namespace="/admin_side"
    action="Category?%{#attr._csrf.parameterName}=%{#attr._csrf.token}"
    enctype="multipart/form-data"
    method="POST"
    validate="true"
    id="dataForm"
    name="dataForm">
    ...
    <s:form>

    最佳答案

    如果您使用@annotations,并且jsp View 是这样的:

        <form:form id="profileForm" action="profile?id=${param.id}" method="POST" 
    modelAttribute="appUser" enctype="multipart/form-data" >
    ...
    <input type="file" name="file">
    ...
    <input type="hidden" name="${_csrf.parameterName}"
    value="${_csrf.token}" />
    </form:form>

    这可能会有所帮助:

    AppConfig.java:
    @EnableWebMvc
    @Configuration
    @Import({ SecurityConfig.class })
    public class AppConfig {

    @Bean(name = "filterMultipartResolver")
    public CommonsMultipartResolver filterMultipartResolver() {
    CommonsMultipartResolver filterMultipartResolver = new CommonsMultipartResolver();
    filterMultipartResolver.setDefaultEncoding("utf-8");
    // resolver.setMaxUploadSize(512000);
    return filterMultipartResolver;
    }
    ...

    SecurityConfig.java扩展了WebSecurityConfigurerAdapter,并且是SpringSecurity的配置。

    需要在启用CSRF的SecurityConfig之前注册多部分/表单数据过滤器(MultipartFilter)。您可以这样做:

    SecurityInitializer.java:
    public class SecurityInitializer extends
    AbstractSecurityWebApplicationInitializer {

    @Override
    protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
    super.beforeSpringSecurityFilterChain(servletContext);

    // CSRF for multipart form data filter:
    FilterRegistration.Dynamic springMultipartFilter;
    springMultipartFilter = servletContext.addFilter(
    "springMultipartFilter", new MultipartFilter());
    springMultipartFilter.addMappingForUrlPatterns(null, false, "/*");

    }
    }

    关于当要发送的请求是多部分请求时,Spring CSRF token 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21514074/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com