Spring security changing sessionid - java

I'm using spring security 3.1.4 and I have the following problem:
I implemented my custom SavedRequestAwareAuthenticationSuccessHandler and I implemented a cache SessionRegistry.
The problem is that the session id that I get in the SessionRegistry.registerNewSession is different then the on i get in SavedRequestAwareAuthenticationSuccessHandler .onAuthenticationSuccess
The session registery is called first.
what is the correct one? How can I get the same in both?
Is there a way that the custom SessionRegistry.registerNewSession will take the spring security session id?

Just a mere guess. But it sounds like the following issue.
In Spring security by default there is a feature enabled called session fixation protection.
It migrates the session to a new ID for a security reason.
Imagine somebody supplies you an url with an existing session ID via email, you click the link and login.
Now the person who can supplied you the url, can simply hack your account by using the supplied session id.
If you want to disable it, you can do so by putting the following line in your spring security configuration. However be aware of the risk.
<http .. >
...
<session-management session-fixation-protection="none">
...
</http>

The way I solved it was with the below steps:
Added a new bean for SessionFixationProtectionStrategy
<bean id="sessionFixationProtectionStrategy" class="org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy" />
Added the new bean in # 1 as a property to the AuthenticationFilter bean
<bean id="authenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
...
<property name="sessionAuthenticationStrategy" ref="sessionFixationProtectionStrategy" />
...
</bean>
Added a session management configuration with session-fixation-protection property in the <security:http> tag
<security:http>
<security:headers />
<security:csrf disabled="true"/>
...
<security:session-management session-fixation-protection="changeSessionId" />
</security:http>
Per Spring Security doco, SessionFixationProtectionStrategy is used as SessionAuthenticationStrategy for Java EE Servlet API implementations pre 3.1 - https://docs.spring.io/spring-security/site/docs/4.2.13.BUILD-SNAPSHOT/apidocs/org/springframework/security/web/authentication/session/SessionFixationProtectionStrategy.html, whilst from Servlet API 3.1, ChangeSessionIdAuthenticationStrategy should be used.

Related

Disable multiple session support in Spring Session

I would like to use Spring Session in an xml-config-based project, but without support for multiple sessions (user-logins) in the same browser window.
Can that be disabled? If yes, how?
As per CookieHttpSessionStrategy#setSessionAliasParamName javadoc:
Sets the name of the HTTP parameter that is used to specify the
session alias. If the value is null, then only a single session is
supported per browser.
So with Spring XML config this translates to:
<bean class="org.springframework.session.web.http.CookieHttpSessionStrategy">
<property name="sessionAliasParamName">
<null/>
</property>
</bean>

How to perform user-locking in Spring-MVC?

I wanted to know how I can perform user locking (or the best way to perform the same) i.e. if a user is already logged in from a device and tries to login from another device, he/she should be notified that a session is already available for that user and an option to close other session and start a new one.
Framework Used Spring-MVC + hibernate 4.1.
And one more thing: how can I set a list of some user hashmap object in application context?
That can be done with Spring Security and Conncurrent Session Control. You can define how many sessions may exist concurrently and decide what to do if the maximum exceeds.
Their is a simple xml configuration in spring security for the same. First you have to register the SessionRegistry bean. I have used default class of SessionRegistryImpl of spring security for Session registry like :
<bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
After that we have to register the ConcurrentSessionControlStrategy with container and tell it the maximum session allowed per user.
Example:
<bean id="sessionStrategy"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions"
value="${security.config.sessionStrategy.maximumSessions.value}" />
<property name="exceptionIfMaximumExceeded" value="true" />
</bean>
security.config.sessionStrategy.maximumSessions.value is the integer value specified in property file. By varying the maximumSessions property value we can define maximum concurrent users easily.

Custom Permission Evaluator

I'm trying to override the default permission evaluator in Spring Security 3.0, but no matter what I do, the permission elevator is ignored and the default, DenyAllPermissionEvaluator is invoked instead.
I'm using programmatic configuration, and I've tried setting the permission evaluator by overriding the configure(WebSecurity) and configure(Http) methods of the WebSecurityConfigurerAdapter class, but this doesn't help much.
What is the proper way of setting a custom permission evaluator that will actually be used by Spring Security?
Using xml conf
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
<security:expression-handler ref="methodSecurityExpressionHandler"/>
</security:global-method-security>
<bean id="methodSecurityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<property name="permissionEvaluator" ref="defaultPermissionEvaluator"/>
</bean>
and then simply define your bean like normal :
<bean id="defaultPermissionEvaluator" class="com.your.class.implements.permissionevaluator"/>
haven't done with java conf (am I the only person still using xml conf?), but shouldn't be to hard to convert from the above. And make sure you are defining in the correct place, which in most situations is the root context, hwoever we did it in the web context, so as to secure the controllers

using form-login in a Multi-tenant webapp using Spring MVC and Spring Security

