Spring Security 3.1: after logging-out catches session expired - spring

I'm developing a webapp with Java + Spring MVC + Hibernate + Spring Security 3.1. When I log out instead of just redirect to the log in page it goes to the session expired method so it shows the log in page but with a "Session expired!" message...
Here's security-context.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<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.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:debug />
<!-- preauthentication -->
<security:global-method-security pre-post-annotations="enabled">
</security:global-method-security>
<security:http auto-config="false" use-expressions="true" entry-point-ref="http403EntryPoint" access-denied-page="/errores/accesodenegado">
<security:intercept-url pattern="/" access="permitAll"/>
<security:intercept-url pattern="/error.jsp" access="permitAll"/>
<!-- Allow non-secure access to static resources -->
<security:intercept-url pattern="/resources/**" access="permitAll"/>
<security:intercept-url pattern="/autenticacion/**" access="permitAll"/>
<security:intercept-url pattern="/errores/**" access="permitAll"/>
<!-- URLs que dependen de perfiles -->
<security:intercept-url pattern="/gestion/facturas/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN','ROLE_CONSL')"/>
<security:intercept-url pattern="/gestion/tarifas/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN','ROLE_CONSL')"/>
<security:intercept-url pattern="/gestion/envios/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN')"/>
<security:intercept-url pattern="/gestion/perfiles/**" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/gestion/usuarios/**" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/consulta/**" access="hasAnyRole('ROLE_CONSL','ROLE_ADMIN','ROLE_S_CEN')"/>
<security:intercept-url pattern="/importacion/**" access="hasAnyRole('ROLE_ADMIN','ROLE_S_CEN')"/>
<!-- Pantalla a la que redirige el logout -->
<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>
<!-- El session timeout lleva a la pantalla de login -->
<security:session-management invalid-session-url="/errores/sesionexpirada" />
</security:http>
<bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint">
</bean>
<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/**" filters="j2eePreAuthFilter"/>
</security:filter-chain-map>
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref='preAuthenticatedAuthenticationProvider'/>
</security:authentication-manager>
<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService"/>
</bean>
<bean id="preAuthenticatedUserDetailsService"
class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"/>
<bean id="j2eePreAuthFilter" class="es.myApp.security.MyAppUserJ2eePreAuthenticatedProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationDetailsSource" ref="authenticationDetailsSource"/>
<property name="continueFilterChainOnUnsuccessfulAuthentication" value="false"/>
</bean>
<bean id="authenticationDetailsSource" class="org.springframework.security.web.authentication.preauth.j2ee.J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource">
<property name="mappableRolesRetriever" ref="j2eeMappableRolesRetriever"/>
<property name="userRoles2GrantedAuthoritiesMapper" ref="j2eeUserRoles2GrantedAuthoritiesMapper"/>
</bean>
<bean id="j2eeMappableRolesRetriever" class="org.springframework.security.web.authentication.preauth.j2ee.WebXmlMappableAttributesRetriever">
</bean>
<bean id="j2eeUserRoles2GrantedAuthoritiesMapper" class="org.springframework.security.core.authority.mapping.SimpleAttributes2GrantedAuthoritiesMapper">
<property name="attributePrefix" value="test"/>
</bean>
</beans>
The log out button calls:
#Controller
#RequestMapping("/autenticacion")
public class AutenticacionController {
[...]
#RequestMapping(value = "salir")
public String salir(Model model, HttpServletRequest request, HttpServletResponse response) {
// request.getSession().removeAttribute(Constantes.USUARIO_SESION);
// request.getSession().invalidate();
return "redirect:/j_spring_security_logout";
}
}
I tried commenting out those lines and using them, but the behaviour is exactly the same... Constantes.USUARIO_SESION stores the name of the user variable in session.
The log in method executes, among other things:
request.getSession().setAttribute(Constantes.USUARIO_SESION, usuario);
UserDetails userDetails = myAppUserDetailsService.loadUserByUsername(usuario.getLogin());
Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(auth);
Session expired goes through:
#RequestMapping("sesionexpirada")
public String sesionExpirada(Model model, HttpServletRequest request, HttpServletResponse response) {
MessageManager msgManager = new MessageManager();
msgManager.addError("error.sesion.expirada");
request.getSession().setAttribute("messageManager", msgManager);
return "inicio";
}
And web.xml
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Aplicación Web MyApp</display-name>
<!-- Define la localización de los ficheros de configuración de Spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext.xml
</param-value>
</context-param>
<!-- Reads request input using UTF-8 encoding -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>myAppUserJ2eePreAuthenticatedProcessingFilter</filter-name>
<filter-class>es.myApp.security.XiscoUserJ2eePreAuthenticatedProcessingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myAppUserJ2eePreAuthenticatedProcessingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Handles all requests into the application -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>es.myApp.controller.XiscoDispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- del. welcome files -->
<!-- useful for Servlet 3 container (Tomcat 7 and Jetty 6) -->
<welcome-file-list>
<welcome-file></welcome-file>
</welcome-file-list>
<!-- Página de error -->
<error-page>
<error-code>404</error-code>
<location>/errores/error</location>
</error-page>
<!-- Tiempo de sesión -->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<!-- Referencia a recursos jndi WAS -->
<resource-ref id="ResourceRef_MyApp>
<res-ref-name>jdbc/myApp</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
</web-app>
I tested it on Tomcat 6 and WAS 8.5...
EDIT: If I get rid of Spring Security's logout and implement my own it works as expected:
I erase: <security:logout logout-success-url="/" delete-cookies="JSESSIONID"/> from security-context.xml and change the method that is called on logout:
#RequestMapping("salir")
public String salir(Model model, HttpServletRequest request, HttpServletResponse response) {
request.getSession().removeAttribute(Constantes.USUARIO_SESION);
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
SecurityContextHolder.clearContext();
return "inicio";
}
Why is it working now? These lines of code are taken from Spring's logout code...

You need add
<security:session-management session-fixation-protection="none"/>
to you security:http section.

I don't understand what you are trying to accomplish. You wrote your own controller that invalidates the session then redirects to the spring security logout url. The controller is unnecessary, just use the spring logout url directly, by default it will invalidate the session for you. If you need to add special behavior on logout, either write your own LogoutSuccessHandler or extend one of the spring handlers and add it to the LogoutFilter.

Related

Spring security error while creating bean expected single matching bean but found 2

I am trying to implementing spring security with My Rest easy web services in spring application.I tried some basic authentications and it works perfectly.Next step I tried to create custom filters My security-context.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"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- SPRING SECURITY SETUP -->
<beans:bean id="userDao" class="com.cheasyy.cofinding.dao.UserDAO">
</beans:bean>
<beans:bean id="passwordEncoder"
class="org.springframework.security.crypto.password.StandardPasswordEncoder">
<beans:constructor-arg value="ThisIsASecretSoChangeMe" />
</beans:bean>
<security:authentication-manager id="authenticationManager">
<security:authentication-provider
user-service-ref="userDao">
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<security:http realm="Protected API" use-expressions="true"
auto-config="false" create-session="stateless" entry-point-ref="unauthorizedEntryPoint"
authentication-manager-ref="authenticationManager">
<security:custom-filter ref="authenticationTokenProcessingFilter"
position="FORM_LOGIN_FILTER" />
<security:intercept-url pattern="/loginService/authenticate"
access="permitAll" />
<security:intercept-url method="GET"
pattern="/profileService/**" access="hasRole('user')" />
<security:intercept-url method="PUT"
pattern="/profileService/**" access="hasRole('admin')" />
<security:intercept-url method="POST"
pattern="/profileService/**" access="hasRole('admin')" />
<security:intercept-url method="DELETE"
pattern="/profileService/**" access="hasRole('admin')" />
</security:http>
<beans:bean id="unauthorizedEntryPoint"
class="com.cheasyy.cofinding.util.UnauthorizedEntryPoint" />
<beans:bean
class="com.cheasyy.cofinding.util.AuthenticationTokenProcessingFilter"
id="authenticationTokenProcessingFilter">
<beans:constructor-arg ref="userDao" />
</beans:bean>
</beans:beans>
My web.xml is
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- Context Param -->
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/appServlet/servlet-context.xml
/WEB-INF/spring/appServlet/security-context.xml
</param-value>
</context-param>
<!-- Enables Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/profileService/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<!-- This SpringCotextLoader absolutely has to come after the reasteasy
configuration -->
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<!-- Servlets -->
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value> /WEB-INF/spring/appServlet/servlet-context.xml </param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Error pages -->
<error-page>
<error-code>400</error-code>
<location>/400</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500</location>
</error-page>
<!-- ALL NEW SERVICE PATHS MUST BE SPECIFIED HERE. WHENEVER A NEW SERVICE
IS INTRODUCED INTO THE API IT MUST BE ADDED INTO THE RESTEASY SERVLET-MAPPING -->
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/deal/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>securedapp</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
</web-app>
My LoginLogoutServiceImpl is
#Service
#Path("/loginService")
public class LoginLogoutServiceImpl extends BaseService {
#Autowired
private UserDetailsService userService;
#Autowired
#org.springframework.beans.factory.annotation.Qualifier("authenticationManager")
private AuthenticationManager authManager;
/**
* Authenticates a user and creates an authentication token.
*
* #param username
* The name of the user.
* #param password
* The password of the user.
* #return A transfer containing the authentication token.
*/
#Path("authenticate")
#POST
#Produces(MediaType.APPLICATION_JSON)
public TokenTransfer authenticate(#FormParam("username") String username,
#FormParam("password") String password) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
username, password);
Authentication authentication = this.authManager
.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
/*
* Reload user as password of authentication principal will be null
* after authorization and password is needed for token generation
*/
UserDetails userDetails = this.userService.loadUserByUsername(username);
return new TokenTransfer(TokenUtils.createToken(userDetails));
}
}
When I run application it gives error like
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.security.core.userdetails.UserDetailsService] is defined: expected single matching bean but found 2: [loginLogoutBusinessServiceImpl, userDao]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:800)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
... 25 more
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type
[org.springframework.security.core.userdetails.UserDetailsService] is
defined: expected single matching bean but found 2:
[loginLogoutBusinessServiceImpl, userDao]
Looking at the error it seems there are two beans loginLogoutBusinessServiceImpl and userDao both referring implementing of the interface UserDetailsService.
Either two different classes (both spring managed) are implementing UserDetailsService or single class implementing it but configured twice as two different beans with Spring.
So spring is not able to decide which needs to be injected.
Use #Qualifer annotation in LoginLogoutServiceImpl to tell spring which one needs to be injected.
Ex:
#Autowired()
#Qualifier("loginLogoutBusinessServiceImpl") or #Qualifier("userDao")
private UserDetailsService userService;

