2013-03-04 10 views
6

Podążyłem za kilkoma wątkami, aby zaimplementować Spring Security w moim rest API. Początkowo utknąłem na @Secured adnotacji są ignorowane, teraz, gdy mam to rozwiązane, utknąłem na uzyskanie odmowy dostępu.@Secured function getting Access Denied dla autoryzowanego użytkownika

Wygląda na to, że mój problem brzmi bardzo podobnie do: @secured with granted authorities throws access denied exception - ale nadal otrzymuję odmowę dostępu.

Oto moja konfiguracja:

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

} 

Teraz - bez właściwa

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

Moja prośba przechodzi (to dlatego, że @Secured adnotacja jest ignorowany). Kiedy kładę ją i dostępu do niego za pomocą „apiuser”/„apiuser”, trzymałem się odmowa dostępu, dziennik debugowania:

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 

myśli?

Z góry dziękuję!

Odpowiedz

19

Jak pamiętam, adnotacja @Secured działa tylko z nazwami domyślnie rozpoczynającymi się od ROLE_.

Możesz przełączyć się na @PreAuthorize("hasAuthority('PERMISSION_TEST')") (z pre-post-annotations="enabled") lub zmienić swoją rolę.

+0

niesamowite - wielkie dzięki! –

+0

Dodałem odpowiedź, która wyjaśnia, dlaczego odmówiono dostępu. –

+0

dzięki! Dobrze wiedzieć, jakie są wewnętrzne działania. –

8

Chcę dodać trochę więcej do odpowiedzi Michaila Nikołajewa. Moja odpowiedź jest z punktu widzenia kodu źródłowego. Chcę, abyś zrozumiał, dlaczego odmówiono dostępu.

Z dokumentacji:

Podczas korzystania z konfiguracji przestrzeni nazw, domyślna instancja AccessDecisionManager jest automatycznie rejestrowane dla Ciebie i będą wykorzystywane do podejmowania decyzji dostępu do wywołania metody i dostępu URL internetowej, w oparciu o dostępie atrybuty określone w deklaracjach przechwytywania-url i chronionych punktów (oraz w adnotacjach, jeśli używasz metod zabezpieczonych adnotacjami). Strategia domyślna polega na użyciu AffirmativeBased AccessDecisionManager z RoleVoter i AuthenticatedVoter.

RoleVoter wykorzystuje ROLE_ prefiks (domyślnie) w celu podjęcia decyzji, czy może głosować. Możesz zmienić domyślny prefiks za pomocą metody RoleVoter.setRolePrefix().

z kodu źródłowego:

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 nie zaczyna ROLE_ tak RoleVoter wstrzymuje się z podjęciem decyzji. AuthenticatedVoter wstrzymuje się również (ponieważ nie użyłeś prefiksu IS_AUTHENTICATED_ w adnotacji @Secured).

Wreszcie, AffirmativeBased realizacja AccessDecisionManager rzuca AccessDeniedException, ponieważ zarówno AccessDecisionVoters powstrzymał się od głosowania.

docs Java dla AffirmativeBased:

Proste konkretna realizacja org.springframework.security.access.AccessDecisionManager że przyznaje dostęp ewentualne AccessDecisionVoter zwraca odpowiedź twierdzącą.

Powiązane problemy