Wie kann ich die Benutzerberechtigung oder Berechtigung in Java Code überprüfen? Zum Beispiel - Ich möchte die Schaltfläche für den Benutzer je nach Rolle ein- oder ausblenden. Es gibt Anmerkungen wie:
@PreAuthorize("hasRole('ROLE_USER')")
Wie mache ich es in Java-Code? So etwas wie :
if(somethingHere.hasRole("ROLE_MANAGER")) {
layout.addComponent(new Button("Edit users"));
}
Spring Security 3.0 verfügt über diese API
SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)
Sie müssen den Wrapper injizieren, bevor Sie ihn verwenden.
sie können die isUserInRole-Methode des HttpServletRequest-Objekts verwenden.
so etwas wie:
public String createForm(HttpSession session, HttpServletRequest request, ModelMap modelMap) {
if (request.isUserInRole("ROLE_ADMIN")) {
// code here
}
}
Anstelle einer Schleife zum Auffinden der Berechtigung in UserDetails können Sie Folgendes tun:
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN"));
Sie können den Sicherheitskontext abrufen und dann Folgendes verwenden:
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;
}
Sie können eine hasRole () -Methode wie folgt implementieren - (Dies wurde für Spring Security 3.0.x getestet, da andere Versionen nicht sicher sind.)
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;
}
Ich benutze das:
@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);
}
Die Antwort von JoseK kann nicht verwendet werden, wenn Sie sich in Ihrer Service-Schicht befinden, wenn Sie keine Kopplung mit der Web-Ebene aus dem Verweis auf die HTTP-Anforderung einführen möchten. Wenn Sie versuchen, die Rollen in der Service-Ebene zu lösen, ist die Antwort von Gopi der richtige Weg.
Es ist jedoch etwas langatmig. Auf die Behörden kann direkt von der Authentifizierung aus zugegriffen werden. Wenn Sie also davon ausgehen können, dass ein Benutzer angemeldet ist, gilt Folgendes:
/**
* @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;
}
Hilfe erhalten Sie von AuthorityUtils class. Überprüfungsrolle als Einzeiler:
if (AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities()).contains("ROLE_MANAGER")) {
/* ... */
}
Vorsichtsmaßnahme: Dies überprüft die Rollenhierarchie nicht, sofern vorhanden.
Seltsamerweise glaube ich nicht, dass es eine Standardlösung für dieses Problem gibt, da die Zugriffskontrolle auf Federsicherheit Ausdruck basiert und nicht Java-basiert ist. Sie können den Quellcode für DefaultMethodSecurityExpressionHandler überprüfen, um zu sehen, ob Sie etwas wiederverwenden können, das sie dort tun
Die @ gouki-Antwort ist am besten!
Nur ein Tipp, wie der Frühling das wirklich macht.
Es gibt eine Klasse mit dem Namen SecurityContextHolderAwareRequestWrapper
, die die ServletRequestWrapper
-Klasse implementiert.
Die SecurityContextHolderAwareRequestWrapper
überschreibt den isUserInRole
und den Suchbenutzer Authentication
(der von Spring verwaltet wird), um festzustellen, ob der Benutzer eine Rolle hat oder nicht.
SecurityContextHolderAwareRequestWrapper
Der Code lautet:
@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;
}
Besser spät als nie, lassen Sie mich meinen Wert von 2 Cent einbringen.
In der JSF-Welt habe ich in meiner Managed Bean Folgendes getan:
HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
SecurityContextHolderAwareRequestWrapper sc = new SecurityContextHolderAwareRequestWrapper(req, "");
Wie bereits erwähnt, kann ich meinen, dass dies auf die lange gewundene Weise geschehen kann:
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
if (principal instanceof UserDetails) {
userDetails = (UserDetails) principal;
Collection authorities = userDetails.getAuthorities();
}
Den meisten Antworten fehlen einige Punkte:
Rolle und Autorität sind im Frühling nicht dasselbe. Siehe hier für mehr Details.
Rollennamen sind gleich rolePrefix
+ authority
.
Das Standardrollenpräfix lautet ROLE_
, es ist jedoch konfigurierbar. Siehe hier .
Daher muss bei einer ordnungsgemäßen Rollenprüfung das Rollenpräfix berücksichtigt werden, wenn es konfiguriert ist.
Leider ist die Anpassung der Rollenpräfixe in Spring etwas hackig, an vielen Stellen ist das Standardpräfix ROLE_
hartcodiert. Darüber hinaus wird eine Bean vom Typ GrantedAuthorityDefaults
im Spring-Kontext und, falls vorhanden, die benutzerdefinierte Rolle überprüft Präfix wird respektiert.
Um all diese Informationen zusammenzuführen, wäre eine bessere Implementierung des Rollenprüfers so etwas wie:
@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);
}
}
Diese Frage kommt irgendwie von der anderen Seite, aber ich dachte, ich würde sie einwerfen, da ich wirklich im Internet suchen musste, um das herauszufinden.
Es gibt eine Menge Sachen, wie man Rollen überprüft, aber nicht viel sagt, was man eigentlich prüft, wenn man hasRole ("blah") sagt.
HasRole prüft die erteilten Behörden auf den aktuell authentifizierten Auftraggeber
Wenn Sie also hasRole ("blah") sehen, bedeutet dies wirklich hasAuthority ("blah") .
In dem Fall, den ich gesehen habe, tun Sie dies mit einer Klasse, die UserDetails implementiert, die eine Methode namens getAuthorities definiert. In diesem Fall fügen Sie im Grunde etwas new SimpleGrantedAuthority("some name")
zu einer Liste hinzu, die auf einer Logik basiert. Die Namen in dieser Liste werden von den hasRole-Anweisungen geprüft.
Ich denke, in diesem Zusammenhang ist das UserDetails-Objekt der aktuell authentifizierte Principal. In und um Authentifizierungsanbieter gibt es einige magische Effekte, und insbesondere der Authentifizierungsmanager, der dies ermöglicht.
Fügen Sie Ihrem Benutzermodell einfach eine "hasRole" -Methode wie unten hinzu
public boolean hasRole(String auth) {
for (Role role : roles) {
if (role.getName().equals(auth)) { return true; }
}
return false;
}
Ich benutze es normalerweise, um zu überprüfen, ob der authentifizierte Benutzer die Rolle admin wie folgt hat
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // This gets the authentication
User authUser = (User) authentication.getPrincipal(); // This gets the logged in user
authUser.hasRole("ROLE_ADMIN") // This returns true or false
Diese zwei Annotationen sind gleich, "hasRole" fügt automatisch das Präfix "ROLE_" hinzu. Stellen Sie sicher, dass Sie die richtige Anmerkung haben. Diese Rolle wird in UserDetailsService # loadUserByUsername festgelegt.
@PreAuthorize("hasAuthority('ROLE_user')")
@PreAuthorize("hasRole('user')")
anschließend können Sie die Rolle in Java-Code abrufen.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_user"))){
System.out.println("user role2");
}
Mein Ansatz mit Hilfe von Java 8: Durch das Passieren von durch Kommas getrennten Rollen erhalten Sie Wahr oder Falsch
public static Boolean hasAnyPermission(String permissions){
Boolean result = false;
if(permissions != null && !permissions.isEmpty()){
String[] rolesArray = permissions.split(",");
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
for (String role : rolesArray) {
boolean hasUserRole = authentication.getAuthorities().stream().anyMatch(r -> r.getAuthority().equals(role));
if (hasUserRole) {
result = true;
break;
}
}
}
return result;
}
In unserem Projekt verwenden wir eine Rollenhierarchie, während die meisten der obigen Antworten nur darauf abzielen, nach einer bestimmten Rolle zu suchen, d. H. Nur nach der zugewiesenen Rolle, nicht aber nach dieser Rolle und nach oben.
Eine Lösung dafür:
@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 ist in spring-security.xml als Bean definiert.