Spring security anotation not working

I've tried and tried, but seems like i'm unable to make the spring security annotation work. I've refer to alot of sites.. and i cant seems to see what's wrong with my code. any help will be much appreciated
Here is spring security xml
<security:global-method-security pre-post-annotations="enabled"/>
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/login" access="permitAll" />
<security:intercept-url pattern="/logout" access="permitAll" />
<security:intercept-url pattern="/accessdenied" access="permitAll" />
<security:intercept-url pattern="/**/*.css" access="permitAll" />
<security:intercept-url pattern="/**/*.js" access="permitAll" />
<security:intercept-url pattern="/**" access="hasRole('LANDING')" />
<security:form-login login-page="/login" default-target-url="/landing" authentication-failure-url="/login" authentication-success-handler-ref="loginSuccesHandler" />
<security:logout logout-success-url="/logout" />
</security:http>
here is my web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>XSSFilter</filter-name>
<filter-class>simptex.my.core.security.filter.XSSFilter</filter-class>
</filter>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>XSSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/dispatcher-servlet.xml
/WEB-INF/application-security.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
here is a sample of java code
#PreAuthorize("hasAuthority('ROLE_TELLER')")
#RequestMapping(value = "/urlxxxx" , method = RequestMethod.GET)
public String controlerMethod(HttpServletRequest req, HttpSession session) {
return "urlxxxx";
}
Firstly I think you're using the wrong expression. According to the Spring documentation here, I don't see a hasAuthority() expression. There is however a hasRole() expression. So in your case I believe you need to change the annotation to #PreAuthorize("hasRole('ROLE_TELLER')").
Secondly, the Spring Documentation states:
To use hasPermission() expressions, you have to explicitly configure a PermissionEvaluator in your application context
So in your security XML configuration use the following bean declaration:
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" />
And then update your security:global-method-security definition to look something like:
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
That should be enough to get the default Spring Security annotations running out of the box.

