Reputation: 1358
I am trying to implement custom @PreAuthorize
method in my spring (3.2.2) mvc app. But whenever I click on the link which is supposed to take me to the controller method where the @PreAuthorize
is implemented it gives me this error :
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:339)
org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:198)
org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:60)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
com.nav.qanda.admin.question.controller.AdminQuestionController$$EnhancerByCGLIB$$5bcda356_2.handleRequest(<generated>)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
This is my app-servlet.xml
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler" />
</security:global-method-security>
<bean id="expressionHandler" class="com.nav.panda.security.PandaMethodSecurityExpressionHandler" />
and these are the java files overriding
public class PandaMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler{
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
MethodInvocation invocation){
PandaMethodSecurityExpressionRoot root = new PandaMethodSecurityExpressionRoot(authentication);
root.setThis(invocation.getThis());
return root;
}
public class PandaMethodSecurityExpressionRoot implements MethodSecurityExpressionOperations {
private Object filterObject;
private Object returnObject;
private Object target;
public boolean adminOnly() {
System.out.println("Checking admin authority");
return true;
// return this.hasAuthority("ADMIN");
} ... other methods
And the controller looks like this :
@RequestMapping(value = "/createPandaPage", method = RequestMethod.GET)
@PreAuthorize("adminOnly()")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
return new ModelAndView("admin/createPanda");
}
web.xml :
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The login in my application will populate a User object (which has the users authority filled from a db read) from my application. How do I pass this User Object to check for authority ? And, what else would I need to do to get this working ?
Upvotes: 0
Views: 1824
Reputation: 22742
The request which leads to this method being called need to pass through the Spring Security filter chain, otherwise there will be no security context available when the permissions are checked.
Without seeing the rest of the stacktrace, I can't say 100%, but it looks like that's what's happening here, given the exception you are seeing (you should find similar issues if you search for the error message).
So you need to make sure all the requests you want secured are handled by the security filter chain, and also that your filter chain is properly configured (which it should be automatically if you're using the namespace).
Upvotes: 3