2013-03-04 1 views
6

Ich habe einige Threads verfolgt, um Spring Security zu meiner Rest API zu implementieren. Am Anfang bleibe ich bei @Secured Anmerkung hängen, die ignoriert wird, jetzt, da ich das gelöst habe, bin ich darauf beharrt, Zugriff verweigert zu bekommen.@Secured Funktion Zugriff für autorisierten Benutzer verweigert

Fühlt sich wie mein Problem Sound sehr ähnlich zu: @secured with granted authorities throws access denied exception - aber ich bekomme immer noch Zugriff verweigert.

Hier ist mein Setup:

feder 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; 
    } 

} 
Jetzt

- ohne die richtige

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

Meine Anfrage geht durch (dies, weil die @Secured Anmerkung ignoriert). Wenn ich es in und Zugriff auf sie "apiuser"/"apiuser" können, hielt ich den Zugriff immer verweigert, das Debug-Log:

11:42:43,899 [http-apr-8080-exec-4] DEBUG MethodSecurityInterceptor - Previously Authenticated: org.springframew[email protected]cc12af5d: Principal: [email protected]: Username: apiuser; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: PERMISSION_TEST; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: PERMISSION_TEST 

11:42:43,899 [http-apr-8080-exec-4] DEBUG AffirmativeBased - Voter: [email protected], returned: 0 
11:42:43,900 [http-apr-8080-exec-4] DEBUG AffirmativeBased - Voter: [email protected]6ec2, returned: 0 

11:42:43,902 [http-apr-8080-exec-4] DEBUG AnnotationMethodHandlerExceptionResolver - Resolving exception from handler [[email protected]]: org.springframework.security.access.AccessDeniedException: Access is denied 
11:42:43,905 [http-apr-8080-exec-4] DEBUG ResponseStatusExceptionResolver - Resolving exception from handler [[email protected]]: org.springframework.security.access.AccessDeniedException: Access is denied 
11:42:43,906 [http-apr-8080-exec-4] DEBUG DefaultHandlerExceptionResolver - Resolving exception from handler [[email protected]]: 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 

Gedanken?

Vielen Dank im Voraus!

Antwort

19

Wie ich mich erinnere @Secured Annotation funktioniert nur mit Rollennamen beginnend ROLE_ standardmäßig. Sie können zu @PreAuthorize("hasAuthority('PERMISSION_TEST')") wechseln (mit) oder Ihre Rolle umbenennen.

+0

genial - vielen Dank! –

+0

Ich habe eine Antwort hinzugefügt, die erklärt, warum der Zugriff verweigert wurde. –

+0

danke! gut zu wissen, die inneren arbeiten –

8

Ich möchte ein wenig mehr zu Michail Nikolaev Antwort hinzufügen. Meine Antwort ist aus Sicht des Quellcodes. Ich möchte, dass Sie verstehen, warum der Zugang verweigert wurde.

Aus Dokumentation:

Wenn Sie eine Namespace-Konfiguration verwenden, eine Standardinstanz von AccessDecisionManager automatisch für Sie registrieren und wird für die Herstellung von Zugriffsentscheidungen für Methodenaufrufe und Web-URL-Zugriff verwendet werden, basierend auf dem Zugang Attribute, die Sie in Ihren intercept-URL- und protect-poincut-Deklarationen angeben (und in Annotationen, wenn Sie mit Annotation gesicherte Methoden verwenden). Die Standardstrategie besteht darin, einen AffirmativeBased AccessDecisionManager mit einem RoleVoter und einem AuthenticatedVoter zu verwenden.

RoleVoter verwendet ROLE_ Präfix (Standardeinstellung), um zu entscheiden, ob es stimmen. Sie können dieses Standardpräfix mit der Methode RoleVoter.setRolePrefix() ändern.

Von Quellcode:

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 startet nicht mit ROLE_ so RoleVoter enthält sich von der Entscheidung. AuthenticatedVoter enthält auch (wie Sie IS_AUTHENTICATED_ Präfix in @Secured Annotation nicht verwendet haben).

Schließlich AffirmativeBased Umsetzung von AccessDecisionManager wirft AccessDeniedException, weil beide AccessDecisionVoters Stimme enthalten.

Java-Dokumentation für AffirmativeBased:

Einfache konkrete Umsetzung org.springframework.security.access.AccessDecisionManager die Zugang gewährt, wenn eine AccessDecisionVoter eine positive Antwort zurückgibt.