Spring security login-processing-url throws 405 request method POST not supported

i'm working with spring security 3.1.3 in a spring 3.2.0 project. I've configured two entry points for my security using spring security. The idea is to have a url like /enterprise_login where enterprise users should log in and other url like /login where normal users do their log in action. In my security configuration i've the next code
<security:global-method-security jsr250-annotations="enabled" pre-post-annotations="enabled" secured-annotations="enabled" />
<security:http pattern="/enterprise/**" auto-config="false" use-expressions="true" authentication-manager-ref="autenticationManagerUserEnterprise">
<security:intercept-url pattern="/enterprise/**" access="hasRole('ROLE_ENTERPRISE')" />
<security:intercept-url pattern="/enterprise_login" access="isAnonymous()" />
<security:form-login login-page="/enterprise_login" default-target-url="/" authentication-failure-url="/empresas_login_error" login-processing-url="/enterprise_login_process" />
<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>
<security:remember-me user-service-ref="enterpriseAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:http pattern="/**" auto-config="false" use-expressions="true" authentication-manager-ref="autenticationManagerUser">
<security:intercept-url pattern="/**" access="permitAll" />
<security:form-login login-page="/login" default-target-url="/" authentication-failure-url="/login_error" />
<security:logout logout-success-url="/" delete-cookies="JSESSIONID"/>
<security:remember-me user-service-ref="UserAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
<security:authentication-manager id="autenticationManagerUserEnterprise">
<security:authentication-provider user-service-ref="enterpriseAuthenticationProvider">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<security:authentication-manager id="autenticationManagerUser">
<security:authentication-provider user-service-ref="UserAuthenticationProvider">
<security:password-encoder hash="plaintext"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="enterpriseAuthenticationProvider" class="com.test.security.enterpriseAuthenticationProvider"></bean>
<bean id="UserAuthenticationProvider" class="com.test.security.UserDetailsServiceImp"></bean>
Then when I go to /enterprise_login form and submit the login data I get a "HTTP 405 - Request method 'POST' not supported" throwed by tomcat in the url /enterprise_login_process (the url configured to act as login-processing-url. I can't figure out where the problem is, any help is really appreciated.
PD: My web.xml looks like:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>AT-2</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-config.xml
</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>tutorial.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
The issue is that the first configuration currently only matches on URLs that start with "/enterprise/" and the URL to process authentication is configured as "/enterprise_login_process". This means that submitting a POST to "/enterprise_login_process" will submit to the second configuration which is not trying to authenticate "/enterprise_login_process".
To fix this you need to ensure the http#pattern and the login-processing-url are aligned. For example:
<security:http pattern="/enterprise/**"
auto-config="false"
use-expressions="true"
authentication-manager-ref="autenticationManagerUserEnterprise">
<security:intercept-url pattern="/enterprise/login"
access="isAnonymous()" />
<security:intercept-url pattern="/**"
access="hasRole('ROLE_ENTERPRISE')" />
<security:form-login login-page="/enterprise/login"
default-target-url="/"
authentication-failure-url="/enterprise/login?error"
login-processing-url="/enterprise/login_process" />
<security:logout logout-success-url="/"
delete-cookies="JSESSIONID"/>
<security:remember-me
user-service-ref="enterpriseAuthenticationProvider"/>
<security:session-management invalid-session-url="/">
<security:concurrency-control max-sessions="2"
error-if-maximum-exceeded="true" />
</security:session-management>
</security:http>
You will observe that I modified the code to ensure all URLs within the block start with "/enterprise/". This also means that you will need to ensure that your login form for enterprise is updated to POST to "/enterprise/login_process".

Securing GWT servlets with Spring Security

I'm writing a GWT application secured with Spring security. Logging in works fine, but authorization doesn't.
I've tried using #Secured and #PreAuthorize annotations on my methods and that didn't work either.
For instance, this is a code snippet from AppUserServiceImpl
#Secured("ROLE_ADMINISTRATOR")
#Override
public List<AppUser> fetch(Integer startRow, Integer endRow, Map criteria) {
return appUserManagerBean.getUsers(criteria);
}
ApplicationContext.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.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<http auto-config="true">
<intercept-url pattern="/testapplication/**" access="ROLE_USER"/>
<intercept-url pattern="/gwt/**" access="ROLE_USER"/>
<intercept-url pattern="/**/*.html" access="ROLE_USER"/>
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/security/*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/testapplication/appUserService*" access="ROLE_ADMIN"/>
<form-login
login-page="/login.jsp"
authentication-failure-url="/security/error.html"
login-processing-url="/j_spring_security_check"
/>
</http>
<beans:bean id="appUserService" class="com.test.testapplication.server.admin.appuser.AppUserServiceImpl"/>
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
[DATASOURCE CONFIGURATION]
</beans:bean>
<global-method-security pre-post-annotations="enabled" secured-annotations="enabled" />
<authentication-manager>
<authentication-provider>
<password-encoder hash="sha" />
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username,password,DECODE(enabled,'Y',1,'N',0) as enabled from APP_USER where username=?"
authorities-by-username-query="select u.username, ur.role from APP_USER u, APP_USER_ROLE ur
where u.id = ur.APP_USER_ID and u.username =? "
/>
</authentication-provider>
</authentication-manager>
To test, I'm trying to secure 'appUserService'.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
</param-value>
</context-param>
<servlet>
<servlet-name>appUserService</servlet-name>
<servlet-class>com.test.testapplication.server.admin.appuser.AppUserServiceImpl</servlet-class>
</servlet>
<!-- Spring security filter -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>testapplication.html</welcome-file>
</welcome-file-list>
I'm looking for the simplest solution and I would prefer not to use AspectJ, help would be greatly appreciated
Where are you mapping your servlet to particular path?
I'm using gwt-sl for integration of RemoteServiceServlets and Spring.
Define Dispatcher servlet in your web.xml:
<servlet>
<servlet-name>gwtservice</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
And declaration and mapping for your gwt-servlet:
<bean name="DeviceListenerServlet" class="your.package.your.SomeService"/>
<bean id="urlMappingGWT" class="org.gwtwidgets.server.spring.GWTHandler">
<property name="mappings">
<map>
<entry key="/service" value-ref="DriverServiceImpl"/>
</map>
</property>
</bean>
And change Annotation in your RemoteService class (in my example it will be #RemoteServiceRelativePath("gwtservice/service")).
Now you can use you #Secured annotation (if you added )
Hope this help.

Facing Problems when using Spring Security in GAE

I am following this article to implement spring security in my GAE project http://blog.springsource.com/2010/08/02/spring-security-in-google-app-engine/
I could not make it work, URLs that i have configured to be protected are not getting protected and application is not redirecting me to google log in page. Here is my web.xml and security-config.xml. Please help, as i have already spent lot of time on this. I think there is some small issue which i am unable to catch.
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/security-config.xml
</param-value>
</context-param>
<!-- Enables Spring Security -->
<filter>
<filter-name>authenticationFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!-- Reads request input using UTF-8 encoding -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>authenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
security-config.xml
<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-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<security:http pattern="/static/**" security="none" />
<security:http pattern="/favicon.ico" security="none" />
<security:http use-expressions="true" entry-point-ref="entryPoint"
access-denied-page="/">
<security:intercept-url pattern="/" access="isAuthenticated()" />
<security:intercept-url pattern="/sample"
access="isAuthenticated()" />
<security:custom-filter position="PRE_AUTH_FILTER"
ref="authenticationFilter" />
</security:http>
<bean id="entryPoint"
class="com.generic.gae.security.GoogleAccountsAuthenticationEntryPoint" />
<bean id="authenticationFilter" class="com.generic.gae.security.GaeAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="authenticationProvider" />
</security:authentication-manager>
<bean id="authenticationProvider"
class="com.generic.gae.security.GoogleAccountsAuthenticationProvider" />
Thanks
authenticationFilter defined in security-config.xml is not the one you use in web.xml. Spring Security by default makes the filter bean available to you with name springSecurityFilterChain. So your filter declaration in web.xml should be:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
...
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
See section 2.2 of page Security Namespace Configuration

Resources