@Secured access function for authorized user

I have performed quite a few threads to implement Spring Security in my leisure API. Originally I was stuck in @Secured annotations are ignored, now that I got this solution, I'm stuck in getting access denied.

It sounds like my problematic sound is very similar to: privileged @secured, which prohibits access exception - but I still get access denied.

Here is my setup:

spring -security.xml

<authentication-manager> <authentication-provider user-service-ref="userDetailsService"> <password-encoder ref="passwordEncoder" /> </authentication-provider> </authentication-manager> <beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder"/> <user-service id="userDetailsService"> <user name="john" password="john1" authorities="ROLE_USER, ROLE_ADMIN" /> <user name="jane" password="jane1" authorities="ROLE_USER" /> <user name="apiuser" password="apiuser" authorities="PERMISSION_TEST" /> </user-service> 

controller

 @Controller @RequestMapping("/secure") public class SecureController { private static final Logger logger = Logger.getLogger(SecureController.class); @Secured("PERMISSION_TEST") @RequestMapping(value = "/makeRequest", method = RequestMethod.GET) @ResponseBody public SimpleDTO executeSecureCall() { logger.debug("[executeSecureCall] Received request to a secure method"); SimpleDTO dto = new SimpleDTO(); dto.setStringVariable("You are authorized!"); return dto; } } 

Now - without the right

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

My request passes (this is because the @Secured annotation is ignored). When I insert it and access it using "apiuser" / "apiuser", I always refuse access, debug log:

 11:42:43,899 [http-apr-8080-exec-4] DEBUG MethodSecurityInterceptor - Previously Authenticated: org.springframew ork.security.authentication.UsernamePasswordAuthenticationToken@ cc12af5d: Principal: org.springframework.security.core.userdetails.User@d059c8e5 : Username: apiuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: PERMISSION_TEST; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin gframework.security.web.authentication.WebAuthenticationDetails@ 957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: PERMISSION_TEST 11:42:43,899 [http-apr-8080-exec-4] DEBUG AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@2a9a42ef , returned: 0 11:42:43,900 [http-apr-8080-exec-4] DEBUG AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@75a0 6ec2, returned: 0 11:42:43,902 [http-apr-8080-exec-4] DEBUG AnnotationMethodHandlerExceptionResolver - Resolving exception from handler [ com.test.webapp.spring.controller.SecureController@342d150f ]: org.springframework.security.access.AccessDeniedException: Access is denied 11:42:43,905 [http-apr-8080-exec-4] DEBUG ResponseStatusExceptionResolver - Resolving exception from handler [ com.test.webapp.spring.controller.SecureController@342d150f ]: org.springframework.security.access.AccessDeniedException: Access is denied 11:42:43,906 [http-apr-8080-exec-4] DEBUG DefaultHandlerExceptionResolver - Resolving exception from handler [ com.test.webapp.spring.controller.SecureController@342d150f ]: org.springframework.security.access.AccessDeniedException: Access is denied 11:42:43,909 [http-apr-8080-exec-4] DEBUG DispatcherServlet - Could not complete request org.springframework.security.access.AccessDeniedException: Access is denied 

Thoughts?

Thanks in advance!

+6
source share
2 answers

As I recall, the @Secured annotation @Secured works with role names starting with ROLE_ by default.

You can switch to @PreAuthorize("hasAuthority('PERMISSION_TEST')") (using pre-post-annotations="enabled" ) or rename your role.

+20
source

I want to add a little more answer Nikolay Nikolaev. My answer is in terms of source code. I want you to understand why access was denied.

From the documentation:

When you use a namespace configuration, an AccessDecisionManager instance is automatically registered for you by default and will be used to make decisions about accessing method calls and accessing web URLs based on the access attributes that you specify in your intercept URL and the -pointcut protection (and in annotations if you use protected annotation methods). The default strategy is to use the AccessDecisionManager with confirmation using RoleVoter and AuthenticatedVoter.

RoleVoter uses the ROLE_ prefix (default) to decide if it can vote. You can change this default prefix using the RoleVoter.setRolePrefix() method.

From the source code:

 public class RoleVoter implements AccessDecisionVoter<Object> { (...) private String rolePrefix = "ROLE_"; (...) public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } (...) public boolean supports(ConfigAttribute attribute) { if ((attribute.getAttribute() != null) && attribute.getAttribute().startsWith(getRolePrefix())) { return true; } else { return false; } } (...) public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) { int result = ACCESS_ABSTAIN; Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication); for (ConfigAttribute attribute : attributes) { if (this.supports(attribute)) { result = ACCESS_DENIED; // Attempt to find a matching granted authority for (GrantedAuthority authority : authorities) { if (attribute.getAttribute().equals(authority.getAuthority())) { return ACCESS_GRANTED; } } } } return result; } 

PERMISSION_TEST does not start with ROLE_ , so RoleVoter refrains from making a decision. AuthenticatedVoter also abstains (since you did not use the IS_AUTHENTICATED_ prefix in the IS_AUTHENTICATED_ annotation).

Finally, the AffirmativeBased implementation of the AccessDecisionManager throws an AccessDeniedException because both AccessDecisionVoters abstained from voting.

Java docs for AffirmativeBased :

A simple concrete implementation of org.springframework.security.access.AccessDecisionManager that provides access if any AccessDecisionVoter returns a positive response.

+8
source

All Articles