2015-01-12 57 views
0

我一直在配置使用CAS的SSO解決方案與Spring Security集成的現有應用程序。我經歷了很多Stackoverflow的答案,但不幸的是,任何人都可以幫助我。你能否從我的配置角度幫助我解決這個問題?先謝謝你!CAS與春季安全 - 重定向循環

這裏是我的核心安全配置:

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

<description>This context sets up security configurations of the core module.</description> 

<!-- Enabled support for @Secured annotations on Spring bean methods --> 
<security:global-method-security secured-annotations="enabled" 
           access-decision-manager-ref="accessDecisionManager"/> 

<security:authentication-manager alias="authenticationManager"> 
    <security:authentication-provider ref="casAuthenticationProvider"/> 
</security:authentication-manager>  

<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider"> 
    <property name="authenticationUserDetailsService"> 
     <bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper"> 
      <constructor-arg ref="userDetailsService"/> 
     </bean> 
    </property> 
    <property name="serviceProperties" ref="serviceProperties"/> 
    <property name="ticketValidator"> 
     <bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator"> 
      <constructor-arg index="0" value="https://localhost:8443/cas"/> 
     </bean> 
    </property> 
    <property name="key" value="an_id_for_this_auth_provider_only"/> 
</bean> 

<security:http entry-point-ref="casEntryPoint"> 
    <security:custom-filter ref="casFilter" position="CAS_FILTER"/> 
</security:http> 

<bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"> 
    <property name="authenticationManager" ref="authenticationManager"/> 
</bean> 

<bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"> 
    <property name="loginUrl" value="https://localhost:8443/cas/login"/> 
    <property name="serviceProperties" ref="serviceProperties"/> 
</bean> 

<bean id="exceptionTranslationFilter" 
     class="org.springframework.security.web.access.ExceptionTranslationFilter"> 
    <property name="authenticationEntryPoint" ref="casEntryPoint"/> 
</bean> 

<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">   
    <property name="service" value="http://localhost:8080/myApp/j_spring_cas_security_check"/> 
    <property name="sendRenew" value="false"/> 
</bean> 

<!-- Service that retrieves UserDetails from DB for authentication --> 
<bean id="userDetailsService" class="com.xxx.yyy.core.security.userdetails.DefaultUserDetailsService"> 
    <property name="pmUserService" ref="pmUserService"/> 
</bean> 

<bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="randomSaltSource"> 
    <property name="userPropertyToUse" value="salt"/> 
</bean> 


<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> 
    <property name="decisionVoters"> 
     <!-- At least one voter must agree that the user can access a resource --> 
     <bean class="org.springframework.security.access.vote.RoleVoter"> 
      <!-- Override the default is 'ROLE_' prefix for role names --> 
      <property name="rolePrefix"> 
       <util:constant static-field="com.xxx.yyy.core.security.SecurityConstants.AUTHORITY_PREFIX"/> 
      </property> 
     </bean> 
    </property> 
</bean> 

...和額外的安全模塊:

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

<description>This context sets up security configurations of the web module</description> 

<import resource="web-security-urls.xml"/> 

<!-- Spring Security Filter Chain --> 
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy"> 
    <security:filter-chain-map path-type="ant"> 
     <security:filter-chain pattern="/**" 
           filters="securityContextPersistenceFilter, 
             logoutFilter, 
             authenticationFilter, 
             anonymousAuthenticationFilter, 
             exceptionTranslationFilter, 
             filterSecurityInterceptor"/> 
    </security:filter-chain-map> 
</bean> 

<!-- Responsible for propagation of SecurityContext on ThreadLocal from HttpSession --> 
<bean id="securityContextPersistenceFilter" 
     class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/> 

<!-- define the logout exit point --> 
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
    <!-- go to login page upon successful logout --> 
    <constructor-arg value="/"/> 
    <!-- Classes that get run when a user logs out --> 
    <constructor-arg> 
     <list> 
      <bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/> 
     </list> 
    </constructor-arg> 
    <property name="filterProcessesUrl" value="/j_spring_security_logout"/> 
