I've implemented my own LogoutHandler and I'm trying to configure it in the spring security xml, but for some reason it's not being called on logout (the logout is successful, but my code isn't executed).
This is my security.xml:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http use-expressions="true">
<security:intercept-url pattern="/logoutSuccess"
access="permitAll" />
<security:logout logout-url="/logout"
logout-success-url="/logoutSuccess" />
</security:http>
<bean id="logoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg index="0" value="/logoutSuccess" />
<constructor-arg index="1">
<list>
<bean id="securityContextLogoutHandler"
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
<bean id="myLogoutHandler" class="my.package.MyLogoutHandler" />
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout" />
</bean>
MyLogoutHandler - this is what I want to execute on logout, but it's not being called:
import org.springframework.security.web.authentication.logout.LogoutHandler;
public class MyLogoutHandler implements LogoutHandler {
#Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
System.out.println("logout!");
}
}
Does anyone have any idea why it's not working? Thanks!
As you want to use your custom filter instead of spring security default log out filter, add this line to logout filter bean
<security:custom-filter position="LOGOUT_FILTER"/>
or add this line in your spring security config
<security:custom-filter ref="logoutFilter" position="LOGOUT_FILTER"/>
Editted
<security:http use-expressions="true">
<security:intercept-url pattern="/logoutSuccess"
access="permitAll" />
<security:logout logout-url="/logout"
logout-success-url="/logoutSuccess" success-handler-ref="myLogoutHandler" />
</security:http>
<bean id="myLogoutHandler" class="my.package.MyLogoutHandler" />
Also you can implement LogoutSuccessHandler interface instead of LogoutHandler
Edit2
ok, so if you dont want to call your handler after logout is complete, remove logout tag and set everything in logout filter bean
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg index="0" value="/logoutSuccess" />
<constructor-arg index="1">
<list>
<bean id="securityContextLogoutHandler"
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
<bean id="myLogoutHandler" class="my.package.MyLogoutHandler" />
</list>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout" />
</bean>
And add <security:custom-filter ref="logoutFilter" position="LOGOUT_FILTER"/>
Related
Im doing a new webapp with Spring and Tiles.
So far I have the login, create/edit users working.
Now I have to start with Rest Controller for third apps with json.
And I need to disable the csrf only on the rest URL's.
I tried using the XML from spring <csrf disabled="true"/> and it works but for the enthire app is there a way to do this config by path or the only way is to write it down by Java?:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}
This is not working for me, every simple example I find is the same and seems to work to everyone except me, what am i doing wrong?
spring-security config:
<?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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<http auto-config="true">
<!-- <csrf disabled="true"/> -->
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/welcome" access="hasRole('ROLE_ADMIN')"/>
<!-- <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" access="ROLE_USER,ROLE_ADMIN"/> -->
<intercept-url pattern="/administration/**" access="hasRole('ROLE_ADMIN')"/>
<form-login login-page="/login" default-target-url="/" authentication-failure-url="/login?error" username-parameter="username" password-parameter="password" />
<logout logout-success-url="/login?logout" />
</http>
<authentication-manager>
<authentication-provider ref="CustomAuthenticationProvider" />
</authentication-manager>
<beans:bean id="CustomAuthenticationProvider"
class="net.eqtconsulting.webapp.service.CustomAuthenticationProvider">
</beans:bean>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="11" />
</beans:bean>
</beans:beans>
Also my spring-mvc
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/"/>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptors>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<property name="cookieName" value="locale" />
</bean>
<!-- Application Message Bundle -->
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="WEB-INF/i18n/messages" />
<property name="fallbackToSystemLocale" value="false" />
<property name="useCodeAsDefaultMessage" value="true" />
<property name="cacheSeconds" value="3000" />
</bean>
<mvc:annotation-driven >
<mvc:argument-resolvers>
<bean class="org.springframework.data.web.PageableHandlerMethodArgumentResolver">
<property name="maxPageSize" value="10"></property>
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
<context:component-scan base-package="com.javatpoint.controller" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.tiles3.TilesViewResolver" />
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
</beans>
Im also thinking about doing it by using 2 xml servlets, but how would the spring-security work, can I make it use an other one aswell?
Added this to my xml configuration and works just fine:
<http pattern="/rest/**" security="none" />
and then the other <http... </http> config for the standard app
I have a spring application with the config files as shown below. All configs seem correct but while debugging I found that, during the initialization spring creates two beans for FilterSecurityInterceptor one without any intercept-url rules and the other with the rules that I have specified.
When a request comes, it uses the FilterSecurityInterceptor bean with no intercept-url rules. So I see the following log:
DEBUG FilterSecurityInterceptor:183 - Public object - authentication not attempted
But the request URL falls under the intercept URL rule. I debugged and found that this is because the bean used didn't have any intercept rules in httpMethodMap of DefaultFilterInvocationSecurityMetadataSource.
I am not sure what is wrong here.
Below is the applicationContext-security.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
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-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"
default-init-method="init">
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
user-service-ref="userDetailService">
</security:authentication-provider>
</security:authentication-manager>
<alias name="filterChainProxy" alias="springSecurityFilterChain" />
<bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<property name="decisionVoters">
<list>
<bean class="org.springframework.security.access.vote.RoleVoter" />
<bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
<bean id="consoleAuthenticationSuccessHandler"
class="custom_class">
<property name="defaultTargetUrl" value="/loginSuccess.htm" />
<property name="targetUrlParameter" value="targetURL" />
</bean>
<bean id="consoleAuthenticationFailureHandler"
class="custom_class">
<property name="loginFailureUrl" value="/loginFailure.htm" />
</bean>
<bean id="consoleLogoutSuccessHandler"
class="custom_class">
<property name="logoutUrl" value="/loggedout.htm" />
</bean>
<bean id="userDetailService"
class="custom_class">
</bean>
<security:http auto-config="true"
security-context-repository-ref="securityContextRepository">
<security:form-login authentication-failure-url="/loginFailure.htm"
default-target-url="/loginSuccess.htm"
authentication-success-handler-ref="consoleAuthenticationSuccessHandler" />
<security:logout success-handler-ref="consoleLogoutSuccessHandler" />
<security:anonymous enabled="false" />
<security:session-management
session-fixation-protection="none" />
</security:http>
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/login.htm*"
filters="none" />
<security:filter-chain pattern="/**"
filters="securityContextFilter, logoutFilter, formLoginFilter, servletApiFilter, exceptionTranslator, filterSecurityInterceptor" />
</security:filter-chain-map>
</bean>
<bean id="securityContextRepository"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
<bean id="securityContextFilter"
class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<property name="securityContextRepository" ref="securityContextRepository" />
</bean>
<bean id="logoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg ref="consoleLogoutSuccessHandler"
index="0"
type="org.springframework.security.web.authentication.logout.LogoutSuccessHandler" />
<constructor-arg>
<list>
<bean
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</list>
</constructor-arg>
</bean>
<bean id="servletApiFilter"
class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter" />
<bean id="exceptionTranslator"
class="org.springframework.security.web.access.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
</bean>
</property>
</bean>
<bean id="formLoginFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="consoleAuthenticationSuccessHandler" />
<property name="authenticationFailureHandler" ref="consoleAuthenticationFailureHandler" />
</bean>
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/login.htm*"
access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**"
access="ROLE_USER,ROLE_ADMIN" />
</security:filter-security-metadata-source>
</property>
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
</beans>
Appreciate any help here.
You have <security:http> element in the config. From the documentation:
38.1.2 <http>
Each <http> namespace block always creates an SecurityContextPersistenceFilter, an ExceptionTranslationFilter and a FilterSecurityInterceptor. These are fixed and cannot be replaced with alternatives.
So your <bean id="filterSecurityInterceptor"> is ignored. Instead of
<bean id="filterSecurityInterceptor"
class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="securityMetadataSource">
<security:filter-security-metadata-source>
<security:intercept-url pattern="/login.htm*"
access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**"
access="ROLE_USER,ROLE_ADMIN" />
</security:filter-security-metadata-source>
</property>
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="authenticationManager" ref="authenticationManager" />
</bean>
you should change <security:http> to include something like
<security:http ...
authentication-manager-ref="authenticationManager">
...
<security:intercept-url pattern="/login.htm*"
access="ROLE_ANONYMOUS" />
<security:intercept-url pattern="/**"
access="ROLE_USER,ROLE_ADMIN" />
</security:http>
You don't need <bean id="accessDecisionManager">, because (quote from the docs) "by default an AffirmativeBased implementation is used for with a RoleVoter and an AuthenticatedVoter", which is exactly what you define.
Also your <bean id="securityContextFilter"> is ignored, instead you should add security-context-repository-ref="securityContextRepository" attribute to http element.
And your <bean id="exceptionTranslator"> is ignored, I'm not sure how to replace it properly.
And you manually define a lot of org.springframework.security beans. I suspect that most of them are either unnecessary (defined by default), or should be defined using specialized elements of security: namespace, instead of raw spring beans.
spring-security.xml
<?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:oauth="http://www.springframework.org/schema/security/oauth2"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd ">
<!-- Default url to get a token from OAuth -->
<http pattern="/api/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<csrf disabled="true"/>
<intercept-url pattern="/api/oauth/token" access="isFullyAuthenticated()"/>
<anonymous enabled="false"/>
<http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER"/>
<access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>
<!-- Protected sources -->
<http pattern="/api/services/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security" use-expressions="true">
<anonymous enabled="false"/>
<intercept-url pattern="/api/**" access="hasRole('ROLE_APP')"/>
<custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
<access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager"/>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased" xmlns="http://www.springframework.org/schema/beans">
<constructor-arg>
<list>
<bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter"/>
<bean class="org.springframework.security.access.vote.RoleVoter"/>
<bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
</list>
</constructor-arg>
</bean>
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService"/>
</authentication-manager>
<sec:authentication-manager>
<sec:authentication-provider user-service-ref='userDetailsServiceImpl'/>
</sec:authentication-manager>
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetails"/>
</bean>
<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="userDetailsServiceImpl"></authentication-provider>
</authentication-manager>
<!-- Token store -->
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore"/>
<property name="supportRefreshToken" value="true"/>
<property name="accessTokenValiditySeconds" value="120"/>
<property name="clientDetailsService" ref="clientDetails"/>
</bean>
<bean id="oAuth2RequestFactory" class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<constructor-arg ref="clientDetails"/>
</bean>
<bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenStore" ref="tokenStore"/>
<property name="requestFactory" ref="oAuth2RequestFactory"/>
</bean>
<bean id="oauthAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client"/>
<property name="typeName" value="Basic"/>
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="test/client"/>
<property name="typeName" value="Basic"/>
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter" resource-id="test" token-services-ref="tokenServices"/>
<bean id="clientDetails" class="com.xxxxxx.service.ClientService"></bean>
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<sec:expression-handler ref="oauthExpressionHandler"/>
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler"/>
<oauth:web-expression-handler id="oauthWebExpressionHandler"/>
</beans>
UserServiceImpl
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private OauthRepository oauthRepository;
#Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = oauthRepository.getByUsername(s);
return user;
}
}
ClientServiceImpl
#Component
public class ClientService implements ClientDetailsService {
#Autowired
private OauthRepository oauthRepository;
#Override
public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException {
BaseClientDetails clientDetails = oauthRepository.getByClientId(s);
return clientDetails;
}
}
I've been searching a lot, but I can't figure out why the UserServiceImpl is not called. I debbuged and always ClientServiceImpl is being called to fetch for client AND users.
After sending a request to /api/oauth/token, with proper parameters (user and client stored in database), I get:
{"error":"unauthorized","error_description":"Incorrect result size: expected 1, actual 0"}
I'm using
- Spring Framework 4.2.5.RELEASE
- Spring Mvc 4.2.5.RELEASE,
- Spring Security 4.1.0.RC1,
- Spring Security Oauth2 2.0.9.RELEASE
I think you are doing good but in the
#Service public class UserDetailsServiceImpl implements UserDetailsService
You should set the user’s password and its role.
Please look code here
#Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException
{
System.out.println("Getting access details from Database !!");
// Ideally it should be fetched from database and populated instance of
// #org.springframework.security.core.userdetails.User should be returned from this method
UserDetails user = new User(username, "password", true, true, true, true, new GrantedAuthority[]{ new GrantedAuthorityImpl("ROLE_USER") });
return user;
}
UserDetailsService interface is used in order to lookup the username, password and GrantedAuthorities for any given user. This interface provide only one method which implementing class need to implement.
I solved it with the following changes in spring-security.xml:
<!-- Default url to get a token from OAuth -->
<http pattern="/api/oauth/token" create-session="stateless"
authentication-manager-ref="authenticationManager"
:
<authentication-manager id="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="userDetailsServiceImpl"/>
</authentication-manager>
I guess I had two instances fo authenticationMangager. Thanks anyway.
We have the following spring security configuration:
<bean id="authenticationSuccessHandler" class="***.JsonAuthenticationSuccessHandler"/>
<bean id="logoutSuccessHandler" class="***.web.security.***UrlLogoutSuccessHandler">
<property name="redirectStrategy" ref="noRedirectStrategy"/>
</bean>
<bean id="authenticationFailureHandler"
class="***.web.security.***UrlAuthenticationFailureHandler"/>
<bean id="httpStatusEntryPoint" class="org.springframework.security.web.authentication.HttpStatusEntryPoint">
<constructor-arg value="UNAUTHORIZED"/>
</bean>
<security:http auto-config="true" use-expressions="false" entry-point-ref="httpStatusEntryPoint">
<security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrentSessionFilter"/>
<security:form-login
authentication-success-handler-ref="authenticationSuccessHandler"
authentication-failure-handler-ref="authenticationFailureHandler"
/>
<security:intercept-url pattern="/api/**"/>
<security:anonymous enabled="false"/>
<security:logout logout-url="/logout" delete-cookies="JSESSIONID,sessionId"
success-handler-ref="logoutSuccessHandler"
/>
<security:csrf disabled="true"/>
<security:session-management session-authentication-strategy-ref="sessionAuthenticationStrategy"/>
</security:http>
<bean id="concurrentSessionFilter" class="***.***ConcurrentSessionFilter">
<constructor-arg ref="***SessionRegistry"/>
<constructor-arg ref="errorController"/>
</bean>
<bean id="sessionAuthenticationStrategy" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<constructor-arg>
<list>
<ref bean="registerSessionAuthenticationStrategy"/>
<ref bean="concurrentSessionControlAuthenticationStrategy"/>
</list>
</constructor-arg>
</bean>
<bean id="registerSessionAuthenticationStrategy" class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<constructor-arg name="sessionRegistry" ref="***SessionRegistry" />
</bean>
<bean id="concurrentSessionControlAuthenticationStrategy" class="***.web.security.***ConcurrentSessionControlAuthenticationStrategy">
<constructor-arg name="sessionRegistry" ref="***SessionRegistry" />
<constructor-arg name="logoutService" ref="logoutService"/>
<property name="maximumSessions" value="1" />
</bean>
<!-- enable spring security annotation processing -->
<security:global-method-security secured-annotations="enabled"/>
<bean id="***LdapAuthenticationProvider" class="***.web.***LdapAuthProvider">
<property name="url" value="${ldap.url}"/>
<property name="filter" value="${ldap.filter}"/>
<property name="domain" value="${ldap.domain}"/>
<property name="dn" value="${ldap.dn}"/>
<property name="ldapEnabled" value="${ldap.enable}"/>
</bean>
<security:authentication-manager>
<security:authentication-provider ref="***LdapAuthenticationProvider"/>
<security:authentication-provider user-service-ref="***UserDetailsService"/>
</security:authentication-manager>
<bean id="usersResource" class="org.springframework.core.io.ClassPathResource">
<constructor-arg value="/users.properties" />
</bean>
<util:property-path id="usersResourceFile" path="usersResource.file" />
<bean id="***UserDetailsService" class="***.web.security.***InMemoryUserDetailsManager">
<constructor-arg index="0" ref="usersResourceFile"/>
</bean>
I tried different ways But I can not find a way to exclude some specific URLs from authentication.
For example:
/api/url/available/without/login
should be available even user is not logged in.
P.S.
I have tried to apply this answer, but it doesn't work for me:
https://stackoverflow.com/a/5382178/2674303
UPD
I have tired
....
<bean id="httpStatusEntryPoint" class="org.springframework.security.web.authentication.HttpStatusEntryPoint">
<constructor-arg value="UNAUTHORIZED"/>
</bean>
<security:http pattern="/api/url/available/without/login" security="none"/>
<security:http auto-config="true" use-expressions="false" entry-point-ref="httpStatusEntryPoint">
....
but when I try to use - this url still locked and I get 401
because this code:
SecurityContext securityContext = SecurityContextHolder.getContext();
Authentication authentication = securityContext.getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
String name = authentication != null ? authentication.getName() : "";
throw new BadCredentialsException("Could not find user " + name);
}
throws exception
You just need to add a "default" http interceptor:
<security:http xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/" access="permitAll()"/>
<anonymous/>
<csrf disabled="true"/>
</security:http>
after your current security:http tag. It will handle all requests, which were not handled by the first http construction.
I am trying to setup my Spring CAS.XML file but I dont know why the file is not seeing the values I have set in the file:
Can someone please tell me what I am getting the following error:
2012-09-10 11:16:00,396 ERROR org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'requestSingleLogoutFilter' defined in ServletContext resource [/WEB-INF/spring/CAS-Local.xml]: Could not resolve placeholder 'cas.server.host'
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209)
if you look I do have the values setup at the end of the file...
Here is my CAS-Local.xml file:
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-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.1.xsd">
<security:http entry-point-ref="casEntryPoint"
use-expressions="true">
<security:intercept-url pattern="/" access="permitAll" />
<security:intercept-url pattern="/index.jsp"
access="permitAll" />
<security:intercept-url pattern="/cas-logout.jsp"
access="permitAll" />
<security:intercept-url pattern="/casfailed.jsp"
access="permitAll" />
<security:intercept-url access="hasRole('ROLE_MEMBER_INQUIRY')"
pattern="/visit**" />
<security:custom-filter ref="requestSingleLogoutFilter"
before="LOGOUT_FILTER" />
<security:custom-filter ref="singleLogoutFilter"
before="CAS_FILTER" />
<security:custom-filter ref="casFilter"
position="CAS_FILTER" />
<security:logout logout-success-url="/cas-logout.jsp" />
</security:http>
<security:authentication-manager alias="authManager">
<security:authentication-provider
ref="casAuthProvider" />
</security:authentication-manager>
<security:ldap-server id="ldapServer"
url="ldaps://dvldap01.uftwf.dev:636/dc=uftwf,dc=dev" manager-dn="cn=xxx,dc=uftwf,dc=dev"
manager-password="xxx" />
<security:ldap-user-service id="userServiceLDAP"
server-ref="ldapServer" user-search-base="ou=webusers"
user-search-filter="(uid={0})" group-search-base="ou=groups"
group-role-attribute="cn" group-search-filter="(uniqueMember={0})"
role-prefix="ROLE_" />
<!-- This filter handles a Single Logout Request from the CAS Server -->
<bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter" />
<!-- This filter redirects to the CAS Server to signal Single Logout should
be performed -->
<bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter"
p:filterProcessesUrl="/j_spring_cas_security_logout">
<constructor-arg
value="https://${cas.server.host}/cas-server-webapp/logout" />
<constructor-arg>
<bean
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</constructor-arg>
</bean>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties"
p:service="http://wcmisdlin07.uftmasterad.org:8080/SchoolVisitLocked/j_spring_cas_security_check"
p:authenticateAllArtifacts="true" />
<bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint"
p:serviceProperties-ref="serviceProperties"
p:loginUrl="https://6dvews01.uftwf.dev:8443/cas-server-webapp/login" />
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter"
p:authenticationManager-ref="authManager" p:serviceProperties-ref="serviceProperties"
p:proxyGrantingTicketStorage-ref="pgtStorage"
p:proxyReceptorUrl="/j_spring_cas_security_proxyreceptor">
<property name="authenticationDetailsSource">
<bean
class="org.springframework.security.cas.web.authentication.ServiceAuthenticationDetailsSource" />
</property>
<property name="authenticationFailureHandler">
<bean
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:defaultFailureUrl="/casfailed.jsp" />
</property>
<property name="authenticationSuccessHandler">
<bean
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"
p:defaultTargetUrl="/visit" />
</property>
</bean>
<!-- NOTE: In a real application you should not use an in memory implementation.
You will also want to ensure to clean up expired tickets by calling ProxyGrantingTicketStorage.cleanup() -->
<bean id="pgtStorage"
class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
<bean id="casAuthProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider"
p:serviceProperties-ref="serviceProperties" p:key="casAuthProviderKey">
<property name="authenticationUserDetailsService">
<bean
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg ref="userServiceLDAP" />
</bean>
</property>
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0"
value="https://6dvews01.uftwf.dev:8443/cas-server-webapp" />
</bean>
</property>
</bean>
<!-- Configuration for the environment can be overriden by system properties -->
<context:property-placeholder
system-properties-mode="OVERRIDE" properties-ref="environment" />
<util:properties id="environment">
<prop key="cas.service.host">wcmisdlin07.uftmasterad.org:8443</prop>
<prop key="cas.server.host">6dvews01.uftwf.dev:8443</prop>
</util:properties>
</beans>
you use placeholders for properties like "${cas.server.host}" which must be defined in a property file and resolved by spring. create a new property file "your.properties" in your classpath and add this into your context:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>your.properties</value>
</property>
</bean>
your.properties:
cas.server.host=http://localhost/abc