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)?
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.
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.
There are at least 4 different ways:
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>
requires <global-method-security secured-annotations="enabled" />
@Secured("ROLE_ADMIN") @RequestMapping(params = "onlyForAdmins") public ModelAndView onlyForAdmins() { .... }
requires <global-method-security pre-post-annotations="enabled" />
@PreAuthorize("isAuthenticated()") @RequestMapping(params = "onlyForAuthenticated") public ModelAndView onlyForAuthenticatedUsers() { .... }
SecurityContextHolder.getContext().getAuthentication() != null && SecurityContextHolder.getContext().getAuthentication().isAuthenticated() && //when Anonymous Authentication is enabled !(SecurityContextHolder.getContext().getAuthentication() instanceof AnonymousAuthenticationToken)
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:
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; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With