</bean> 

<!-- Enable expression evaluation for Spring Security --> 
<bean class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/> 

<bean class="org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator"> 
    <constructor-arg ref="filterSecurityInterceptor"/> 
</bean> 

而且我們有單獨的模塊web-security-urls.xml其中o.s.s.web.access.intercept.FilterSecurityInterceptor被配置爲聲明安全網址

+0

問題已解決!看來,我只需在'filterChainProxy' bean中用'casFilter'替換'authenticationFilter' – sidlejinks

回答

0

我不確定這是否是確切的問題,但看起來像您可能會遺漏過濾器網址,因此您會收到無限重定向循環。

<bean id="casFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter"> 
    <property name="authenticationManager" ref="authenticationManager"/> 
</bean> 

您可以添加過濾URL過濾只有一個特定的URL模式

<property name="filterProcessesUrl" value="/j_spring_cas_security_check"/> 

這幫助我,當我被卡在了同一類型的問題。

+0

感謝您的反饋!然而,不幸的是,它並沒有太大的幫助:( – sidlejinks

0

我不知道你是否還有這個問題。我面對同樣的情況,而且很傷腦筋。當CasAuthenticationFilter無法確定傳入的URL(來自CAS服務器的重定向URL)是否需要身份驗證時,會出現無限重定向問題。

if (!requiresAuthentication(request, response)) { 
     chain.doFilter(request, response); 

     return; 
    } 

如果請求被標識爲「可篩選」URL,則需要進行身份驗證檢查。

private static final class FilterProcessUrlRequestMatcher implements RequestMatcher { 
    private final String filterProcessesUrl; 

    private FilterProcessUrlRequestMatcher(String filterProcessesUrl) { 
     Assert.hasLength(filterProcessesUrl, "filterProcessesUrl must be specified"); 
     Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL"); 
     this.filterProcessesUrl = filterProcessesUrl; 
    } 

    public boolean matches(HttpServletRequest request) { 
     String uri = request.getRequestURI(); 
     int pathParamIndex = uri.indexOf(';'); 

     if (pathParamIndex > 0) { 
      // strip everything after the first semi-colon 
      uri = uri.substring(0, pathParamIndex); 
     } 

     if ("".equals(request.getContextPath())) { 
      return uri.endsWith(filterProcessesUrl); 
     } 

     return uri.endsWith(request.getContextPath() + filterProcessesUrl); 
    } 
} 

與上下文路徑,檢查基本檢查,如果「服務URL」結尾request.getContextPath() + filterProcessesUrl

所以,URL在ServiceProperties對象的「服務」屬性需要匹配什麼是filterProcessesUrl提供。 例如:

<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"> 
    <property name="service" 
     value="https://localhost:9444/SpringSecurity2.5/tbr/j_spring_cas_security_check" /> 
    <property name="sendRenew" value="false" /> 

</bean> 

<bean id="casFilter" 
    class="org.springframework.security.cas.web.CasAuthenticationFilter"> 
    <property name="authenticationManager" ref="authenticationManager" /> 
    <property name="authenticationSuccessHandler"> 
     <bean 
      class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler" /> 
    </property> 
    <property name="filterProcessesUrl" value="/tbr/j_spring_cas_security_check"/> 

</bean> 

註記匹配圖案/ TBR/j_spring_cas_security_check在這兩種配置。

+0

並且補充一下,在spring-security + CAS的情況下,服務URL的概念與「正常」的CAS客戶端過濾的web應用程序的工作方式不同。 (BASIC,FORM BASED,CAS,X.509等),當認證成功時,它從緩存中獲取原始請求,並嘗試客戶端重定向(302)。服務URL實際上不是您在彈簧控制器中映射的URL,而只是由CAS篩選器 – user3030761

+0

'SavedRequestAwareAuthenticationSuccessHandler(SavedRequest)session.getAttribute(SAVED_REQUEST); String targetUrl = savedRequest識別的URL。getRedirectUrl(); getRedirectStrategy()。sendRedirect(request,response,targetUrl);' – user3030761