Reputation: 1774
I'm configuring and testing spring security 3.1.0.
I have a user that has ROLE_COMPANY_OWNER. The idea is that only users with that authority access the url : companies/list
so, in my controller in method list i annotated it with @Secured("hasRole('ROLE_COMPANY_OWNER')")
i know i can configure it in security context file with But i will have services annotated with @Secured so i'm probing in advace with controller methods.
The problem is access denied is thrown even when the user has the authority.
I'm missing something? Every voter is returning access abstain.
Here is my configuration:
security-applicationContext.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<global-method-security secured-annotations="enabled" pre-post-annotations="enabled" proxy-target-class = "true"/>
<http pattern="/resources/**" security="none"/>
<http use-expressions="true">
<!-- <intercept-url pattern="/**" access="isAuthenticated()" /> -->
<form-login login-page='/spring_security_login' default-target-url='/index.html'
always-use-default-target='true' />
<logout delete-cookies="JSESSIONID" />
</http>
<authentication-manager>
<authentication-provider user-service-ref="AuthRepository">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
</beans:beans>
controller
package ar.com.held.controller;
@Controller
@RequestMapping("companies")
public class CompanyController {
@Autowired
private CompanyRepository companyRepository;
@Secured("hasRole('ROLE_COMPANY_OWNER')")
@RequestMapping(value={"","list"})
public String list(Model model){
Long userId = getLoggedUser().getId();
List<Company> companies = this.companyRepository.findOwnedBy(userId);
model.addAttribute("companies", companies);
return "company/list";
}
}
my custom provider
@Repository(value="AuthRepository")
public class AuthRepository extends JdbcDaoImpl {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userRepository.findByUserName(username);
if(user==null)
throw new UsernameNotFoundException(username+" no es un usuario registrado");
return new ar.com.held.auth.UserDetails(user);
}
@Override
protected void checkDaoConfig() {
}
}
my custom user details:
public class UserDetails implements
org.springframework.security.core.userdetails.UserDetails {
/**
*
*/
private static final long serialVersionUID = -2636146093986968636L;
private User user;
private String userName;
private String password;
private List<SimpleGrantedAuthority> authorities;
public User getUser() {
return user;
}
public UserDetails(User user) {
this.authorities = new ArrayList<>();
this.user = user;
this.userName = user.getUsername();
this.password = user.getPassword();
if(user.getAuthorities()!=null){
for (Authority authotiry : user.getAuthorities()) {
if(authotiry.isValid())
this.authorities.add(new SimpleGrantedAuthority(authotiry.getAuthority()));
}
}
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.authorities;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.userName;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Here is the exception:
2012-02-15 19:39:11 DispatcherServlet [DEBUG] Last-Modified value for [/Held/companies/list] is: -1
2012-02-15 19:39:11 MethodSecurityInterceptor [DEBUG] Secure object: ReflectiveMethodInvocation: public java.lang.String ar.com.held.controller.CompanyController.list(org.springframework.ui.Model); target is of class [ar.com.held.controller.CompanyController]; Attributes: [hasRole('ROLE_COMPANY_OWNER')]
2012-02-15 19:39:11 MethodSecurityInterceptor [DEBUG] Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@e0634cab: Principal: ar.com.held.auth.UserDetails@1fd596b; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: AEEB034DEEFA679FB64DC3BF3475928D; Granted Authorities: ROLE_COMPANY_OWNER
2012-02-15 19:39:11 AffirmativeBased [DEBUG] Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@1201fe5, returned: 0
2012-02-15 19:39:11 AffirmativeBased [DEBUG] Voter: org.springframework.security.access.vote.RoleVoter@e11b6, returned: 0
2012-02-15 19:39:11 AffirmativeBased [DEBUG] Voter: org.springframework.security.access.vote.AuthenticatedVoter@1ace180, returned: 0
2012-02-15 19:39:11 ExceptionHandlerExceptionResolver [DEBUG] Resolving exception from handler [public java.lang.String ar.com.held.controller.CompanyController.list(org.springframework.ui.Model)]: org.springframework.security.access.AccessDeniedException: Access is denied
2012-02-15 19:39:11 ResponseStatusExceptionResolver [DEBUG] Resolving exception from handler [public java.lang.String ar.com.held.controller.CompanyController.list(org.springframework.ui.Model)]: org.springframework.security.access.AccessDeniedException: Access is denied
2012-02-15 19:39:11 DefaultHandlerExceptionResolver [DEBUG] Resolving exception from handler [public java.lang.String ar.com.held.controller.CompanyController.list(org.springframework.ui.Model)]: org.springframework.security.access.AccessDeniedException: Access is denied
2012-02-15 19:39:11 SimpleMappingExceptionResolver [DEBUG] Resolving exception from handler [public java.lang.String ar.com.held.controller.CompanyController.list(org.springframework.ui.Model)]: org.springframework.security.access.AccessDeniedException: Access is denied
2012-02-15 19:39:11 SimpleMappingExceptionResolver [DEBUG] Resolving to view 'errors/accessDenied' for exception of type [org.springframework.security.access.AccessDeniedException], based on exception mapping [.AccessDeniedException]
2012-02-15 19:39:11 SimpleMappingExceptionResolver [DEBUG] Exposing Exception as model attribute 'exception'
2012-02-15 19:39:11 DispatcherServlet [DEBUG] Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name 'errors/accessDenied'; model is {exception=org.springframework.security.access.AccessDeniedException: Access is denied}
org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70)
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:88)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:205)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at ar.com.held.controller.CompanyController$$EnhancerByCGLIB$$5279c365.list(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:212)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.opensymphony.sitemesh.webapp.SiteMeshFilter.obtainContent(SiteMeshFilter.java:129)
at com.opensymphony.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:77)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:311)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:101)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
2012-02-15 19:39:11 DispatcherServlet [DEBUG] Rendering view [org.springframework.web.servlet.view.JstlView: name 'errors/accessDenied'; URL [/WEB-INF/view/errors/accessDenied.jsp]] in DispatcherServlet with name 'spring'
2012-02-15 19:39:11 JstlView [DEBUG] Added model object 'exception' of type [org.springframework.security.access.AccessDeniedException] to request in view with name 'errors/accessDenied'
2012-02-15 19:39:11 JstlView [DEBUG] Forwarding to resource [/WEB-INF/view/errors/accessDenied.jsp] in InternalResourceView 'errors/accessDenied'
2012-02-15 19:39:11 DispatcherServlet [DEBUG] Successfully completed request
2012-02-15 19:39:11 DefaultListableBeanFactory [DEBUG] Returning cached instance of singleton bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0'
2012-02-15 19:39:11 DefaultListableBeanFactory [DEBUG] Returning cached instance of singleton bean 'org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler#0'
2012-02-15 19:39:11 DefaultListableBeanFactory [DEBUG] Returning cached instance of singleton bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler#0'
2012-02-15 19:39:11 DefaultListableBeanFactory [DEBUG] Returning cached instance of singleton bean 'org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler#0'
2012-02-15 19:39:11 ExceptionTranslationFilter [DEBUG] Chain processed normally
2012-02-15 19:39:11 SecurityContextPersistenceFilter [DEBUG] SecurityContextHolder now cleared, as request processing completed
Upvotes: 3
Views: 6932
Reputation: 120771
It is a syntax error.
The correct syntax for @Secured
(in Spring 3.0) is
@Secured("ROLE_COMPANY_OWNER")
Upvotes: 3