2010-06-11 113 views

回答

59
+1

這只是爲了 - 通過auth.getAuthorities()進行每次查找 複製此代碼比構造或讀取SecurityContextHolderAwareRequestWrapper對象更容易。 我寧願要使用所有安全EL方法。例如ACL – 2010-06-11 11:58:57

+33

的hasPermission正如你的答案所述,它看起來像方法是靜態的,但是你需要一個'SecurityContextHolderAwareRequestWrapper'實例。你可以改進它,解釋如何獲得它,並更多地澄清答案本身。 – 2015-02-23 09:59:18

+2

如何檢索控制器中的包裝? – 2015-08-04 12:17:59

2

奇怪的是,我不認爲這是一個標準的解決了這個問題,因爲彈簧安全訪問控制是expression based,不是基於Java的。你可能要檢查的源代碼 DefaultMethodSecurityExpressionHandler,看看是否可以重複使用的東西,他們正在做的有

+0

所以你的解決方案是使用DefaultMethodSecurityExpressionHandler豆,並得到表達式解析器,並檢查它在EL? – 2010-06-11 12:03:32

+0

可能無法正常工作,因爲處理程序在methodinvocations(您在上下文中沒有)上運行。您可能需要創建自己的bean,但是不需要使用方法調用上下文 – 2010-06-11 12:54:32

112

可以使用的isUserInRole方法的HttpServletRequest對象。

類似:

public String createForm(HttpSession session, HttpServletRequest request, ModelMap modelMap) { 


    if (request.isUserInRole("ROLE_ADMIN")) { 
     // code here 
    } 
} 
+0

你是最棒的! – 2013-04-30 18:15:43

+0

更容易測試我認爲 – fego 2014-02-14 11:16:43

+0

但如果我沒有要求? – gstackoverflow 2015-09-15 12:07:15

13

您可以實現如下一個hasRole()方法 - (這是在春季安全3.0.x的測試,不知道其他版本。)

protected final boolean hasRole(String role) { 
    boolean hasRole = false; 
    UserDetails userDetails = getUserDetails(); 
    if (userDetails != null) { 
     Collection<GrantedAuthority> authorities = userDetails.getAuthorities(); 
     if (isRolePresent(authorities, role)) { 
     hasRole = true; 
     } 
    } 
    return hasRole; 
    } 
    /** 
    * Get info about currently logged in user 
    * @return UserDetails if found in the context, null otherwise 
    */ 
    protected UserDetails getUserDetails() { 
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
    UserDetails userDetails = null; 
    if (principal instanceof UserDetails) { 
     userDetails = (UserDetails) principal; 
    } 
    return userDetails; 
    } 
    /** 
    * Check if a role is present in the authorities of current user 
    * @param authorities all authorities assigned to current user 
    * @param role required authority 
    * @return true if role is present in list of authorities assigned to current user, false otherwise 
    */ 
    private boolean isRolePresent(Collection<GrantedAuthority> authorities, String role) { 
    boolean isRolePresent = false; 
    for (GrantedAuthority grantedAuthority : authorities) { 
     isRolePresent = grantedAuthority.getAuthority().equals(role); 
     if (isRolePresent) break; 
    } 
    return isRolePresent; 
    } 
+0

謝謝Gopi! – anton1980 2012-07-11 16:30:08

+1

'SecurityContextHolder.getContext()。getAuthentication()'可以檢索'null'。也許你添加一些檢查? – Mrusful 2013-01-20 09:45:50

2

更好從不遲到,讓我把我的2美分價值。

在JSF的世界裏,我的管理bean中,我做了以下內容:


HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); 
SecurityContextHolderAwareRequestWrapper sc = new SecurityContextHolderAwareRequestWrapper(req, ""); 

正如上面提到的,我的理解是,這是可以做到的長篇大論方式如下:


Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
UserDetails userDetails = null; 
if (principal instanceof UserDetails) { 
    userDetails = (UserDetails) principal; 
    Collection authorities = userDetails.getAuthorities(); 
} 
5

當你在你的服務層,你不希望從引用到HTTP請求引入與web層的耦合時,來自JoseK的答案不能用於。如果您正在尋找解決服務層中的角色問題,Gopi的答案就是要走的路。

然而,它有點囉嗦。可以從認證中直接訪問權限。因此,如果你可以假設你有一個用戶登錄,下面做的:

/** 
* @return true if the user has one of the specified roles. 
*/ 
protected boolean hasRole(String[] roles) { 
    boolean result = false; 
    for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) { 
     String userRole = authority.getAuthority(); 
     for (String role : roles) { 
      if (role.equals(userRole)) { 
       result = true; 
       break; 
      } 
     } 

     if (result) { 
      break; 
     } 
    } 

    return result; 
} 
9

我使用這個:

@RequestMapping(method = RequestMethod.GET) 
public void welcome(SecurityContextHolderAwareRequestWrapper request) { 
    boolean b = request.isUserInRole("ROLE_ADMIN"); 
    System.out.println("ROLE_ADMIN=" + b); 

    boolean c = request.isUserInRole("ROLE_USER"); 
    System.out.println("ROLE_USER=" + c); 
} 
38

您可以檢索安全上下文,然後使用:

