2015-09-01 39 views
0

我在我的項目中設置了Spring Security,並且遇到了其他休息端點中的一個問題。當我通過客戶端訪問端點時,服務器收到「Error:Forbidden」響應。Spring Security - 來自休息端點的「錯誤:禁止」響應

我正在做的是進入登錄頁面(我假設在這一點上我是一個匿名用戶與ROLE_ANONYMOUS),並點擊一個標籤,顯示我創建一個新的帳戶表單。

當我填寫字段並點擊提交時,剩下的端點被調用並且JSON數據被髮送到服務器。在我的安全配置中,我已經在我使用的端點url下面發佈了/createUserAccount/submit,它被設置爲與filterSecurityInterceptor bean xml中的ROLE_ANONYMOUS和ROLE_ADMIN角色一起工作。

由於我是登錄頁面上的匿名用戶,我認爲點擊該端點會起作用,但事實並非如此。所有與我的問題有關的文件都在下面。

這裏是我的控制器:

@Controller 
@RequestMapping("/createUserAccount") 
@SessionAttributes("userAccount") 
public class CreateUserAccountController { 
    private final String loginViewName = "login"; 
    private CreateUserAccountValidator validator; 
    private UserAccountManager userAccountManager; 

    @Autowired 
    public CreateUserAccountController(
      @Qualifier("createUserAccountValidator") CreateUserAccountValidator validator, 
      @Qualifier("userAccountManager") UserAccountManager userAccountManager) { 
     this.validator = validator; 
     this.userAccountManager = userAccountManager; 
    } 

    @RequestMapping(value="/submit", method = RequestMethod.POST) 
    @ResponseBody 
    public GenericJsonDTO submitForm(@RequestBody UserAccount userAccount, BindingResult result, SessionStatus status){ 
     JsonFactory jsonFactory = new JsonFactory(result, "/gravytrack/dashboard"); 
     validator.validate(userAccount, result); 

     if(!result.hasErrors()) { 
      userAccountManager.createUserAccount(userAccount); 
      status.setComplete(); 
     } 
     return jsonFactory.getDto(); 
    } 
} 

我有我的服務器設置,所以我可以在運行時調試,我把上線

JsonFactory jsonFactory = new JsonFactory(result, "/gravytrack/dashboard"); 

斷點,看該功能不斷時進入調用/createUserAccount/submit端點。該功能從未輸入。

以下是我的安全配置。我已經開始整合ACL安全性,因此配置文件很長。我認爲問題出現在http elementfilterSecurityInterceptor bean配置xml中。 filterSecurityInterceptor XML是我的URI許可被定義的地方。

