Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC - Checking if User is already logged in via Spring Security?

I have a Spring MVC application.It uses its own custom Login page. Upon successful login, a 'LOGGED_IN_USER' object is placed in the HTTPSession.

I want to allow only authenticated users to access URLs. I know i can achieve this by using a web filter. But, This part i want to do using Spring Security (my check will remain the same - look for 'LOGGED_IN_USER' object in HTTPSession, if present you are logged in).

My constraint is i cannot change Login behavior at present - that will not use Spring Security yet.

What aspect of Spring Security can i use to achieve this part alone - check if the request is authenticated (from logged in user)?

like image 430
Jasper Avatar asked Sep 11 '12 14:09

Jasper


People also ask

What is SecurityContextHolder getContext () getAuthentication ()?

The HttpServletRequest.getUserPrincipal() will return the result of SecurityContextHolder.getContext().getAuthentication() . This means it is an Authentication which is typically an instance of UsernamePasswordAuthenticationToken when using username and password based authentication.

What is SecurityContextHolder in Spring?

The SecurityContextHolder is a helper class, which provide access to the security context. By default, it uses a ThreadLocal object to store security context, which means that the security context is always available to methods in the same thread of execution, even if you don't pass the SecurityContext object around.


1 Answers

There are at least 4 different ways:

spring security XML configuration

this is the easiest way

<security:http auto-config="true" use-expressions="true" ...>    ...   <security:intercept-url pattern="/forAll/**" access="permitAll" />   <security:intercept-url pattern="/**" access="isAuthenticated()" /> </security:http> 
  • @see Spring Security Reference, Chapter 16.1.1 Common Built-In Expressions
  • @see Spring Security Reference, Chapter 16.2 Web Security Expressions

Per @Secured Annotation

requires <global-method-security secured-annotations="enabled" />

@Secured("ROLE_ADMIN") @RequestMapping(params = "onlyForAdmins")     public ModelAndView onlyForAdmins() {     .... } 

Per @PreAuthorize Annotation

requires <global-method-security pre-post-annotations="enabled" />

 @PreAuthorize("isAuthenticated()")  @RequestMapping(params = "onlyForAuthenticated")  public ModelAndView onlyForAuthenticatedUsers() {      ....  } 

Programmatic

 SecurityContextHolder.getContext().getAuthentication() != null &&  SecurityContextHolder.getContext().getAuthentication().isAuthenticated() &&  //when Anonymous Authentication is enabled  !(SecurityContextHolder.getContext().getAuthentication()            instanceof AnonymousAuthenticationToken)  

Custom Expression

If the built-in expressions are not enough, you can extend them. How to extend the SpEL Expressions for the method annotations is discussed for example here:

  • How to create custom methods for use in spring security expression language annotations
  • http://bmchild.blogspot.de/2012/02/creating-custom-regex-spring-security.html

But for the interceptor <security:intercept-url ... access="myCustomAuthenticatedExpression" /> there is a slightly different approach possible, that does not need to deal with the private class problem. -- I have only done it for Spring Security 3.0, but I hope it works for 3.1 too.

1.) you need to create a new class that extends from WebSecurityExpressionRoot (Prefix Web is the important part!).

public class MyCustomWebSecurityExpressionRoot          extends WebSecurityExpressionRoot {      public MyCustomWebSecurityExpressionRoot(Authentication a,                  FilterInvocation f) {           super(a, f);      }       /** That method is the one that does the expression evaluation! */      public boolean myCustomAuthenticatedExpression() {         return super.request.getSession().getValue("myFlag") != null;      } } 

2.) you need a extend the DefaultWebSecurityExpressionRootHandler to have a handler that provides your custom expression root

 public class MyCustomWebSecurityExpressionHandler               extends DefaultWebSecurityExpressionHandler {        @Override               public EvaluationContext createEvaluationContext(Authentication a,                 FilterInvocation f) {           StandardEvaluationContext ctx =                    (StandardEvaluationContext) super.createEvaluationContext(a, f);             WebSecurityExpressionRoot myRoot =                     new MyCustomWebSecurityExpressionRoot(a, f);             ctx.setRootObject(myRoot);            return ctx;       }  } 

3.) Then you need to register your handler with the voters

<security:http use-expressions="true"  access-decision-manager-ref="httpAccessDecisionManager" ...>       ...     <security:intercept-url pattern="/restricted/**"               access="myCustomAuthenticatedExpression" />                ... </security:http>  <bean id="httpAccessDecisionManager"       class="org.springframework.security.access.vote.AffirmativeBased">     <constructor-arg name="decisionVoters">             <list>                 <ref bean="webExpressionVoter" />             </list>     </constructor-arg> </bean>  <bean id="webExpressionVoter"       class="org.springframework.security.web.access.expression.WebExpressionVoter">     <property name="expressionHandler"               ref="myCustomWebSecurityExpressionHandler" /> </bean>  <bean id="myCustomWebSecurityExpressionHandler"     class="MyCustomWebSecurityExpressionHandler" /> 

Spring Security 3.1 Update

Since Spring Security 3.1 it is a bit easier to implement a custom expression. One does not longer need to sublcass WebSecurityExpressionHandler and override createEvaluationContext. Instead one sublass AbstractSecurityExpressionHandler<FilterInvocation> or its subclass DefaultWebSecurityExpressionHandler and override SecurityExpressionOperations createSecurityExpressionRoot(final Authentication a, final FilterInvocation f).

 public class MyCustomWebSecurityExpressionHandler               extends DefaultWebSecurityExpressionHandler {        @Override               public SecurityExpressionOperations createSecurityExpressionRoot(                 Authentication a,                 FilterInvocation f) {            WebSecurityExpressionRoot myRoot =                     new MyCustomWebSecurityExpressionRoot(a, f);             myRoot.setPermissionEvaluator(getPermissionEvaluator());            myRoot.setTrustResolver(this.trustResolver);            myRoot.setRoleHierarchy(getRoleHierarchy());            return myRoot;       }  } 
like image 185
Ralph Avatar answered Sep 27 '22 20:09

Ralph