I tried to implement a role hierarchy but it doesn't want to work. everything else works perfectly except that. Here is my spring-security.xml:
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Enable method-level security via annotations -->
<global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>
<!-- Configure form-based authentication -->
<http auto-config="true" use-expressions="true" entry-point-ref="securityEntryPoint" >
<intercept-url pattern="/resources/script/jquery-ui/**" access="permitAll" />
<intercept-url pattern="/resources/script/jquery*" access="permitAll" />
[....]
<intercept-url pattern="/**" access="isAuthenticated()" />
<session-management invalid-session-url="/login.jsp?info=invalid" >
<concurrency-control max-sessions="1" session-registry-alias="sessionRegistry" expired-url="/login.jsp?info=expired" />
</session-management>
<form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=credentials" />
<logout logout-url="/logout" invalidate-session="true" logout-success-url="/login.jsp" />
</http>
<!-- Configure a spring security logger listener for logging authentication attempts. -->
<beans:bean id="loggerListener" class="org.springframework.security.access.event.LoggerListener"/>
<!-- Configure a delegating entry point -->
<beans:bean id="securityEntryPoint" class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
<!-- Requests of type text/html or application/xhtml+xml should be handled by form-based authentication -->
<beans:constructor-arg>
<beans:map>
<beans:entry>
<beans:key>
<beans:bean class="com.test.security.AcceptHeaderRequestMatcher"/>
</beans:key>
<beans:bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.jsp" />
</beans:bean>
</beans:entry>
</beans:map>
</beans:constructor-arg>
<!-- Otherwise use BASIC authentication by default -->
<beans:property name="defaultEntryPoint">
<beans:bean class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<beans:property name="realmName" value="test Web Service" />
</beans:bean>
</beans:property>
</beans:bean>
<!-- Configure an authentication manager via our defaultUserService -->
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="defaultUserService">
<password-encoder hash="md5" />
</authentication-provider>
</authentication-manager>
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:ref bean="roleVoter" />
<beans:ref bean="authenticatedVoter" />
</beans:list>
</beans:property>
<beans:bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
<beans:constructor-arg ref="roleHierarchy" />
<beans:property name="rolePrefix" value="" />
</beans:bean>
<beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<beans:property name="hierarchy">
<beans:value>
PERM_READ_ALL_USER_LIST > PERM_READ_USER_LIST
</beans:value>
</beans:property>
</beans:bean>
If i try to access a resource for which PERM_READ_USER_LIST is required, #PreAuthorize("hasRole('PERM_READ_USER_LIST')"), with a user who has the PERM_READ_ALL_USER_LIST it doesn't work, but if he has PERM_READ_USER_LIST, it works. So obviously the rolevoter is not doing its job but I don't get why...
Thank you.
You have to specify the hirarchy explicite for the MethodSecurityExpressionHandler.
See this Stack Overflow question and answer for more details.
How to use role-hierarchy in Spring Security 3 with Spring EL?
Related
I have an application develop on Spring 4.1.4 and Spring Security 4.0.2, deployed on a server with Apache Tomcat 8 and JDK 1.7.
It happens that after some days some users can't login anymore even if they specity correct user/password combination.
Restarting Tomcat fixes the problem.
Any suggestion?
May it be a session related issue?
This is my security configuration
<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"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd
">
<http auto-config="true" use-expressions="true">
<custom-filter after="EXCEPTION_TRANSLATION_FILTER" ref="ajaxTimeoutRedirectFilter"/>
<custom-filter position="SWITCH_USER_FILTER" ref="switchUserProcessingFilter" />
<intercept-url pattern="/j_spring_security_switch_user" access="hasRole('ROLE_SUPERVISOR')"/>
<session-management invalid-session-url="/login.html?invalidSession=1" session-fixation-protection="newSession">
<concurrency-control max-sessions="10" error-if-maximum-exceeded="true" />
</session-management>
<intercept-url pattern="/login.html" access="hasRole('ROLE_ANONYMOUS')" requires-channel="https"/>
<intercept-url pattern="/resources/**" access="permitAll" requires-channel="any"/>
<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')" requires-channel="https"/>
<intercept-url pattern="/rest/**" access="hasRole('ROLE_USER')" requires-channel="https"/>
<intercept-url pattern="/index" access="hasRole('ROLE_USER')" requires-channel="https"/>
<intercept-url pattern="/upload/**" access="hasRole('ROLE_USER')" requires-channel="https"/>
<headers>
<xss-protection block="false"/>
<frame-options disabled="true"/>
<cache-control/>
</headers>
<!-- access denied page -->
<access-denied-handler error-page="/403" />
<form-login
login-page="/login.html"
default-target-url="/index"
always-use-default-target="true"
authentication-failure-url="/login.html?error=1"
username-parameter="username"
password-parameter="password"/>
<logout logout-success-url="/login.html?logout=1" invalidate-session="false" delete-cookies="JSESSIONID"/>
<!-- enable csrf protection -->
<!-- <csrf disabled="true" /> -->
<port-mappings>
<port-mapping http="8080" https="8443"/>
</port-mappings>
</http>
<beans:bean id="ajaxTimeoutRedirectFilter" class="com.finconsgroup.mens.springsecurity.AjaxTimeoutRedirectFilter">
<beans:property name="customSessionExpiredErrorCode" value="419"/>
</beans:bean>
<beans:bean id="switchUserProcessingFilter" class="com.finconsgroup.mens.springsecurity.MensSwitchUserFilter">
<beans:property name="userDetailsService" ref="mensAuthenticationService"/>
<beans:property name="switchUserUrl" value="/j_spring_security_switch_user"/>
<beans:property name="exitUserUrl" value="/j_spring_security_exit_user"/>
<beans:property name="targetUrl" value="/index"/>
</beans:bean>
<beans:bean name="bcryptEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!-- Select users and user_roles from database -->
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="mensAuthenticationService">
<password-encoder ref="bcryptEncoder"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="mensAuthenticationService" class="com.finconsgroup.mens.springsecurity.MensAuthenticationProvider">
<beans:property name="dataSource" ref="mensDataSource"/>
<beans:property name="usersByUsernameQuery" value="my_query"/>
<beans:property name="authoritiesByUsernameQuery" value="my_query"/>
<beans:property name="groupAuthoritiesByUsernameQuery" value="my_query"/>
<beans:property name="enableGroups" value="true"/>
</beans:bean>
<!-- Spring Security -->
<beans:bean id="mensPermissionEvaluator" class="com.finconsgroup.mens.springsecurity.MensPermissionEvaluator">
<beans:constructor-arg ref="aclService"/>
</beans:bean>
<beans:bean id="securityExpressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="mensPermissionEvaluator"/>
</beans:bean>
<global-method-security
authentication-manager-ref="authenticationManager"
pre-post-annotations="enabled"
secured-annotations="enabled">
<expression-handler ref="securityExpressionHandler"/>
</global-method-security>
<!-- ================================================================== -->
<!-- ACL service -->
<!-- ================================================================== -->
<beans:bean id="aclService" class="org.springframework.security.acls.jdbc.JdbcMutableAclService">
<beans:constructor-arg ref="mensDataSource" />
<beans:constructor-arg ref="lookupStrategy" />
<beans:constructor-arg ref="aclCache" />
</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:ref bean="mensEhCacheManager"/>
</beans:property>
<beans:property name="cacheName" value="aclCache"/>
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean class="org.springframework.security.acls.domain.DefaultPermissionGrantingStrategy">
<beans:constructor-arg>
<beans:bean class="org.springframework.security.acls.domain.ConsoleAuditLogger"/>
</beans:constructor-arg>
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean 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_ACL_ADMIN"/>
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<beans:constructor-arg ref="mensDataSource" />
<beans:constructor-arg ref="aclCache" />
<beans:constructor-arg>
<!-- Decides whether current principal can make ACL changes. See
AclAuthorizationStrategyImpl Javadoc for the rules involved. -->
<beans:bean class="org.springframework.security.acls.domain.AclAuthorizationStrategyImpl">
<beans:constructor-arg>
<beans:list>
<!-- Role required to change ACL ownership -->
<beans:ref bean="adminRole" />
<!-- Role required to change auditing details -->
<beans:ref bean="adminRole" />
<!-- Role required to change other ACL/ACE details -->
<beans:ref bean="adminRole" />
</beans:list>
</beans:constructor-arg>
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean class="org.springframework.security.acls.domain.ConsoleAuditLogger" />
</beans:constructor-arg>
</beans:bean>
<beans:bean id="adminRole" class="org.springframework.security.core.authority.SimpleGrantedAuthority">
<beans:constructor-arg value="ADMIN" />
</beans:bean>
Thank you in advance for your help!
I fixed the problem changing the session-fixation-protection attribute to migrateSession.
Now I have no need to restart Tomcat periodically.
I'm using Spring 4.2.1.RELEASE, Spring Security 4.0.2.RELEASE and Spring Security OAuth 2.0.7.RELEASE to build a web application with a RESTful API.
Previously my login functionality wasn't 100% RESTful because I used cookies for authentication.
Now I need to move to pure RESTful with token authentication through an OAuth endpoint.
I followed many guides, and in particular this one : https://www.youtube.com/watch?v=LnJsspvxE1c
When I try to get an access token I make the following request with Postman.
HTTP GET
http://localhost:8080/oauth/token?grant_type=password&client_id=trusted-client&username=name&password=pass
But I always get a 404 Not Found.
I can't find where I'm wrong.
Below is my spring security configuration file.
```
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
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-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.0.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- Definition of the Authentication Service -->
<http pattern="/oauth/token"
create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/oauth/token"
access="isAuthenticated()"/>
<anonymous enabled="false"/>
<http-basic entry-point-ref="clientAuthenticationEntryPoint"/>
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER"/>
<access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>
<!-- Protected resources -->
<http auto-config="true"
use-expressions="true"
pattern="/api/**"
create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager"
xmlns="http://www.springframework.org/schema/security">
<anonymous enabled="false"/>
<intercept-url pattern="/api/**" access="ROLE_USER" />
<custom-filter ref="resourceServerFilter"
before="PRE_AUTH_FILTER"/>
<access-denied-handler
ref="oauthAccessDeniedHandler"/>
</http>
<beans:bean id="oauthAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="auth"/>
</beans:bean>
<beans:bean id="clientAuthenticationEntryPoint"
class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<beans:property name="realmName" value="auth/client"/>
<beans:property name="typeName" value="Basic"/>
</beans:bean>
<beans:bean
id="oauthAccessDeniedHandler"
class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler"/>
<beans:bean id="clientCredentialsTokenEndpointFilter"
class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<beans:property name="authenticationManager"
ref="clientAuthenticationManager"/>
</beans:bean>
<beans: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"/>
<bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
</list>
</constructor-arg>
</beans:bean>
<!-- Authentication in config file -->
<authentication-manager id="clientAuthenticationManager"
xmlns="http://www.springframework.org/schema/security">
<authentication-provider user-service-ref="clientDetailsUserService"/>
</authentication-manager>
<beans:bean id="passwordEncoder"
class="org.springframework.security.authentication.encoding.Md5PasswordEncoder">
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="customUserService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
<beans:bean id="clientDetailsUserService"
class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<beans:constructor-arg ref="clientDetails"/>
</beans:bean>
<!-- Token Store -->
<beans:bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore"/>
<beans:bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<beans:property name="tokenStore" ref="tokenStore"/>
<beans:property name="supportRefreshToken" value="true"/>
<beans:property name="clientDetailsService" ref="clientDetails"/>
<beans:property name="accessTokenValiditySeconds" value="10"/>
</beans:bean>
<beans:bean id="oAuth2RequestFactory"
class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
<beans:constructor-arg ref="clientDetails" />
</beans:bean>
<beans:bean id="userApprovalHandler"
class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<beans:property name="tokenStore" ref="tokenStore"/>
<beans:property name="requestFactory" ref="oAuth2RequestFactory" />
<beans:property name="clientDetailsService" ref="clientDetails"/>
</beans:bean>
<!-- Token management -->
<oauth:authorization-server client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler"
token-endpoint-url="/oauth/token">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password/>
</oauth:authorization-server>
<oauth:resource-server id="resourceServerFilter"
resource-id="auth"
token-services-ref="tokenServices"/>
<!-- Client Definition -->
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="trusted-client"
authorized-grant-types="password,authorization_code,refresh_token,implicit,redirect"
authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT"
redirect-uri="/secure/index"
scope="read,write,trust"
access-token-validity="30"
refresh-token-validity="600"/>
</oauth:client-details-service>
<global-method-security pre-post-annotations="enabled"
secured-annotations="enabled"
proxy-target-class="true" order="1" >
<expression-handler ref="oauthExpressionHandler"/>
</global-method-security>
<oauth:expression-handler id="oauthExpressionHandler"/>
<oauth:web-expression-handler id="oauthWebExpressionHandler"/>
Grant type password expects a POST query to /oauth/token, not the GET one.
So it should be:
curl -X POST -d 'grant_type=password&client_id=trusted-client&username=name&password=pass' 'http://localhost:8080/oauth/token'
In addition, your oauth/token endpoint is available for isAuthenticated users only:
<intercept-url pattern="/oauth/token" access="isAuthenticated()"/>
but as far as I understand you make a call as a anonymous user.
I upgraded Spring Security from 2 to 3
Previously Security.xml has AuthenticationProcessingFilter and AuthenticationProcessingFilterEntryPoint
So my new Security.xml is
<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-3.0.3.xsd">
<beans:bean id="userAuthenticationService"
class="com.raykor.core.service.UserAuthenticationService" />
<beans:bean id="shaEncoder"
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" />
<global-method-security />
<http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint">
<intercept-url pattern="/resettingPassword.do**" access="ROLE_ADMIN" />
<intercept-url pattern="/resetPassword.do**" access="ROLE_ADMIN" />
<logout logout-success-url="/index.jsp" invalidate-session="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="userAuthenticationService">
<password-encoder ref="shaEncoder">
<salt-source user-property="salt" />
</password-encoder>
</authentication-provider>
</authentication-manager>
<beans:bean id="authenticationFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="authenticationFailureHandler"
ref="failureHandler" />
<beans:property name="authenticationSuccessHandler"
ref="successHandler" />
</beans:bean>
<beans:bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="alwaysUseDefaultTargetUrl" value="false" />
<beans:property name="defaultTargetUrl" value="/home.do" />
</beans:bean>
<beans:bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.do?error=true" />
</beans:bean>
<beans:bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/login.do" />
<beans:property name="forceHttps" value="false" />
</beans:bean>
`
Also added filter springSecurityFilterChain in web.xml
On login.do it opens Login Page,On Submit it submits to j_spring_security_check with username and password as j_username & j_password
So why is it saying as j_spring_security_checknot avaliable
You instantiate a UsernamePasswordAuthenticationFilter, but it won't be part of the security filter chain just by creating it. Try removing the auto-config="false" from the http config element, and include a <form-login> element within that. I think all the configuration that you have done through the bean definitions can be done using the more concise namespace configuration which should be preferred with Spring Security 3.
I missed to add custom-filter ref i updated
as
<http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint">
<custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter"/>
<intercept-url pattern="/resettingPassword.do**" access="ROLE_ADMIN" />
<intercept-url pattern="/resetPassword.do**" access="ROLE_ADMIN" />
<logout logout-success-url="/index.jsp" invalidate-session="true" />
</http>
I'm developing a web application using Spring MVC and Spring security. Actually I do not have an error but a warning instead. It looks like this warning will come up with an error soon:)
When I try to deploy my application, it is deployed successfully but a warning appears:
"WARNING: Possible error: Filters at position 7 and 8 are both instances of org.springframework.security.web.session.SessionManagementFilter"
I have both sessionManagementFilter and preAuthenticationFilter in my spring-security xml.
I've googled the problem but it looks like there is not anybody that gets the same warning. What is this warning? Will it cause an error and how can I fix it? I cannot solve the issue, I'll be appreciated if someone helps me. Thank you.
My spring-security.xml:
<?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.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http create-session="never" use-expressions="true" auto-config="false" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint">
<custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<intercept-url pattern="/restricted/**" access="isAuthenticated()" />
<custom-filter position="PRE_AUTH_FILTER" ref="myPreAuthFilter" />
<session-management>
<concurrency-control max-sessions="1" error-if-maximum-exceeded="false" expired-url="/invalid-session.xhtml?concurrent=true" />
</session-management>
<logout logout-url="/cikis" invalidate-session="true" delete-cookies="JSESSIONID" success-handler-ref="myLogoutHandler" />
</http>
<beans:bean id="myLogoutHandler" class="com.test.MyLogoutHandler" />
<beans:bean id="userDetailsServiceImpl" class="com.test.UserDetailsServiceImpl" />
<beans:bean id="preAuthenticatedProcessingFilterEntryPoint" class="com.test.ForbiddenURLEntryPoint" />
<beans:bean id="preAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="userDetailsServiceImpl" />
</beans:bean>
<beans:bean id="myPreAuthFilter" class="com.test.MyPreAuthenticationFilter">
<beans:property name="authenticationManager" ref="appControlAuthenticationManager" />
</beans:bean>
<beans:bean id="sessionManagementFilter" class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg name="securityContextRepository" ref="httpSessionSecurityContextRepository" />
<beans:property name="invalidSessionStrategy" ref="jsfRedirectStrategy" />
</beans:bean>
<beans:bean id="jsfRedirectStrategy" class="com.test.JsfRedirectStrategy"/>
<beans:bean id="httpSessionSecurityContextRepository" class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"/>
<authentication-manager alias="appControlAuthenticationManager">
<authentication-provider ref="preAuthenticationProvider" />
</authentication-manager>
</beans:beans>
Spring security includes SessionManagementFilter by default on startup.
If you want to specify your own SESSION_MANAGEMENT_FILTER you have to disable session-fixation-protection, just type:
<http create-session="never" use-expressions="true" auto-config="false" entry-point-ref="preAuthenticatedProcessingFilterEntryPoint">
<session-management session-fixation-protection="none"/>
<custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<...>
</http>
I am using role hierarchy in Spring Security as in my question. When I try to secure a method with #PreAuthorize("hasRole('ROLE_USER')"), I always got AccessDeniedException. However, if I change it to #Secured("ROLE_USER") or
<protect-pointcut
expression="execution(* my.package.Class.*(..))"
access="ROLE_GUEST" />
I have no issue. From this answer, both should behave the same except the listed differences. Am I missing something here?
Edit:
Here is my configuration.
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http entry-point-ref="entryPoint">
<anonymous enabled="false" />
</http>
<beans:bean id="entryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
<global-method-security secured-annotations="enabled"
pre-post-annotations="enabled" access-decision-manager-ref="accessDecisionManager">
<!-- this is disable if I secure with annotation #Secured -->
<protect-pointcut
expression="execution(* my.package.Class.*(..))"
access="ROLE_GUEST" />
</global-method-security>
<beans:bean id="accessDecisionManager"
class="org.springframework.security.access.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:ref bean="roleHierarchyVoter" />
</beans:list>
</beans:property>
</beans:bean>
<beans:bean id="roleHierarchyVoter"
class="org.springframework.security.access.vote.RoleHierarchyVoter">
<beans:constructor-arg ref="roleHierarchy" />
</beans:bean>
<beans:bean id="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
<beans:property name="hierarchy">
<beans:value>
ROLE_USER > ROLE_GUEST
</beans:value>
</beans:property>
</beans:bean>
<beans:bean id="userDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="enableGroups" value="true" />
<beans:property name="enableAuthorities" value="false" />
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
</authentication-provider>
</authentication-manager>
</beans:beans>
I'm not so sure how your configuration looks like as you are referring to another post. The solution might be simple. Leave out access-decision-manager-ref as:
<sec:global-method-security
secured-annotations="enabled" pre-post-annotations="enabled" />
In practice, if Pre* / Post* annotations are being used for method security, a voter-based system is not really necessary. Actually there is no voter for that at all, so all other voters abstain and the access is denied.