import org.springframework.security.core.Authentication; 
    import org.springframework.security.core.GrantedAuthority; 
    import org.springframework.security.core.context.SecurityContext; 
    import org.springframework.security.core.context.SecurityContextHolder; 

    protected boolean hasRole(String role) { 
     // get security context from thread local 
     SecurityContext context = SecurityContextHolder.getContext(); 
     if (context == null) 
      return false; 

     Authentication authentication = context.getAuthentication(); 
     if (authentication == null) 
      return false; 

     for (GrantedAuthority auth : authentication.getAuthorities()) { 
      if (role.equals(auth.getAuthority())) 
       return true; 
     } 

     return false; 
    } 
46

而不是使用一個循環來找到的UserDetails的權限,你可以這樣做:

Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); 
boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN")); 
+2

一個更好的答案,但是ROLE_ADMIN應該用雙引號。 – 2015-01-18 20:17:49

+4

這是非常危險的。請注意,切換到GrantedAuthority實現的另一個實現(例如JAAS,通過添加另一個授權可能性)將會導致此代碼發生故障。請參閱SimpleGrantedAuthority中的equals()實現 – 2016-04-19 12:35:19

0

這是來自另一端的問題,但我想我會把它扔進去,因爲我真的必須在互聯網上挖掘才能找到答案。

有一個關於如何檢查的作用,但並不多說什麼你實際上是在檢查時,你說hasRole(「嗒嗒」)

HasRole檢查授予的權限目前已通過驗證本金

很多東西

所以真的,當你看到hasRole( 「嗒嗒」)的真正含義hasAuthority( 「嗒嗒」)

在我看到的情況下,您可以使用實現UserDetails的類來完成此操作,該類定義了一個名爲getAuthorities的方法。在這裏,你基本上將一些new SimpleGrantedAuthority("some name")添加到基於某種邏輯的列表中。這個列表中的名字是由hasRole語句檢查的東西。

我猜在這種情況下,UserDetails對象是當前認證的主體。在身份驗證提供程序中及其周圍發生一些魔術,更具體地說是發生這種情況的身份驗證管理器。

+1

從Spring Security 4.0開始,此hasRole(「bla」)'現在等於'hasAuthority(「ROLE_bla」)'。 – lanoxx 2016-07-28 13:38:07

1

@gouki答案是最好的!

只是春天真的這樣做的一角。

有一個名爲SecurityContextHolderAwareRequestWrapper類,它實現ServletRequestWrapper類。

SecurityContextHolderAwareRequestWrapper覆蓋isUserInRole和搜索用戶Authentication(由Spring管理)來查找用戶是否具有角色。

SecurityContextHolderAwareRequestWrapper代碼爲:

@Override 
    public boolean isUserInRole(String role) { 
     return isGranted(role); 
    } 

private boolean isGranted(String role) { 
     Authentication auth = getAuthentication(); 

     if(rolePrefix != null) { 
      role = rolePrefix + role; 
     } 

     if ((auth == null) || (auth.getPrincipal() == null)) { 
      return false; 
     } 

     Collection<? extends GrantedAuthority> authorities = auth.getAuthorities(); 

     if (authorities == null) { 
      return false; 
     } 

     //This is the loop which do actual search 
     for (GrantedAuthority grantedAuthority : authorities) { 
      if (role.equals(grantedAuthority.getAuthority())) { 
       return true; 
      } 
     } 

     return false; 
    } 
0

在我們的項目中,我們使用的是角色的層次結構,而最上面的答案只針對檢查一個特定的角色,即只檢查中的作用給予,但不是那個角色和層次結構。

該A液:

@Component 
public class SpringRoleEvaluator { 

@Resource(name="roleHierarchy") 
private RoleHierarchy roleHierarchy; 

public boolean hasRole(String role) { 
    UserDetails dt = AuthenticationUtils.getSessionUserDetails(); 

    for (GrantedAuthority auth: roleHierarchy.getReachableGrantedAuthorities(dt.getAuthorities())) { 
     if (auth.toString().equals("ROLE_"+role)) { 
      return true; 
     } 
    } 
    return false; 
} 

RoleHierarchy被定義爲在彈簧security.xml文件的bean。

+0

或者您可以正確填充您的角色: https://github.com/spring-projects/spring-security/issues/2152#issuecomment-180599279 – arctica 2017-08-04 12:05:53

0

您可以從AuthorityUtils類獲得一些幫助。檢查角色作爲一行:

if (AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities()).contains("ROLE_MANAGER")) { 
    /* ... */ 
} 

注意:這不檢查角色層次結構,如果存在。

0

大多數答案都缺少一些要點:

  1. 作用和權威不是在春天一樣的東西。看到這裏爲more細節。

  2. 角色名等於rolePrefix + authority

  3. 默認角色前綴爲ROLE_,但是,它是可配置的。見here

因此,如果角色前綴配置正確,角色檢查需要考慮角色前綴。

不幸的是,在Spring中的作用前綴定製是有點哈克,在許多地方的默認前綴,ROLE_是硬編碼的,但除此之外,GrantedAuthorityDefaults類型的豆在Spring上下文進行檢查,如果存在,它具有的自定義角色前綴是受到尊重的。

將所有這些信息一起,更好的角色檢查的實施將是這樣的:

@Component 
public class RoleChecker { 

    @Autowired(required = false) 
    private GrantedAuthorityDefaults grantedAuthorityDefaults; 

    public boolean hasRole(String role) { 
     String rolePrefix = grantedAuthorityDefaults != null ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_"; 
     return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) 
       .map(Authentication::getAuthorities) 
       .map(Collection::stream) 
       .orElse(Stream.empty()) 
       .map(GrantedAuthority::getAuthority) 
       .map(authority -> rolePrefix + authority) 
       .anyMatch(role::equals); 
    } 
} 
相關問題