<global-method-security pre-post-annotations="enabled" 
          secured-annotations="enabled"> 
     <expression-handler ref="expressionHandler" /> 
    </global-method-security> 

    <http use-expressions="true"> 
     <intercept-url pattern="/**" requires-channel="https" /> 
     <!--<intercept-url pattern="/gravytrack/dashboard**" requires-channel="https" access="ROLE_USER"/>--> 
     <http-basic /> 
     <session-management> 
      <concurrency-control max-sessions="10" 
           error-if-maximum-exceeded="true" /> 
     </session-management> 
     <anonymous username="guest" granted-authority="ROLE_ANONYMOUS"/> 
    </http> 

    <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, password, enabled FROM user_account 
              WHERE email = ?" /> 

     </authentication-provider> 
    </authentication-manager> 

    <beans:bean id="springSecurityFilterChain" 
       class="org.springframework.security.web.FilterChainProxy"> 
     <beans:constructor-arg> 
      <util:list> 
       <filter-chain pattern="/images/**" filters="" /> 
       <filter-chain pattern="/**" 
           filters="securityContextPersistenceFilterWithASCFalse, 
            basicAuthenticationFilter, 
            basicExceptionTranslationFilter, 
            filterSecurityInterceptor" /> 
      </util:list> 
     </beans:constructor-arg> 
    </beans:bean> 
    <beans:bean id="securityContextPersistenceFilterWithASCFalse" 
       class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> 
    </beans:bean> 

    <beans:bean id="securityContextPersistenceFilterWithASCTrue" 
       class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> 
    </beans:bean> 

    <!--......................--> 
    <!-- basic authentication --> 
    <!--......................--> 
    <beans:bean id="basicAuthenticationFilter" 
       class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter"> 
     <beans:constructor-arg name="authenticationManager"> 
      <beans:ref bean="authenticationManager" /> 
     </beans:constructor-arg> 
     <beans:constructor-arg name="authenticationEntryPoint"> 
      <beans:ref bean="basicAuthenticationEntryPoint" /> 
     </beans:constructor-arg> 
    </beans:bean> 
    <beans:bean id="basicAuthenticationEntryPoint" 
       class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint"> 
     <beans:property name="realmName" value="gravytrack.com" /> 
    </beans:bean> 

    <beans:bean id="basicExceptionTranslationFilter" 
       class="org.springframework.security.web.access.ExceptionTranslationFilter"> 
     <beans:constructor-arg name="authenticationEntryPoint" ref="basicAuthenticationEntryPoint" /> 
     <beans:property name="accessDeniedHandler" ref="basicAccessDeniedHandler" /> 
    </beans:bean> 

    <beans:bean id="basicAccessDeniedHandler" 
       class="org.springframework.security.web.access.AccessDeniedHandlerImpl"> 
    </beans:bean> 

    <!--......................--> 
    <!--  security  --> 
    <!--......................--> 
    <beans:bean id="filterSecurityInterceptor" 
       class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor"> 

     <beans:property name="authenticationManager" ref="authenticationManager" /> 
     <beans:property name="accessDecisionManager" ref="accessDecisionManager" /> 

     <beans:property name="securityMetadataSource"> 
      <filter-security-metadata-source use-expressions="false"> 
       <intercept-url pattern="/login.jsp*" 
           access="ROLE_ANONYMOUS,ROLE_ADMIN" /> 
       <intercept-url pattern="/gravytrack/createUserAccount/*" 
           access="ROLE_ANONYMOUS,ROLE_ADMIN" /> 
       <intercept-url pattern="/images/**" 
           access="ROLE_ANONYMOUS,ROLE_USER,ROLE_ADMIN" /> 
       <intercept-url pattern="/admin.htm*" access="ROLE_ADMIN" /> 
       <intercept-url pattern="/**" 
           access="ROLE_USER,ROLE_ADMIN" /> 
      </filter-security-metadata-source> 
     </beans:property> 

    </beans:bean> 

    <beans:bean id="accessDecisionManager" 
       class="org.springframework.security.access.vote.AffirmativeBased"> 
     <beans:constructor-arg name="decisionVoters"> 
      <beans:list> 
       <beans:bean class="org.springframework.security.access.vote.RoleVoter" /> 
       <beans:bean 
         class="org.springframework.security.access.vote.AuthenticatedVoter" /> 
      </beans:list> 
     </beans:constructor-arg> 
    </beans:bean> 


    <beans:bean id="expressionHandler" 
       class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"> 
     <beans:property name="permissionEvaluator" ref="permissionEvaluator" /> 
    </beans:bean> 

    <beans:bean id="permissionEvaluator" 
       class="org.springframework.security.acls.AclPermissionEvaluator"> 
     <beans:constructor-arg ref="aclService" /> 
    </beans:bean> 

    <beans:bean id="aclService" 
       class="org.springframework.security.acls.jdbc.JdbcMutableAclService"> 
     <beans:constructor-arg ref="dataSource" /> 
     <beans:constructor-arg ref="lookupStrategy" /> 
     <beans:constructor-arg ref="aclCache" /> 
     <beans:property name="sidIdentityQuery" 
         value="SELECT max(id) FROM acl_sid" /> 
     <beans:property name="classIdentityQuery" 
         value="SELECT max(id) FROM acl_class" /> 
     <!-- 
     <beans:property name="sidIdentityQuery" 
      value="select currval(pg_get_serial_sequence('acl_sid', 'id'))" /> 
     <beans:property name="classIdentityQuery" 
      value="select currval(pg_get_serial_sequence('acl_class', 'id'))" /> 
     --> 
    </beans:bean> 

    <beans:bean id="consoleAuditLogger" class="org.springframework.security.acls.domain.ConsoleAuditLogger"/> 

    <beans:bean id="lookupStrategy" 
       class="org.springframework.security.acls.jdbc.BasicLookupStrategy"> 
     <beans:constructor-arg ref="dataSource" /> 
     <beans:constructor-arg ref="aclCache" /> 
     <beans:constructor-arg ref="aclAuthorizationStrategy" /> 
     <beans:constructor-arg ref="consoleAuditLogger"/> 
    </beans:bean> 

    <beans:bean id="aclAuthorizationStrategy" 
      class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl"> 
     <beans:constructor-arg> 
      <beans:list> 
       <beans:bean 
         class="org.springframework.security.core.authority.SimpleGrantedAuthority"> 
        <beans:constructor-arg value="ROLE_ADMIN" /> 
       </beans:bean> 
       <beans:bean 
         class="org.springframework.security.core.authority.SimpleGrantedAuthority"> 
        <beans:constructor-arg value="ROLE_ADMIN" /> 
       </beans:bean> 
       <beans:bean 
         class="org.springframework.security.core.authority.SimpleGrantedAuthority"> 
        <beans:constructor-arg value="ROLE_ADMIN" /> 
       </beans:bean> 
      </beans:list> 
     </beans:constructor-arg> 
    </beans:bean> 

    <beans:bean id="permissionGrantingStrategy" class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy"> 
     <beans:constructor-arg ref="consoleAuditLogger"/> 
    </beans:bean> 


    <beans:bean id="aclCache" 
       class="org.springframework.security.acls.domain.EhCacheBasedAclCache"> 
     <beans:constructor-arg> 
      <beans:bean class="org.springframework.cache.ehcache.EhCacheFactoryBean"> 
       <beans:property name="cacheManager"> 
        <beans:bean 
          class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" /> 
       </beans:property> 
       <beans:property name="cacheName" value="aclCache" /> 
      </beans:bean> 
     </beans:constructor-arg> 
     <beans:constructor-arg ref="permissionGrantingStrategy" /> 
     <beans:constructor-arg ref="aclAuthorizationStrategy" /> 
    </beans:bean> 


