问题
I'm trying to change a basic application from using only Spring Security to using CAS, to enable SSO. But i'm getting a redirect loop somewhere, and i can't find out what is wrong. I have made two other mock applications, and there's no problem on CAS, because they are working. I'm using the Java configuration in place of the XML one, taken from here. I've tried the XML configuration for the example, but i'm still getting the same result. My guess would be for a problem with the authenticationManager, that can't detect the user from Spring Security. The log, at least, indicates a AnonymousUser and throws an AccessDeniedException. But it's working for the two other mock applications, that have the similar configuration(i've even tried copying it, but the error still occurs). I've been trying to fix this for some days without success, so any help is appreciated. I'm using Tomcat 8, Spring 4.2 and Ja-sig CAS 4.0.0, all on Windows 8.
My WebSecurityConfig:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
@Resource(name="CASuserDetailsService")
private AuthenticationUserDetailsService userDetailsService;
@Bean
public ServiceProperties serviceProperties() {
ServiceProperties serviceProperties = new ServiceProperties();
serviceProperties.setService("https://localhost:8443/i9t-YM/j_spring_cas_security_check");
serviceProperties.setSendRenew(false);
return serviceProperties;
}
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
casAuthenticationProvider.setAuthenticationUserDetailsService(authenticationUserDetailsService());
casAuthenticationProvider.setServiceProperties(serviceProperties());
casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
casAuthenticationProvider.setKey("some_id_for_this_cas_prov");
return casAuthenticationProvider;
}
@Bean
public AuthenticationUserDetailsService authenticationUserDetailsService() {
return userDetailsService;
}
@Bean
public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
return new Cas20ServiceTicketValidator("https://localhost:8443/cas");
}
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
casAuthenticationFilter.setAuthenticationManager(authenticationManager());
casAuthenticationFilter.setFilterProcessesUrl("https://localhost:8443/i9t-YM/j_spring_cas_security_check");
return casAuthenticationFilter;
}
@Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint() {
CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
casAuthenticationEntryPoint.setLoginUrl("https://localhost:8443/cas/login");
casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
return casAuthenticationEntryPoint;
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(casAuthenticationProvider());
//Yes, joe is with a md5 poassword on the database, but i'm using it here as a mockup to see if it works. Also, if there's no ".password", it'll throw an ConstructorCantBeNull or something like that.
auth.inMemoryAuthentication().withUser("joe").password("joe").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilter(casAuthenticationFilter());
http.exceptionHandling().authenticationEntryPoint(casAuthenticationEntryPoint());
http.authorizeRequests().antMatchers("/**").access("hasRole('ROLE_USER')");
// http.authorizeRequests().antMatchers("/resource", "/secure/**").access("hasRole('ROLE_USER')");
// http.authorizeRequests().antMatchers("/resources/**").permitAll();
// http.httpBasic().and().authorizeRequests().antMatchers("/index.html", "/home.html", "/login.html", "/")
// .permitAll().anyRequest().authenticated()
// //.and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
// //.csrf().csrfTokenRepository(csrfTokenRepository())
// ;
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
The TestCasAuthenticationUserDetailsService(notice that i've tried to make it work through a number of ways...)
@Service("CASuserDetailsService")
public class TestCasAuthenticationUserDetailsService implements AuthenticationUserDetailsService, UserDetailsService {
@Autowired
private DataSource dataSource;
@Override
public UserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException {
List<GrantedAuthority> authorities = new ArrayList<>();
System.out.println(token.getName());
System.out.println(token.toString());
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(token.getName(), token.getName(), authorities);
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<GrantedAuthority> authorities = new ArrayList<>();
System.out.println(username);
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(username, username, authorities);
}
}
My web.xml:
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-context.xml
<!-- /WEB-INF/spring-security.xml -->
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/erro.html</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.html</location>
</error-page>
<!-- CAS -->
<filter>
<filter-name>CAS-SSO-Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS-SSO-Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- Force SSL -->
<security-constraint>
<web-resource-collection>
<web-resource-name>i9t-YM</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
The applicationContext-security.xml from the mock applications:
<security:http auto-config="true" entry-point-ref="casEntryPoint">
<security:intercept-url pattern="/*" access="ROLE_USER" />
<security:custom-filter position="CAS_FILTER"
ref="casFilter" />
</security:http>
<security:user-service id="userService">
<security:user name="joe" authorities="ROLE_USER" />
</security:user-service>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="casAuthenticationProvider" />
</security:authentication-manager>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://localhost:8443/casTest/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" />
</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="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean
class=" org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg ref="userService" />
</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" />
<!-- <property name="proxyGrantingTicketStorage" ref="proxyGrantingTicketStorage" /> -->
<!-- <property name="proxyCallbackUrl" value="https://localhost:8443/cas/secure/receptor" /> -->
</bean>
</property>
<property name="key" value="some_id_for_this_cas_prov" />
</bean>
<bean id="proxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
SSL is working fine for them too. The error logged when there's a loop:
2015-08-27 11:29:59,026 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org] for service [https://localhost:8443/i9t-YM/j_spring_cas_security_check] for user [joe]>
2015-08-27 11:29:59,027 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: joe
WHAT: ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org for https://localhost:8443/i9t-YM/j_spring_cas_security_check
ACTION: SERVICE_TICKET_CREATED
APPLICATION: CAS
WHEN: Thu Aug 27 11:29:59 BRT 2015
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1
=============================================================
>
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
HttpSession returned null object for SPRING_SECURITY_CONTEXT
No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@1c993da0. A new one will be created.
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
Request 'GET /j_spring_cas_security_check' doesn't match 'POST /logout
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 6 of 12 in additional filter chain; firing Filter: 'CasAuthenticationFilter'
Checking match of request : '/j_spring_cas_security_check'; against 'https://localhost:8443/i9t-ym/j_spring_cas_security_check'
serviceTicketRequest = false
proxyReceptorConfigured = false
proxyReceptorRequest = false
proxyTicketRequest = false
requiresAuthentication = false
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
pathInfo: both null (property equals)
queryString: arg1=ticket=ST-9-DElbuW6RP24GocThfiBt-cas01.example.org; arg2=ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org (property not equals)
saved request doesn't match
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 0CA64FA23DD44EECC261887599F2541B; Granted Authorities: ROLE_ANONYMOUS'
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
Request '/j_spring_cas_security_check' matched by universal pattern '/**'
Secure object: FilterInvocation: URL: /j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org; Attributes: [hasRole('ROLE_USER')]
Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@905571d8: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 0CA64FA23DD44EECC261887599F2541B; Granted Authorities: ROLE_ANONYMOUS
Voter: org.springframework.security.web.access.expression.WebExpressionVoter@2c4d2096, returned: -1
Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:614)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1527)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1484)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Trying to match using Ant [pattern='/**', GET]
Request '/j_spring_cas_security_check' matched by universal pattern '/**'
Trying to match using NegatedRequestMatcher [requestMatcher=Ant [pattern='/**/favicon.ico']]
Checking match of request : '/j_spring_cas_security_check'; against '/**/favicon.ico'
matches = true
Trying to match using NegatedRequestMatcher [requestMatcher=MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@37c9ddce, matchingMediaTypes=[application/json], useEquals=false, ignoredMediaTypes=[*/*]]]
httpRequestMediaTypes=[text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8]
Processing text/html
application/json .isCompatibleWith text/html = false
Processing application/xhtml+xml
application/json .isCompatibleWith application/xhtml+xml = false
Processing application/xml;q=0.9
application/json .isCompatibleWith application/xml;q=0.9 = false
Processing */*;q=0.8
Ignoring
Did not match any media types
matches = true
Trying to match using NegatedRequestMatcher [requestMatcher=RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]]
matches = true
All requestMatchers returned true
DefaultSavedRequest added to Session: DefaultSavedRequest[https://localhost:8443/i9t-YM/j_spring_cas_security_check?ticket=ST-10-yA1U32bOGJ6Gg5HShohm-cas01.example.org]
Calling Authentication entry point.
SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
SecurityContextHolder now cleared, as request processing completed
I've tried a number of solutions from other questions here, but i dunno if i'm just doing something really stupid that i can't see, or if i screwed up on the configuration. Anything missing, just tell me that i'll add. Thanks in advance!
Edit: It's not validating the ticket from the app, but it should be working. The other application is working as intended:
2015-08-28 08:44:39,049 INFO [org.jasig.cas.CentralAuthenticationServiceImpl] - <Granted service ticket [ST-44-QmOXrKwachmUcM16DqV4-cas01.example.org] for service [https://localhost:8443/casTest/j_spring_cas_security_check] for user [joe]>
2015-08-28 08:44:39,049 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: joe
WHAT: ST-44-QmOXrKwachmUcM16DqV4-cas01.example.org for https://localhost:8443/casTest/j_spring_cas_security_check
ACTION: SERVICE_TICKET_CREATED
APPLICATION: CAS
WHEN: Fri Aug 28 08:44:39 BRT 2015
CLIENT IP ADDRESS: 0:0:0:0:0:0:0:1
SERVER IP ADDRESS: 0:0:0:0:0:0:0:1
=============================================================
>
2015-08-28 08:44:39,063 INFO [com.github.inspektr.audit.support.Slf4jLoggingAuditTrailManager] - <Audit trail record BEGIN
=============================================================
WHO: audit:unknown
WHAT: ST-44-QmOXrKwachmUcM16DqV4-cas01.example.org
ACTION: SERVICE_TICKET_VALIDATED
APPLICATION: CAS
WHEN: Fri Aug 28 08:44:39 BRT 2015
CLIENT IP ADDRESS: 127.0.0.1
SERVER IP ADDRESS: 127.0.0.1
=============================================================
>
EDIT2: A very strange addition: the others sample applications are using servlets alone, and are working, with spring 3.2. Now, i tried mimicking copying the original one to this sample, and tried to downgrade it until it worked. The problem is that i can't get it to work the any @Controller annotation or similar...But the redirect is gone. If i update my maven, and go from 4.2 to 3.2, the loop is gone. But if i'm on 4.2, without changing nothing but the version, there's the loop!
回答1:
Since Spring Security 4.x, the endpoint for CAS changed from /j_spring_cas_security_check
to /login/cas
(cf. https://stackoverflow.com/a/35136587/3585320)
回答2:
pom.xml
<spring.version>4.3.2.RELEASE</spring.version>
<spring.security.version>4.1.3.RELEASE</spring.security.version>
spring-security.xml
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<!-- spring security 3.x -->
<!--
<property name="service" value="http://localhost:8080/j_spring_cas_security_check"/>
-->
<property name="service" value="http://localhost:8080/login/cas"/>
<property name="sendRenew" value="false"/>
</bean>
Reference:
Migrating from Spring Security 3.x to 4.x (XML Configuration)
Migrating from Spring Security 3.x to 4.x (Java Configuration)
The CasAuthenticationFilter filterProcessesUrl property default value changed from "/j_spring_cas_security_check" to "/login/cas". This means if the filterProcessesUrl property is not explicitly specified, then the configuration will need updated. For example, if an application using Spring Security 3.2.x contains a configuration similar to the following:
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setAuthenticationManager(authenticationManager);
The configuration will need to be updated to something similar to the following when Spring Security 4.x:
xml config:
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<b:property name="authenticationManager" ref="authenticationManager"/>
<b:property name="filterProcessesUrl" value="/j_spring_cas_security_check"/>
</bean>
java config:
CasAuthenticationFilter filter = new CasAuthenticationFilter();
filter.setFilterProcessesUrl("/j_spring_cas_security_check");
filter.setAuthenticationManager(authenticationManager);
Alternatively, the ServiceProperties can be updated to use the new default:
xml config:
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://example.com/cas-sample/login/cas"/>
</bean>
java config:
ServiceProperties properties = new ServiceProperties();
properties.setService("https://example.com/cas-sample/login/cas");
回答3:
The CAS server has returned a service ticket (ticket
parameter) to the j_spring_cas_security_check url. It should work. Enable DEBUG logs on the org.jasig.cas
package to know what happens in the CAS client: is the service ticket validation successfull?
回答4:
serviceProperties.setAuthenticateAllArtifacts(true);
回答5:
So, the "answer" to it was simply to downgrade Spring Security from 4.0.2 to 3.2.8. Then I only had to change from the XML template to the Java configuration again, by commenting the spring-security-xml:
<param-value>
/WEB-INF/spring-context.xml
<!-- /WEB-INF/spring-security.xml -->
</param-value>
Not sure if this is the "actual" answer, as I dunno if there's a specific configuration for Spring Security 4 to make it work that is different than the 3.2 one, but since that all the Spring features that I was using from 4.2 were just Spring's, they didn't need the downgrade to work.
回答6:
In my case this loop was due to an incorrect rewrite rule inside Apache. The /login/cas
path was being changed into /secured/cas
, falling again into a secured url and thus invoking CAS login page.
来源:https://stackoverflow.com/questions/32252695/getting-a-loop-redirect-with-spring-security-cas-but-should-be-working