2013-03-04 19 views
6

我已經遵循了很多線程來實現Spring Security到我的rest API。最初我被卡住@Secured註解被忽略,現在我得到了解決,我堅持拒絕訪問。@Secured函數獲得授權用戶拒絕訪問

覺得我的問題聽起來很像:@secured with granted authorities throws access denied exception - 但我仍然拒絕訪問。

這裏是我的設置:

彈簧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 
@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; 
    } 

} 

現在 - 沒有正確

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

我的請求經過(這是因爲@Secured註釋被忽略)。當我把它放在和使用「apiuser」 /「apiuser」訪問它,我一直得到拒絕訪問,調試日誌:

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 

的思考?

在此先感謝!

回答

19

我記得@Secured註釋只適用於角色名稱,默認開始ROLE_

您可以切換到@PreAuthorize("hasAuthority('PERMISSION_TEST')")(與pre-post-annotations="enabled")或重命名您的角色。

+0

真棒 - 非常感謝! – 2013-03-04 17:19:10

+0

我添加了答案,解釋了訪問被拒絕的原因。 – 2013-03-04 18:16:02

+0

謝謝!很高興知道內部工作原理 – 2013-04-14 04:36:52

8

我想多給Michail Nikolaev添加一些答案。 我的答案是從源代碼的角度來看。我想讓你明白爲什麼訪問被拒絕。

從技術文檔:

當你使用一個命名空間的配置,默認的AccessDecisionManager實例會自動註冊爲您和將被用來爲方法調用和web URL訪問做驗證,基於訪問你在intercept-url和protect-pointcut聲明中指定的屬性(如果你使用註解安全方法,則在註釋中)。 默認策略是使用AffirmativeBased AccessDecisionManager與RoleVoter和AuthenticatedVoter。

RoleVoter,以決定它是否可以投用ROLE_前綴(默認情況下)。您可以使用RoleVoter.setRolePrefix()方法更改該默認前綴。

從源代碼:

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_TESTROLE_所以RoleVoter棄權票從決定開始。 AuthenticatedVoter也棄權(因爲您在@Secured註釋中沒有使用IS_AUTHENTICATED_前綴)。

最後,AffirmativeBased執行AccessDecisionManager引發AccessDeniedException,因爲AccessDecisionVoters都投了棄權票。

AffirmativeBased Java文檔:

簡單的具體實施 org.springframework.security.access.AccessDecisionManager授予 訪問,如果任何的AccessDecisionVoter返回肯定響應。

相關問題