</beans:beans> 

最後但並非最不重要,這裏是我的web.xml

<?xml version="1.0" encoding="UTF-8"?> 

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 
    <!-- Log4j configuration loading --> 
    <listener> 
     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> 
    </listener> 
    <context-param> 
     <param-name>log4jConfigLocation</param-name> 
     <param-value>/WEB-INF/classes/log4j.xml</param-value> 
    </context-param> 
    <!-- Bootstrapping context loading --> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      /WEB-INF/gravytrack-servlet.xml 
      /WEB-INF/gravytrack-services.xml 
      /WEB-INF/gravytrack-security.xml 
      </param-value> 
    </context-param> 
    <context-param> 
     <param-name>webAppRootKey</param-name> 
     <param-value>gravytrack.root</param-value> 
    </context-param> 

    <!-- session management listener --> 
    <listener> 
     <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> 
    </listener> 
    <session-config> 
     <!-- session times out if no activities for 30 minutes --> 
     <session-timeout>30</session-timeout> 
    </session-config> 


    <!-- defining the DispatcherServlet --> 
    <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>*.htm</url-pattern> 
    </servlet-mapping> 
    <!--<servlet-mapping>--> 
     <!--<servlet-name>gravytrack</servlet-name>--> 
     <!--<url-pattern>*.html</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>/*</url-pattern> 
    </filter-mapping> 

    <!-- webflow --> 
    <!-- 
<servlet-mapping> 
     <servlet-name>soba</servlet-name> 
     <url-pattern>/flow/*</url-pattern> 
    </servlet-mapping> 
--> 
<!-- defining the DefaultServlet --> 
<servlet> 
     <servlet-name>DefaultServlet</servlet-name> 
     <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> 
     <load-on-startup>2</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>DefaultServlet</servlet-name> 
     <url-pattern>*.jpg</url-pattern> 
    </servlet-mapping> 
    <servlet-mapping> 
     <servlet-name>DefaultServlet</servlet-name> 
     <url-pattern>*.html</url-pattern> 
    </servlet-mapping> 
    <error-page> 
     <error-code>404</error-code> 
     <location>/WEB-INF/jsp/notfound.jsp</location> 
    </error-page> 
    <welcome-file-list> 
     <welcome-file> 
     login.jsp 
    </welcome-file> 
    </welcome-file-list> 
    <!-- Spring jsp tag lib --> 
    <jsp-config> 
     <taglib> 
      <taglib-uri>/spring</taglib-uri> 
      <taglib-location>/WEB-INF/tld/spring-form.tld</taglib-location> 
     </taglib> 
    </jsp-config> 

</web-app> 

我有一個困難時期試圖找出什麼是錯的,因此任何幫助是極大的讚賞。

回答

2

默認情況下,Spring安全啓用CSRF和每個POST請求,因爲它需要一個csrf標記。 檢查Spring CSRF documentation ..

你可以關機CSRF像這樣在你的配置已經測試,如果是,如果你不想關機CSRF問題

<http auto-config="false"> 
     <csrf disabled="true"/> 

,你必須張貼的CSRF令牌這樣

<c:url var="logoutUrl" value="/logout"/> 
<form action="${logoutUrl}" method="post"> 
    <input type="submit" value="Log out" /> 
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 
</form> 
相關問題