I have a general question. I have a web project written using Spring Security 3.2 and Spring 4. I deployed project in Tomcat 7.0. There are 2 roles in spring sec for project users: USER and COMPANY. When I log in from home computer (without any proxy), everything works fine. But if I login from my work computer (my computer is behind company proxy) my web application does not work properly, It cannot get localization or often it gives USER role to company account and etc. I looked for this issue in web, but cannot find any solutions. Hope anybody can figure out what can be the reason. Thanks in advance..
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:security="http://www.springframework.org/schema/security"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd">
<bean id="securityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" />
<security:global-method-security
pre-post-annotations="enabled">
<security:expression-handler ref="securityExpressionHandler" />
</security:global-method-security>
<security:http auto-config="false" use-expressions="true" access-denied-page="/login" entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/account/register" access="permitAll"/>
<security:intercept-url pattern="/main" access="hasAnyRole('ROLE_USER, ROLE_COMPANY')"/>
<security:intercept-url pattern="/profile" access="hasAnyRole('ROLE_USER, ROLE_COMPANY')"/>
<security:intercept-url pattern="/wishlist" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/messagebox" access="hasAnyRole('ROLE_USER, ROLE_COMPANY')"/>
<security:intercept-url pattern="/settings" access="hasAnyRole('ROLE_USER, ROLE_COMPANY')"/>
<security:intercept-url pattern="/search" access="hasAnyRole('ROLE_USER, ROLE_COMPANY')"/>
<security:logout invalidate-session="true" logout-success-url="/login" logout-url="/logout" />
<security:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER"/>
<security:custom-filter ref="concurrencyFilter" position="CONCURRENT_SESSION_FILTER"/>
<security:session-management session-authentication-strategy-ref="sas" />
</security:http>
<bean id="authenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"
p:sessionAuthenticationStrategy-ref="sas"
p:authenticationManager-ref="authenticationManager"
p:authenticationFailureHandler-ref="customAuthenticationFailureHandler"
p:authenticationSuccessHandler-ref="customAuthenticationSuccessHandler"/>
<bean id="customAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"
p:defaultFailureUrl="/login?fail=true" />
<!-- We just actually need to set the default target url here -->
<bean id="customAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler"
p:defaultTargetUrl="/main" />
<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"
p:loginFormUrl="/login"/>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="customAuthenticationProvider" />
</security:authentication-manager>
<bean id="customAuthenticationProvider" class="service.CustomAuthenticationManager">
</bean>
<!-- A custom service where Spring will retrieve users and their corresponding access levels -->
<bean id="customUserDetailsService" class="service.CustomUserDetailsService"/>
<bean id="concurrencyFilter" class="filter.AzunisConcurrentSessionFilter"
p:sessionRegistry-ref="sessionRegistry"
p:expiredUrl="/login" />
<bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"
p:maximumSessions="-1" p:exceptionIfMaximumExceeded="false" p:alwaysCreateSession="true">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
</bean>
<!-- Maintains a registry of SessionInformation instances
See: http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/core/session/SessionRegistry.html -->
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
I think this is the caching mechanism of the proxy. Let the login and landingpage site expiring with in your Response Header.
Related
I have a problem to properly configure Spring oauth using xml, as I have to add this support to an existing project is required to perform the configuration from XML, I have to integrate Spring MVC, Spring and Spring Security OAuth. I have a project which I have set for trial purposes Spring MVC and Spring security and I have another project where I could configure Spring Oauth it performs authentication password, I could not make it work integrating OAuth (safely through verification code) in the first project, not to me this missing, any suggestion or tip to configure this?
*File: 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:security="http://www.springframework.org/schema/security"
xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
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.2.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd">
<security:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
</security:global-method-security>
<security:http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<security:intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
<security:anonymous enabled="false" />
<security:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>
<!-- This is where we tells spring security what URL should be protected and what roles have access to them -->
<security:http pattern="/oauth/api/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/oauth/api/**" access="hasAnyRole('ROLE_USER')" />
<security:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
</security:http>
<!-- Configuracion de spring global -->
<security:http pattern="/login**" security="none" />
<security:http pattern="/login/**" security="none" />
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER') or #oauth2.clientHasRole('ROLE_USER')"/>
<security:intercept-url pattern="/main" access="hasAnyRole('ROLE_USER') or #oauth2.clientHasRole('ROLE_USER')"/>
<security:form-login authentication-success-handler-ref="authenticationSuccessRedirectHandler"
login-page="/login" default-target-url="/" authentication-failure-url="/login/fail" />
<security:logout logout-success-url="/login" delete-cookies="true" invalidate-session="true" />
</security:http>
<bean id="authenticationSuccessRedirectHandler" class="mx.oauth.resourceserver.AuthenticationHandler" />
<security:authentication-manager id="authenticationManager">
<security:authentication-provider>
<security:user-service>
<security:user name="marcos" password="pwd" authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
<!-- Configuracion 2 Oauth -->
<oauth:expression-handler id="oauthExpressionHandler" />
<oauth:web-expression-handler id="oauthWebExpressionHandler" />
<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:password authentication-manager-ref="authenticationManager"/>
</oauth:authorization-server>
<oauth:client-details-service id="clientDetails">
<!-- client -->
<oauth:client client-id="restapp2" authorized-grant-types="authorization_code,client_credentials" authorities="ROLE_USER" scope="read,write,trust" secret="secret" />
<oauth:client client-id="restapp" authorized-grant-types="password,authorization_code,refresh_token,implicit" secret="restapp" authorities="ROLE_USER" />
</oauth:client-details-service>
<!-- This defined token store, we have used inmemory tokenstore for now but this can be changed to a user defined one -->
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore" />
<!-- This is where we defined token based configurations, token validity
and other things -->
<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="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler">
<property name="tokenServices" ref="tokenServices" />
</bean>
<bean id="accessConfirmationController" class="mx.oauth.resourceserver.AccessConfirmationController">
<property name="clientDetailsService" ref=""clientDetails />
<property name="approvalStore" ref="clientDetails" />
</bean>
</beans>
I have a web app where you can login with form-login or you can be pre-authenticated and be logged in like that. Both method work well but I only can find way to use a success handler with the form-login using the authentication-success-handler-ref property.
My question is, how can I call the success handler "mySuccessHandler" for the PRE_AUTH_FILTER in my security-app-context? I would guess I can call it as a property or something under the PreAuthenticatedProcessingFilter, preauthAuthProvider or the custom-filter.
Just need to go to different pages if the user has the role Teacher or Student.
<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.2.xsd">
<http pattern="/**" use-expressions="true" create-session="always">
<intercept-url pattern="/login.jsp*" access="permitAll" />
<intercept-url pattern="/**/ErrorPages/**" access="permitAll" />
<intercept-url pattern="/**/Students/**" access="hasAnyRole('STUDENT, TEACHER')" />
<intercept-url pattern="/**/Teacher/**" access="hasRole('TEACHER')" />
<intercept-url pattern="/**/Login/**" access="hasRole('ROLE_USER')" />
<intercept-url pattern="/**/Js/**" access="hasRole('ROLE_USER')" />
<intercept-url pattern="/**/Css/**" access="permitAll" />
<intercept-url pattern="/**/Img/**" access="permitAll" />
<intercept-url pattern="/**/api/**" access="hasRole('ROLE_USER')" />
<intercept-url pattern="/**" access="denyAll" />
<custom-filter position="PRE_AUTH_FILTER" ref="PreAuthenticatedProcessingFilter" />
<access-denied-handler
<form-login
username-parameter="idnumber"
password-parameter="password" login-processing-url="/athuga_innskraningu"
login-page='/login.jsp'
authentication-failure-handler-ref="myAuthErrorHandler"
authentication-success-handler-ref="mySuccessHandler"
always-use-default-target='true'
authentication-failure-url="/login.jsp?login_error=true"/>
<logout logout-url="/utskra/" logout-success-url="/login.jsp"/>
</http>
<beans:bean id="mySuccessHandler" class="is.inna.rest.login.AuthenticationSuccess"/>
<beans:bean id="myAuthErrorHandler" class="is.inna.rest.login.AuthenticationFailure"/>
<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<beans:bean name="myUserDetailsService" class="is.inna.rest.login.UserDetailServiceLogin" />
<beans:bean id="userDetailsServiceWrapper" class="is.inna.rest.login.UserDetailServicePreAuth" />
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="myUserDetailsService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
<authentication-provider ref="preauthAuthProvider" />
</authentication-manager>
<beans:bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<beans:property name="preAuthenticatedUserDetailsService" ref="userDetailsServiceWrapper"/>
</beans:bean>
<beans:bean id="PreAuthenticatedProcessingFilter" class="is.inna.rest.login.PreAuthenticatedProcessingFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>
Your requirement is to redirect user to different pages depending on the role. You can do this using authentication success handler also. Refer the sample success handler class I have written. You always have access to Authentication object in the overridden onAuthenticationSuccess method. You can get the authorities and role of logged in user and depending upon it, you can always redirect user to appropriate page.
Hope this helps.
We already have an OAuth2 authorization server set up, so I need to create a corresponding resource server (separate server). We plan to use the Spring Security OAuth2 project. Their documentation for setting up a resource server:
https://github.com/spring-projects/spring-security-oauth/wiki/oAuth2#resource-server-configuration
token-services-ref should point to the token-handling bean. However it seems like the token handling is done by the server itself even though it is the resource server. There doesn't seem to be any remote token services class or any configuration relating to a remote server. This is in contrast with the CloudFoundary UAA (https://github.com/cloudfoundry/uaa/blob/master/samples/api/src/main/webapp/WEB-INF/spring-servlet.xml) which has:
<bean id="tokenServices"
class="org.cloudfoundry.identity.uaa.oauth.RemoteTokenServices">
<property name="checkTokenEndpointUrl" value="${checkTokenEndpointUrl}" />
Is there any way to use Spring Security OAuth2 for a resource server that communicates with a separate OAuth2 Authorization server? How can I set the communication endpoint?
This is possible as long as the authorization server and resource server(s) access a shared tokenStore (e.g. using JdbcTokenStore with a common dataSource). You can just use DefaultTokenServices with a reference to your shared tokenStore. Below is an example Spring config which you should be able to tweak to fit your needs:
<?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:oauth2="http://www.springframework.org/schema/security/oauth2"
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.1.xsd
http://www.springframework.org/schema/security/oauth2
http://www.springframework.org/schema/security/spring-security-oauth2.xsd">
<bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.JdbcTokenStore">
<constructor-arg name="dataSource" ref="dataSource" />
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
</bean>
<bean id="authenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="myRealm" />
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
<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.access.vote.AuthenticatedVoter" />
</list>
</constructor-arg>
</bean>
<!-- This is not actually used, but it's required by Spring Security -->
<security:authentication-manager alias="authenticationManager" />
<oauth2:expression-handler id="oauthExpressionHandler" />
<oauth2:web-expression-handler id="oauthWebExpressionHandler" />
<security:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<security:expression-handler ref="oauthExpressionHandler" />
</security:global-method-security>
<oauth2:resource-server id="myResource" resource-id="myResourceId" token-services-ref="tokenServices" />
<security:http pattern="/myPattern/**" create-session="never"
entry-point-ref="authenticationEntryPoint" access-decision-manager-ref="accessDecisionManager">
<security:anonymous enabled="false" />
<security:intercept-url pattern="/**" access="SCOPE_READ" method="GET" />
<security:intercept-url pattern="/**" access="SCOPE_READ" method="HEAD" />
<security:intercept-url pattern="/**" access="SCOPE_READ" method="OPTIONS" />
<security:intercept-url pattern="/**" access="SCOPE_WRITE" method="PUT" />
<security:intercept-url pattern="/**" access="SCOPE_WRITE" method="POST" />
<security:intercept-url pattern="/**" access="SCOPE_WRITE" method="DELETE" />
<security:custom-filter ref="myResource" before="PRE_AUTH_FILTER" />
<security:access-denied-handler ref="oauthAccessDeniedHandler" />
<security:expression-handler ref="oauthWebExpressionHandler" />
</security:http>
</beans>
Yes its possible. Like you have already mentioned in your question, RemoteTokenServices is the solution.
I have created one sample which has separate auth and resource server. Its just a sample to give a quick idea about the concept and open for extension.
Spring-AngularJS-OAuth2-Sample
I am adding Spring Security to one Spring project.
The architecture of the system is REST and user can access to different resources.
I would like to give access to personal information to administrators and users that are owners of this information.
I have started simple: filtering user profile like this:
In my service layer I wanted to use method annotations and include method parameters..
#PreAuthorize("hasRole('ROLE_ADMIN') or principal.userId == #id")
public Usuario getUser(int id) throws DAOException {
...
}
But this is not working at all. Any user can see all profiles (admins and all users also) when this URL is requested (Web layer):
#RequestMapping(value="/user/{uid}", method=RequestMethod.GET)
public ModelAndView getUser(#PathVariable int uid) throws DAOException {
userDAO = new UsuarioJPADAO();
userService.setUsuarioDAO(userDAO);
return new ModelAndView("user", "user", userService.getUser(uid));
}
Here is my 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">
<!-- Security Annotations -->
<global-method-security
pre-post-annotations="enabled"/>
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/css/**" access="permitAll" />
<intercept-url pattern="/images/**" access="permitAll" />
<intercept-url pattern="/js/**" access="permitAll" />
<intercept-url pattern="/favicon.ico" access="permitAll" />
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/users" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/users/page/*" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/customers" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/employees" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/search/*" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/*" access="hasAnyRole('ROLE_ADMIN, ROLE_EMPLOYEE, ROLE_PARTNER, ROLE_USER')" />
<intercept-url pattern="/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<form-login login-page="/login" login-processing-url="/doLogin"
authentication-failure-url="/login?error"
username-parameter="username" password-parameter="password"
default-target-url="/default" />
<logout invalidate-session="true" logout-success-url="/login?logout" logout-url="/logout"/>
</http>
<authentication-manager>
<authentication-provider user-service-ref="UsuarioService">
</authentication-provider>
</authentication-manager>
I have checked Spring Security 3.1 book and apparently my configuration is as book suggests. I have read other Stack Overflow posts (here and here) but I had no luck.
Update: Added application-context.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:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
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.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<context:annotation-config />
<context:component-scan base-package="com.pe.fs" />
<mvc:annotation-driven />
<mvc:resources mapping="/**" location="/" />
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptors>
<!-- DataSource -->
<bean id="jpaDataSource" class="oracle.jdbc.pool.OracleDataSource"
destroy-method="close"
p:driverType="oracle.jdbc.OracleDriver"
p:user="**********"
p:password="**********"
p:uRL="jdbc:oracle:thin:#localhost:1521:XE"
/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
<property name="persistenceUnitName" value="freesunPU" />
<property name="dataSource" ref="jpaDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="false" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" />
<tx:annotation-driven mode="aspectj"/>
<context:load-time-weaver aspectj-weaving="autodetect" />
Update: I have added spring-security-aspects to POM and no changes. Other changes suggested in answers have been tested with but annotations such #PreAuthorize are still not working. Cna this be a problem between contexts? Can be the usage of aspectJ the reason?
What am I doing wrong?
Finally I found solution.
In SO I found some usefull answers. See here and here.
I moved global-method-security to application-context.xml which is the context of my services.
<security:global-method-security
mode="aspectj"
secured-annotations="enabled"
jsr250-annotations="disabled"
pre-post-annotations="enabled"/>
Where mode="aspectj" as Javadoc says:
...can be used to specify that AspectJ should be used instead of the
default Spring AOP. If set, secured classes must be woven with the
AnnotationSecurityAspect from the spring-security-aspects module.
Of course, I have added to POM spring-security-aspects:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
Add new interface:
public interface UserService extends UserDetailsService {
Usuario getUser(int id) throws DAOException
}
Implement it in your user service and try again. Spring will be able add requested authorization checks using JDK proxies.
As another option you can configure Spring to use some more heavyweight libraries like Javassist or even AspectJ.In this case interface will be not necessary.
EDIT. Make sure that global-method-security is declared in the same spring context with your user service bean.
The alternative way to make it work is to add the following code in your security.xml
<intercept-url pattern="/user/**" access="hasRole('ROLE_ADMIN')" />
It will ensure that only admin can access the resources starting with pattern /user/.
Our application is built with Spring (MVC, transactions, authentication, etc). We use LoginUrlAuthenticationEntryPoint for authentication (please see below for the whole spring security xml). The web client (jsp) uses j_spring_security_check form to login to this app. The app has REST API and the browser code (web client) make REST calls to the app. So far so good and everything works fine. We are writing code in Java to test the app - end-to-end testing using REST calls (similar to how the real client, web client in my case, invokes the app). I am using Apache's HttpClient on the tests side to make REST calls to the app. Do you know how to authenticate/login to the app from the Java-written tests code? Any guidance is much appreciated. Thanks, prams.
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>
<security:http auto-config="false" use-expressions="true" entry-point-ref="authenticationEntryPoint">
<security:intercept-url pattern="/login*" filters="none"/>
<security:intercept-url pattern="/agentMsg" filters="none"/>
<security:intercept-url pattern="/wait" filters="none"/>
<security:intercept-url pattern="/systemConfig/**" filters="none"/>
<security:intercept-url pattern="/js/**" filters="none" />
<security:intercept-url pattern="/css/**" filters="none" />
<security:intercept-url pattern="/images/**" filters="none" />
<security:intercept-url pattern="/heartbeat" filters="none" />
<security:intercept-url pattern="/reposTracking" filters="none" />
<security:intercept-url pattern="/alerts/sev" filters="none" />
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:form-login
login-page="/login"
default-target-url="/"
authentication-failure-url="/login?login_error=1"
authentication-success-handler-ref="mcLoginSuccessHandler"
authentication-failure-handler-ref="mcLoginFailureHandler"
/>
<security:remember-me/>
<security:logout success-handler-ref="mcLogoutHandler"/>
<security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter"/>
<security:session-management session-authentication-strategy-ref="sas"/>
</security:http>
<!-- needed for remember-me service -->
<bean id="customUserDetailService" class="com.mycompany.admin.tools.webui.beans.MyCompanyUserDetailsService"/>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="vuiAuthenticationProvider"/>
</security:authentication-manager>
<bean id="vuiAuthenticationProvider" class="com.mycompany.admin.tools.webui.beans.VuiMycompanyUserDetailsAuthenticationProvider">
<property name="userDetailsService" ref="customUserDetailService"/>
<property name="passwordEncoder" ref="md5PasswordEncoder"/>
</bean>
<bean id="md5PasswordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"/>
<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login"></property>
</bean>
<bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter">
<property name="sessionRegistry" ref="sessionRegistry"/>
<property name="expiredUrl" value="/login"/>
<!-- <property name="redirectStrategy" value=""></property> -->
</bean>
<bean id="sas" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions" value="-1" /> <!-- no limit on number of session per user -->
</bean>
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
<bean id="mcLogoutHandler" class="com.mycompany.admin.tools.webui.servlets.McLogoutHandler"/>
<bean id="mcLoginSuccessHandler" class="com.mycompany.admin.tools.webui.servlets.McLoginSuccessHandler"/>
<bean id="mcLoginFailureHandler" class="com.mycompany.admin.tools.webui.servlets.McLoginFailureHandler"/>
First of all, if your tests are making http requests then they are not unit tests, but functional tests.
If you want to make such tests work you will basically have to go through the steps that are performed when you log in from a browser: POST credentials to /j_spring_security_check, and make sure that the JSESSIONID cookie that was set in the response is sent back to the server with each subsequent call.
You should test one level lower. Test your business logic in unit test manner. Why do you need to test if RestEasy/CXF/Jersey/whatever is calling methods properly? Do you need to test if spring-security works fine? I guess someone has written unit-tests for that already.
For integration testing read Spring documentation. You can set-up a bit simpler context without authentication and call MockHttpRequest.
For REST testing you may also use SoapUI.