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.
Related
My requirement is to secure only the login page to protect user credentials. After successful login, the user can access to the restricted pages but in http mode.
It is a requirement because of SSL overload. Users need to access to protected pages which contains a lot of data.
I would like to know whether it is possible to do although it isn't as secure as maintain https context.
This is my config:
<security:http auto-config="true">
<security:intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
<security:intercept-url pattern="/welcome*" access="ROLE_USER, ROLE_ADMIN" />
<security:form-login login-page="/login" authentication-failure-handler-ref="customAuthenticationFailureHandler" default-target-url="/welcome" />
<security:access-denied-handler ref="openIdAuthFailureHandler"/>
</security:http>
If I try to set /login as https, everything is in https mode. How can I manage to do that?
Edit:
As s.kwiotek suggested I added requires-channel="http" to the other url patterns:
<security:http auto-config="true">
<security:intercept-url pattern="/login*" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>
<security:intercept-url pattern="/welcome*" access="ROLE_USER, ROLE_ADMIN" requires-channel="http"/>
<security:intercept-url pattern="/user/*" access="ROLE_USER, ROLE_ADMIN" requires-channel="http" />
<security:intercept-url pattern="/rest/*" access="ROLE_USER, ROLE_ADMIN" requires-channel="http" />
<security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" requires-channel="http" />
<security:session-management session-fixation-protection="none"/>
<security:port-mappings>
<security:port-mapping http="8080" https="8443"/>
</security:port-mappings>
<security:form-login login-page="/login" authentication-failure-handler-ref="customAuthenticationFailureHandler" always-use-default-target="true" default-target-url="/user/home" />
<security:logout logout-success-url="/" />
<security:access-denied-handler ref="openIdAuthFailureHandler"/>
</security:http>
I added the session-fixation-protection="none" because If I only include requires-channel="http" it doesn't go further from the login. I try to log in but I come back to the login.
If I add the session-fixation-protection it goes to the user's home but at the second login attempt. When you access to /myapp/login two jsessionid are created:
JSESSIONID=5B37413F33DF0AA45F31D711754C3704; path=/myapp; domain=localhost
JSESSIONID=658F9F8669AF6B296A77D448C1A64B71; path=/myapp/; domain=localhost; HttpOnly
Then I try to log in and I come back to the log in but the url is different:
https://myapp/login;jsessionid=C1EC352C42D6AC379DB1B65A9295E8A1
When the jsessionid is in the URL, I try to log in and I'm successfully redirected to the users'home (/user/home). If I remove the session-fixation-protection, the jessesionid is in the URL but I'm not successfully redirected to the user's home.
I don't know who creates the two first jsessionid and how to explain this behaviour. The only thing I want to do is to secure the login by ssl and then access by http.
(This should have been a comment. But my account is limited in reputation.)
You may want to reconsider allowing access to the restricted pages in http mode.
According to http://www.troyhunt.com/2011/11/owasp-top-10-for-net-developers-part-9.html,
Many people think of TLS as purely a means of encrypting sensitive user data in transit. For example, you’ll often see login forms posting credentials over HTTPS then sending the authenticated user back to HTTP for the remainder of their session. The thinking is that once the password has been successfully protected, TLS no longer has a role to play. The example above shows that entire authenticated sessions need to be protected, not just the credentials in transit. This is a lesson taught by Firesheep last year and is arguably the catalyst for Facebook implementing the option of using TLS across authenticated sessions.
Try for Example:
<security:intercept-url pattern="/**" access="ROLE_USER" requires-channel="http"/>
I am a newbie to spring security. I want to understand what do following lines do to my web application
<security:http>
<security:intercept-url pattern="/**" access="ROLE_USER" />
<security:form-login />
<security:logout />
</security:http>
As far as I understand
intercept-url means when request to any resource having location matching the pattern specified in pattern property is received, show the form-login.
form-login means give me default form login
logout means give me default form logout
Please correct above points if they are wrong/inadequate. Also, can someone explain what does access="ROLE_USER" do?
Yes. For every intercept-url Spring Security will check if there is a logged user and if he/she has the needed role to access the url. In your case you match all requests. Notice that if you have multiple intercept-url they are evaluated in the order they are written in the config(if you put a wider intercept-url before some narrower one the later will not be evaluated).
2,3. You got it right.
To understand the access attribute, you have to know about authentication manager and provider. For example you can have:
<authentication-manager>
<authentication-provider>
<user-service>
<user name="myuser" password="mypass" authorities="ROLE_USER" />
<user name="myadmin" password="mypass" authorities="ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
(there other authentication-providers, for JDBC, LDAP...)
If you add another intercept-url:
<security:intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
it will be accessible by myadmin, but not by myuser.
only user with ROLE_USER in their granted authorites can access the resource.
How to adding Spring Security logout to system to logout users? I am trying the following but it does not work:
<http use-expressions="true">
<intercept-url access="hasRole('ROLE_VERIFIED_MEMBER')" pattern="/ask-question**" />
<intercept-url pattern='/*' access='permitAll' />
<form-login default-target-url="/ask" />
<logout logout-success-url="/" />
<logout logout-url="/logout" logout-success-url="/login?logout_successful=1" />
<session-management session-fixation-protection="newSession">
<concurrency-control max-sessions="1"/>
</session-management>
</http>
I suggest to remove one of the <logout/> tags. Then, when you want to logout just navigate to /j_spring_security_logout. And if it's not working again, you should tell us what exactly is not working.
With two <logout> elements, I expect Spring is simply ignoring the second, which is the one wherein the logout-url property is specified. Remove or comment out the first one, and try again, or add the logout-url property to the first one (and remove or comment out the second), and see what happens.
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.
I have a common login and logout screen. When i logout after signing in... I come to signin page. Default behavior of spring security invalidates the session on logout so if i try to sign-in using the same screen, i get redirected to home page as there is no session available at that point. The desired behavior should be able to sign-in immediately after sign-out, which is not happening due to session invalidation
<http use-expressions="true" access-denied-page="/access-denied">
<intercept-url pattern="/secured/user/sign-up" access="hasAnyRole('ROLE_USER','ROLE_ANONYMOUS')" />
<intercept-url pattern="/secured/user/sign-in" access="hasRole('ROLE_ANONYMOUS')" />
<intercept-url pattern="/secured/**" requires-channel="https" />
<intercept-url pattern="/user/dashboard/**" access="hasAnyRole('ROLE_IC')" />
<intercept-url pattern="/**" access="permitAll"
requires-channel="http" />
<form-login login-page="/secured/user/sign-in"
authentication-success-handler-ref="authenticationSuccessHandler"
authentication-failure-url="/secured/user/sign-in" />
<logout logout-success-url="/secured/user/sign-in?loggedout=true"
logout-url="/secured/logout"/>
<security:session-management
session-fixation-protection="none">
</security:session-management>
</http>
If you refer to the xml, you will see /secured/user/sign-in is used for both sign-in and sign-out
How can I handle this issue ?
I think that as a "for now" solution.
You can:
Declare your own HttpSessionEventPublisher in your web.xml:
<listener>
<listener-class>org.yourcompany.MyHttpSessionEventPublisher</listener-class>
</listener>
In the HttpSessionEventPublisher grab the HttpSessionDestroyedEvent and don't allow spring to invalidate the seesion.
I'm not sure if this s a 'correct' solution, but it should work.
I managed to get a work around for this issue by using invalidate-session="false"