2015-01-12 28 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