it-swarm.com.de

Wie kann ich "hasRole" im Java-Code mit Spring Security überprüfen?

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"));
}
105
Piotr Gwiazda

Spring Security 3.0 verfügt über diese API 

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

Sie müssen den Wrapper injizieren, bevor Sie ihn verwenden.

SecurityContextHolderAwareRequestWrapper

68
JoseK

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
    }
}
128
gouki

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"));
59
Ninca

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;
    }
44
Nate Sammons

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;
  }
13
Gopi

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);
}
9
Joey Jarin

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;
}
5
Starman

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.

4
holmis83

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

2

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;
    }
2
Alireza Fattahi

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();
}
2
lukec

Den meisten Antworten fehlen einige Punkte: 

  1. Rolle und Autorität sind im Frühling nicht dasselbe. Siehe hier für mehr Details.

  2. Rollennamen sind gleich rolePrefix + authority.

  3. 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);
    }
}
2
Utku Özdemir

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.

1
JonnyRaa

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
0
user8174892

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");
}
0
Luke Cheung

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

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.

0
Kirinya