I am working on a Spring MVC web application. Last week I started adding Sping Secuirty to my project. The problem I am facing concerns session management.
Here is http part of my spring-security.xml
<http auto-config="true">
<intercept-url pattern="/css" filters="none"/>
<intercept-url pattern="/js" filters="none"/>
<intercept-url pattern="/logout" filters="none"/>
<intercept-url pattern="/loginfailed" filters="none"/>
<intercept-url pattern="/login" filters="none"/>
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login login-page="/login" default-target-url="/hello"
authentication-failure-url="/loginfailed" />
<session-management invalid-session-url="/login.jsp?error=sessionExpired" session-authentication-error-url="/login.jsp?error=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/login.jsp?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>
</http>
Login/logout works fine, but when I try to invalidate user session by trying to login from different browser invalid-session-url="/login.jsp?error=sessionExpired" fails. Browser get redirected, because I see that GET request to login.jsp?error=sessionExpired is being sent. However, web page shows error saying that resource is not available. I suspect that it has something to do with
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
in my dispatcher-servlet.xml. However, I don't know exactly how to fix this issue. login.jsp is located in WEB-INF/pages/
It seems to me Spring MVC DispatcherServlet couldn't find a mapping for /login.jsp because it's not set as a view that accessible without controller. I'm also assuming you had /login mapped to login.jsp (you did not provide enough info to confirm this), but if this is the case, just use expired-url="/login?error=sessionExpiredDuplicateLogin
You are redirecting to the jsp not the mapped url.
session management tag should be :
<session-management invalid-session-url="/login?error=sessionExpired" session-authentication-error-url="/login?error=alreadyLogin">
<concurrency-control max-sessions="1" expired-url="/login?error=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
</session-management>
Related
I have an application which needs 2 security http tags to be deployed in weblogic 10.3.6 server, Spring Framework 3.1.2 & spring-security-3.1.2 version:
1, Form-based-Login: for direct logging in by users using login page.
2. Basic Authentication: Rest WebService calls.
I have added FORM_BASED_LOGIN successfully.-THIS works fine
Appreciate any direction for BASIC Auth for REST WebServices.
For Basic Authentication : Weblogic pops-up an additional pop-up where I have to enter the credentials of weblogic console.
To fix this I have found 2 approaches:
1. Updating the server config.xml file with the below tag:
<enforce-valid-basic-auth-credentials>false</enforce-valid-basic-auth-credentials>
Reference: Spring Security HTTP Basic Authentication
Adding an adapter and applicationContext-acegi-security.xml
and WeblogicAuthenticationFilter
I like to do the 2nd approach as it does not involve any changes to server configuration.
It would be great if any one could point me in the right direction or an example to achieve this.
Reference: http://docs.tpu.ru/docs/oracle/en/fmw/11.1.1.6.0/web.1111/e14453/security.htm
Update : Adding my current spring-security configuration:
<http create-session="stateless" entry-point-ref="basicAuthEntryPoint" pattern="/api/**" use-expressions="true">
<intercept-url pattern="/api/listbyorderid" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
<intercept-url pattern="/api/listbycustomerid" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')" />
<custom-filter ref="basicAuthenticationFilter" after="BASIC_AUTH_FILTER" />
</http>
<http auto-config="false" use-expressions="true" access-denied-page="/security/denied" entry-point-ref="authenticationEntryPoint">
<intercept-url pattern="/security/login" access="permitAll" />
<intercept-url pattern="/layouts/*" access="permitAll"/>
<intercept-url pattern="/tiles/*" access="permitAll"/>
<intercept-url pattern="/jquery/*" access="permitAll"/>
<intercept-url pattern="/css/*" access="permitAll"/>
<intercept-url pattern="/admin/css/*" access="permitAll"/>
<intercept-url pattern="/admin/images/*" access="permitAll"/>
<intercept-url pattern="/admin/ico/*" access="permitAll"/>
<intercept-url pattern="/admin/jquery/*" access="permitAll"/>
<logout invalidate-session="true" logout-url="/j_spring_security_logout" success-handler-ref="logoutSuccessHandler" delete-cookies="JSESSIONID"/>
<!-- Custom filter to deny unwanted users even though registered -->
<custom-filter ref="blacklistFilter" before="FILTER_SECURITY_INTERCEPTOR" />
<!-- Custom filter for username, password and domain. The real customization is done in the customAuthenticationManager -->
<custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER" />
</http>
Thanks in Advance.
Spring Security supports this out of the box. You can take a look at helloworld-jc for a Java Based Configuration or helloworld-xml for an xml based configuration. Given you are on servlet 2.5 with weblogic 10.3.6 you will want to use the XML sample.
I use Spring Security for my web application
By default, the authentication mechanism redirect the user on the "home", but it's possible to access directly to one screen of the application by its URL.
Everything is working well if you fill the URL in your web-browser.
BUT, if I have an hyperlink in Excel sheet, with the same URL, I get the login page, and then I'm forward to the "home" whereas I wanted to access my specific screen.
If I open the Excel sheet with OpenOffice, everything is working well ; as if I were filling the URL in the web browser.
Here is my configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-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">
<security:http auto-config="true" access-denied-page="/accessDenied.jsp" use-expressions="true" access-decision-manager-ref="accessDecisionManager" entry-point-ref="entryPoint">
<security:intercept-url pattern="/css/*.css" access="permitAll" />
<security:intercept-url pattern="/images/**" access="permitAll" />
<security:intercept-url pattern="/javascript/*.js" access="permitAll" />
<security:intercept-url pattern="/j_spring_security_check" access="permitAll"/>
<security:intercept-url pattern="/register.*" access="permitAll" />
<security:intercept-url pattern="/registerUser.*" access="permitAll" />
<security:intercept-url pattern="/login.*" access="permitAll" />
<security:intercept-url pattern="/restore/*" access="permitAll" />
<security:intercept-url pattern="/customer/**" access="permitAll" />
<security:intercept-url pattern="/logout.*" access="isAuthenticated()" />
<security:intercept-url pattern="/j_spring_security_logout" access="isAuthenticated()"/>
<security:intercept-url pattern="/index.*" access="isAuthenticated()" />
<security:intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
<security:intercept-url pattern="/template/*" access="isAuthenticated()" />
<security:intercept-url pattern="/editor/*" access="hasRole('EDITOR')" />
<security:intercept-url pattern="/creator/*" access="hasRole('CREATOR')" />
<security:intercept-url pattern="/task/*" access="hasAnyRole('CREATOR','EDITOR')"/>
<security:intercept-url pattern="/ajax/*" access="hasAnyRole('CREATOR','EDITOR')"/>
<security:intercept-url pattern="/**" access="isAuthenticated()" />
<security:form-login default-target-url="/index.jsp" authentication-failure-url="/login.jsp?login_error=true"/>
<security:logout invalidate-session="true" logout-url="/logout.jsp" logout-success-url="/login.jsp"/>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="userEnvironmenttStatisticService" />
</security:authentication-manager>
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>
<bean id="userEnvironmenttStatisticService" class="com.epam.crs.security.UserEnvironmenttStatisticService">
<property name="userDetailsService" ref="userDetailsService" />
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<constructor-arg>
<list>
<ref bean="notDeletedVoter" />
</list>
</constructor-arg>
</bean>
<bean id="notDeletedVoter" class="com.epam.crs.security.NotDeletedVoter" />
<bean id="entryPoint" class="com.epam.crs.security.ParameterizedLoginUrlAuthenticationEntryPoint">
<constructor-arg value="/login.jsp"/>
</bean>
<bean id="customPermissionEvaluator" class="com.epam.crs.security.CustomPermissionEvaluator" />
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="customPermissionEvaluator" />
</bean>
</beans>
Anybody can help me?
Maybe you have any idea how to fix it?
I got the same issue on a similar system. Here is how I fixed it and a bit more details behind my investigation.
How I fixed it for my similar app
I updated the entrypoint so it uses forwarding. Your updated code would be:
<bean id="entryPoint" class="com.epam.crs.security.ParameterizedLoginUrlAuthenticationEntryPoint">
<constructor-arg value="/login.jsp"/>
<property name="useForward" value="true" />
</bean>
Note: this requires that your entrypoint derives from LoginUrlAuthenticationEntryPoint
More details..
Typical flow of execution:
This is the typical flow of execution of a Spring Security setup like yours:
Anonymous user hits a secured page.
An AccessDeniedException is thrown and is captured by the ExceptionTranslationFilter. That filter adds the request coming from the anonymous user in the session.
The security entrypoint (that's your ParameterizedLoginUrlAuthenticationEntryPoint bean) then redirects the user to the login page. This redirection is done as a HTTP 302 redirect.
The user enters valid credentials.
The default SavedRequestAwareAuthenticationSuccessHandler is called. This handler loads the saved request (stored in the session in step 2) & redirects the user to that page (again with a HTTP 302 redirect.)
How Excel messes with that
Excel, for reasons that are out of scope, uses a simple http client before passing the url to your default browser.
That http client will pass the first url that returns a HTTP 200 code.
The http client will trigger the 3 first steps in the flow, landing on the login page.
Since the login page emits a HTTP 200, that is the url that Excel's http client will send to your browser.
The browser opens the login page, but it receives a new session id: it does not share the session cookie of Excel's http client.
When the user enters valid credentials, the SuccessHandler is called, just like in step 5, except that there is no saved request in the user's session (that saved request was saved in Excel's http client's session, not in the user's one). The handler defaults to sending the user to the default page: your home page.
Why does forwarding fixes this?
Forwarding simply handles the redirection on the server-side, excluding the browser/client from the process. So in the typical flow example, all of the redirections are done as forwards on the server-side.
Concretely, this means that the URL will not change. This allows Excel's http client to pass the right url to the browser, allowing your user to complete the 5 steps process without any hickups.
I had the same problem and for me this helped me:
http://support.microsoft.com/kb/218153
Install the Microsoft Fix it 50655:
http://go.microsoft.com/?linkid=9769998
Everything is working well if you fill the URL in your webbrowser.
BUT, if I have an hyperlink in Excel sheet, with the same URL, I get
the login page, and then I'm forward to the "home" whereas I wanted to
access my specific screen.
This is simply not determined by spring. Your URL's must be different, or you session expired.
I'm using Spring to handle security in my JSF application. I have a login page at /login and I've configured Spring like this:
<http authentication-manager-ref="authenticationManager">
<intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/admin" access="ROLE_ADMIN" />
<intercept-url pattern="/javax.faces.resource/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_USER" />
<form-login login-page="/login" authentication-failure-url="/login" />
<logout logout-url="/logout" />
</http>
I want the admin page at /admin to be available only for users with the ROLE_ADMIN role. Users with ROLE_ADMIN or ROLE_USER may access pages starting from the application root.
When I login with a user having either role I see the page you should see after login. However, whatever my next action may be I get redirected to /login like I'm not logged in. Can someone please explain this as I'm trying to get this thing to work for a day now. I've been reading the Spring 3.1.x documentation but it doesn't give me a clue about how to solve the problem. I'm running Spring 3.1.1.Release by the way.
Extra bonus info: the page you should see after login has an element that should only render if the user had ROLE_ADIN. I can see that element after login. The problems began when I implemented PrettyFaces. I've searched the web for common problems and only came up with that the PrettyFaces filter should appear after the Spring security filter. This is the case so it should work right?
UPDATE: I've updated my config to use expressions. However the problem still exists.
<http authentication-manager-ref="authenticationManager" use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/javax.faces.resource/**" access="permitAll" />
<intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" />
<form-login login-page="/login" authentication-failure-url="/login" />
<logout logout-url="/logout" />
</http>
Output in Firebug's console just after login (the page tries an AJAX call):
First, always debug Spring Security when having problems (add log4j.logger.org.springframework.security=DEBUG).
Second, I think that you wanted hasAnyRole:
<intercept-url pattern="/**" access="hasAnyRole(ROLE_ADMIN,ROLE_USER)" />
plus add use-expressions="true" to http:
<http authentication-manager-ref="authenticationManager" use-expressions="true">
to allow ROLE_ADMIN xor ROLE_USER users to access page. In your current config user must have both roles to access /**.
My question is similar to this one, but I can simplify it some. Basically I want to authenticate users through the remember me cookie, but I want everything on the server side to be completely stateless, i.e. never create a HttpSession. I have the following setup:
<security:http use-expressions="true" create-session="stateless" >
<security:intercept-url pattern="/index.jsp" access="hasRole('ROLE_ANONYMOUS')" />
<security:intercept-url pattern="/**" access="hasRole('ROLE_TEST')" />
<security:form-login login-page="/index.jsp" default-target-url="/home" always-use-default-target="true" authentication-failure-url="/index.jsp?login_error=1" />
<security:logout logout-success-url="/index.jsp"/>
<security:remember-me key="MY_KEY" />
</security:http>
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="testUser" password="testPassword" authorities="ROLE_TEST" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
I authenticate just fine with the username and password above and see the remember me cookie in my browser. That part of it is working great. However, I'm finding it is creating a session during this process. I thought the create-session="stateless" was supposed to prevent this. Am I missing something here?
After working with this more, I found out that it wasn't Spring Security that was creating the session. The index.jsp was creating a new session every time I hit it. I simply added <%# page session="false"> to the top of index.jsp, and now there are no sessions being created.
Imagine the user A have multiple logins (are logged in) in diferent machines. When he logs out in one machine, the other sessions should automatically redirect to login page.
how i can implement this in spring security?
For now, i have tis http configuration on security.xml
<http auto-config="true" use-expressions="true">
<anonymous />
<intercept-url pattern="/login.do" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login login-page="/login.do" />
<logout logout-url="/j_spring_security_logout"
success-handler-ref="myLogoutSuccessHandler" />
<remember-me data-source-ref="dataSource" />
</http>
I would recomment you to have a look at SessionRegistry .You can check this here . There has been a discussion on this at Is it possible to invalidate a spring security session? . Check this out too
Spring sessions are stored as JsessionID cookies. Check here for a discussion on cookie removal.