Müsli
Müsli

Reputation: 1774

@secured with granted authorities throws access denied exception

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

Answers (1)

Ralph
Ralph

Reputation: 120771

It is a syntax error. The correct syntax for @Secured (in Spring 3.0) is

@Secured("ROLE_COMPANY_OWNER")

Upvotes: 3

Related Questions