I created a small and simple webapp using Spring Security and SpringMVC and I'm trying to convert it to be a multi-tenant application.
The concept I want is to re-use actual JSPs I have and alter their contents based on configuration which I determine based on the path of the URL.
Example:
Customer #1 (abc) - URL: http://mydomain.com/abc/login.html
Customer #2 (xyz) - URL: http://mydomain.com/xyz/login.html
So the name of the "tenant" is a prefix to the page's path.
I modified my controller to be like this:
#Controller
#RequestMapping("/{customer:[a-zA-Z0-9]+}/login.htm")
public class LoginController
{
private static final Logger logger = Logger.getLogger(LoginController.class);
#RequestMapping
#ReadOnlyRequest
public String login(#PathVariable("customer") String customer, HttpServletRequest request)
{
// Do some 'customer' related actions here
return "login"; // Map to the 'login.jsp' view
}
}
My view resolver configuration is:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Until now, I had the following form-login configuration:
<form-login
login-page="/login.htm"
authentication-failure-url="/login.htm?error=true"
login-processing-url="/login_process"
default-target-url="/index.jsp"
always-use-default-target="true"
/>
But I do not know how to convert it to support my changes.
Is there a way to convert it to something like:
<form-login
login-page="/${customer}/login.htm"
authentication-failure-url="/${customer}/login.htm?error=true"
login-processing-url="/${customer}/login_process"
default-target-url="/index.jsp"
always-use-default-target="true"
/>
One possible idea is to use URL rewriting instead of manual handling of tenant identifiers. This way you can completely decouple tenant handling logic from your code, for example, as follows:
You define an inbound rewriting rule that converts /abc/login.html to /login.html and saves tenant identifier as a request attribute.
You define an outbound rule that appends the current tenant identifier to URLs being written into response. I think Spring Security should respect such a rule when sending redirects (if it doesn't, you can define a custom RedirectStrategy).
Though I have not tested this idea and cannot be sure that it would work.
See also:
OCPSoft Rewrite
UrlRewriteFilter

How do I check method level spring security

I have implemented spring security in controller method.
Below is my spring security.xml
-->
<!-- URL pattern based security -->
<security:http auto-config="false" entry-point-ref="authenticationEntryPoint"
use-expressions="true">
<custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER" />
<security:intercept-url access="hasAnyRole('ROLE_ADMIN','ROLE_USER')" pattern="/common/admin/**" />
<security:intercept-url pattern="/common/accounting/**" access="hasRole('ROLE_USER')" />
<security:logout logout-url="/j_spring_security_logout" invalidate-session="true" logout-success-url="/login"/>
</security:http>
Below is my controller
#Secured({"ROLE_ADMIN"})
#RequestMapping(value = "/common/admin/addAdmin", method = RequestMethod.GET)
public String add(ModelMap map) {
map.addAttribute(new Administrator());
return "/common/admin/addAdmin";
}
#Secured({"ROLE_ADMIN"})
#RequestMapping(value = "/common/admin/addAdmin", method = RequestMethod.POST)
public String processadd(
#ModelAttribute("administrator") Administrator administrator) {
this.administratorManager.addAdmin(administrator);
return "/common/admin/success";
}
I allow the url /common/admin/** for both admin and user role. But i do some restriction in the admin controller. when user is go in to /common/admin/* as a user role, he can but he can also go in to method that is only for admin role only.
How can I solve it?
Thanks!
You already have added the #Secured annotation.
But you need to enable it:
<!-- secured-annotations = (#Secured("ROLE_ADMIN")) -->
<!-- jsr250-annotations = (#RunAs #RolesAllowed #PermitAll #DenyAll #DeclareRoles) -->
<!-- pre-post-annotations = #PreAuthorized("hasAuthority('ROLE_ADMIN')") -->
<global-method-security
secured-annotations="enabled"
jsr250-annotations="disabled"
pre-post-annotations="disabled">
</global-method-security>
#Secured can take a single or several roles.
#Secured("ROLE_USER")
#Secured({"ROLE_USER", "ROLE_ADMIN"}) //grand access if the user has one of this roles
BWT: From Spring Security 3 Book (http://www.springsecuritybook.com/):
The #Secured annotation is functionallz and syntactiallz the same as #RollesAllowed ... As #Secured functions the same as the JSR standard #RollesAllowed there's not reallz a compelling reason to use it (#Secured) in in new code...
(do not forgett to enable it jsr250-annotations="enabled")
I believe you could have multiple roles defined with #Secured annotation . Is this what you need?
If this is the case , try #RolesAllowed
Check this FAQ. Make sure the global-method-security element is in the web context file if you want to apply security to Spring MVC controllers.
Also, you may need to enable class proxying, using
<global-method-security secured-annotations="enabled" proxy-target-class="true" />
if your controller implements an interface and the method you are securing is not part of that interface (you'll also need cglib as an additional dependency in your app for this).
IF you want to use annotations, better put the following in servlet.xml. There is no point of enabling the annotations n spring-security-xml as it will not take any effect.
Putting above in servlet.xml will do the trick.

Categories