Les annotations d'autorisation SpringSecurity de SpringBoot effectuent l'authentification des autorisations sur les méthodes de plusieurs manières

avant-propos

Spring SecurityPrend en charge le contrôle des autorisations au niveau de la méthode. Sur la base de ce mécanisme, nous pouvons ajouter des annotations d'autorisation à n'importe quelle méthode sur n'importe quelle couche, et la méthode ajoutée à l'annotation sera automatiquement protégée Spring Security, permettant uniquement à des utilisateurs spécifiques d'accéder, afin d'atteindre l'objectif du contrôle des autorisations. l'annotation d'autorisation existante. Si vous n'êtes pas satisfait, nous pouvons également personnaliser

démarrage rapide

  1. Ajoutez d'abord la dépendance de sécurité comme suit
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. Créez ensuite une nouvelle classe de configuration de sécurité

Spring SecurityPar défaut, les annotations sont désactivées. Pour activer les annotations, vous devez annoter la WebSecurityConfigurerAdapterclasse héritée @EnableMethodSecurityet la AuthenticationManagerdéfinir commeBean。

@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(
  prePostEnabled = true, 
  securedEnabled = true, 
  jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
    
    
        return super.authenticationManagerBean();
    }
}

Nous voyons qu'il @EnableGlobalMethodSecurityy a respectivement trois champs prePostEnabled 、securedEnabled、jsr250Enabled, dont chacun code un support d'annotation, et la valeur par défaut est false,true为开启. Parlons ensuite du support de ces trois annotations générales une par une.

L'effet de prePostEnabled = true est d'activer les annotations @PreAuthorize et @PostAuthorize de Spring Security.

Le rôle de secureEnabled = true est d'activer l'annotation @Secured de Spring Security.

La fonction de jsr250Enabled = true est d'activer l'annotation @RoleAllowed

Pour une utilisation et une intégration plus détaillées, veuillez vous référer à mes deux articles
Facile à utiliser SpringBoot + SpringSecurity + JWT Real RESTfulAPI permission control combat

Acquisition de l'autorité utilisateur de l'interface principale de Spring Security, principe d'exécution du processus d'authentification

Définir l'authentification d'autorisation sur la méthode

Annotations JSR-250

Conforme aux annotations de la norme JSR-250
Principales annotations

  1. @Nier tous
  2. @RolesAllowed
  3. @PermitAll

Ici @DenyAllet @PermitAllcrois inutile de dire, représentent le rejet et l'approbation.

@RolesAllowedExemple d'utilisation

@RolesAllowed("ROLE_VIEWER")
public String getUsername2() {
    
    
    //...
}
     
@RolesAllowed({
    
     "USER", "ADMIN" })
public boolean isValidUsername2(String username) {
    
    
    //...
}

Les méthodes représentant les annotations sont accessibles tant qu'elles disposent des autorisations USER, ADMIN. Le préfixe ROLE_ peut être omis ici, et l'autorité réelle peut être ROLE_ADMIN

En termes de fonction et d'utilisation, c'est @Securedexactement la même chose que

Annotation sécurisée activée

note principale

@Sécurisé

  1. Annotations pour Spring Security @Secured. L'annotation spécifie la liste des rôles de la méthode d'accès, et au moins un rôle est spécifié dans la liste

  2. @SecuredSpécifiez la sécurité sur la méthode, nécessitant des rôles/autorisations, etc. Seuls les utilisateurs disposant des rôles/autorisations correspondants peuvent appeler ces méthodes. Si quelqu'un essaie d'appeler une méthode, mais ne dispose pas des rôles/autorisations requis, une exception Accès refusé sera levée.

Par exemple:

@Secured("ROLE_VIEWER")
public String getUsername() {
    
    
    SecurityContext securityContext = SecurityContextHolder.getContext();
    return securityContext.getAuthentication().getName();
}

@Secured({
    
     "ROLE_DBA", "ROLE_ADMIN" })
public String getUsername2() {
    
    
    //...
}

@Secured("ROLE_VIEWER")Indique que seuls ROLE_VIEWERles utilisateurs disposant du rôle peuvent accéder getUsername()à la méthode.

@Secured({ "ROLE_DBA", "ROLE_ADMIN" })Indique que l'utilisateur a " ROLE_DBA", "ROLE_ADMIN"l'un des deux rôles et peut accéder getUsername2à la méthode.

Un autre point est que @Secured ne prend pas en charge les expressions Spring EL

annotation prePostEnabled

Une fois activé, il est assez puissant pour prendre en charge les expressions Spring EL. Une AccessDeniedException est levée s'il n'y a pas d'autorisation d'accéder à la méthode.

note principale

  1. @PreAuthorize-- Convient pour valider l'autorisation avant d'entrer dans la méthode

  2. @PostAuthorize-- Vérifiez la méthode d'autorisation avant son exécution et peut affecter la valeur de retour de la méthode d'exécution

3. @PostFilter--Exécuter après l'exécution de la méthode, et ici vous pouvez appeler la valeur de retour de la méthode, puis filtrer ou traiter ou modifier la valeur de retour et retourner

  1. @PreFilter-- Exécuter avant que la méthode ne soit exécutée, et ici vous pouvez appeler les paramètres de la méthode, puis filtrer ou traiter ou modifier les valeurs des paramètres

Utilisation des annotations @PreAuthorize

@PreAuthorize("hasRole('ROLE_VIEWER')")
public String getUsernameInUpperCase() {
    
    
    return getUsername().toUpperCase();
}

@PreAuthorize("hasRole('ROLE_VIEWER')") est équivalent à @Secured("ROLE_VIEWER").

Le même @Secured({“ROLE_VIEWER”,”ROLE_EDITOR”})peut également être remplacé par : @PreAuthorize(“hasRole(‘ROLE_VIEWER') or hasRole(‘ROLE_EDITOR')”).

De plus, nous pouvons utiliser des expressions sur les paramètres de méthode :

Exécuté avant l'exécution de la méthode, ici vous pouvez appeler les paramètres de la méthode, et vous pouvez également obtenir la valeur du paramètre. Ici, la fonction de réflexion du nom du paramètre de JAVA8 est utilisée. S'il n'y a pas de JAVA8, vous pouvez également utiliser Spring @P de Security pour marquer les paramètres, ou utilisez @ Param de Spring Data pour marquer les paramètres.

//无java8
@PreAuthorize("#userId == authentication.principal.userId or hasAuthority(‘ADMIN’)")
void changePassword(@P("userId") long userId ){
    
    }
//有java8
@PreAuthorize("#userId == authentication.principal.userId or hasAuthority(‘ADMIN’)")
void changePassword(long userId ){
    
    }

Cela signifie changePasswordqu'avant l'exécution de la méthode, il est jugé si la valeur du paramètre de méthode userId est égale à l'userId de l'utilisateur courant enregistré dans le principal, ou si l'utilisateur courant a l'autorité ROLE_ADMIN, et si l'un des deux correspondances, la méthode est accessible.

Utilisation des annotations @PostAuthorize

Une fois la méthode exécutée, la valeur de retour de la méthode peut être obtenue et le résultat final de l'autorisation peut être déterminé en fonction de la méthode (autoriser ou non l'accès) :

@PostAuthorize
  ("returnObject.username == authentication.principal.nickName")
public CustomUser loadUserDetail(String username) {
    
    
    return userRoleRepository.loadUserByUserName(username);
}

loadUserDetailDans le code ci-dessus, l'accès est autorisé uniquement lorsque le nom d'utilisateur dans la valeur de retour de la méthode est le même que le nom d'utilisateur de l'utilisateur actuellement connecté

Notez que si EL est faux, la méthode a également été exécutée et peut être annulée. La variable EL returnObject représente l'objet renvoyé.

Les annotations @PreFilter et @PostFilter sont utilisées

Spring Security fournit une @PreFilterannotation pour filtrer les paramètres entrants :

@PreFilter("filterObject != authentication.principal.username")
public String joinUsernames(List<String> usernames) {
    return usernames.stream().collect(Collectors.joining(";"));
}

Lorsque le sous-élément dans les noms d'utilisateur est différent du nom d'utilisateur de l'utilisateur actuellement connecté, conservez-le ; lorsque le sous-élément dans les noms d'utilisateur est le même que le nom d'utilisateur de l'utilisateur actuellement connecté, supprimez-le. Par exemple, le nom d'utilisateur de l'utilisateur actuel est zhangsan, et la valeur des noms d'utilisateur à ce moment est {"zhangsan", "lisi", "wangwu"}, après filtrage par @PreFilter, la valeur des noms d'utilisateur réellement transmis est{"lisi", "wangwu"}

Si la méthode d'exécution contient plusieurs paramètres de type Collection, filterObject ne saura pas quel paramètre Collection filtrer. À ce stade, vous devez ajouter l'attribut filterTarget pour spécifier le nom de paramètre spécifique :

@PreFilter
  (value = "filterObject != authentication.principal.username",
  filterTarget = "usernames")
public String joinUsernamesAndRoles(
  List<String> usernames, List<String> roles) {
    
    
  
    return usernames.stream().collect(Collectors.joining(";")) 
      + ":" + roles.stream().collect(Collectors.joining(";"));
}

De même, nous pouvons également utiliser la Collection qui @PostFiltera été annotée 返回pour filtrer :

@PostFilter("filterObject != authentication.principal.username")
public List<String> getAllUsernamesExceptCurrent() {
    
    
    return userRoleRepository.getAllUsernames();
}

À ce stade, filterObject représente la valeur de retour. Si le code ci-dessus est suivi, il sera réalisé : supprimez le sous-élément dans la valeur de retour qui est identique au nom d'utilisateur de l'utilisateur actuellement connecté.

Méta-annotations personnalisées

Si nous devons utiliser la même annotation de sécurité dans plusieurs méthodes, nous pouvons améliorer la maintenabilité du projet en créant des méta-annotations.

Par exemple, créez les méta-annotations suivantes :

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@PreAuthorize("hasRole('ROLE_VIEWER')")
public @interface IsViewer {
    
    
}

Ensuite, vous pouvez ajouter directement l'annotation à la méthode correspondante :

@IsViewer
public String getUsername4() {
    
    
    //...
}

Dans les projets de production, étant donné que les méta-annotations séparent la logique métier et le cadre de sécurité, l'utilisation de méta-annotations est un très bon choix.

Utiliser des annotations de sécurité sur les classes

Si toutes les méthodes d'une classe sont toutes appliquées avec la même annotation de sécurité, l'annotation de sécurité doit alors être élevée au niveau de la classe :

@Service
@PreAuthorize("hasRole('ROLE_ADMIN')")
public class SystemService {
    
    
  
    public String getSystemYear(){
    
    
        //...
    }
  
    public String getSystemDate(){
    
    
        //...
    }
}

Le code ci-dessus réalise que l'autorisation ROLE_ADMIN est requise pour accéder aux méthodes getSystemYear et getSystemDate.

Appliquer plusieurs annotations de sécurité aux méthodes

Lorsqu'une annotation de sécurité ne peut pas répondre à nos besoins, plusieurs annotations de sécurité peuvent également être appliquées :

@PreAuthorize("#username == authentication.principal.username")
@PostAuthorize("returnObject.username == authentication.principal.nickName")
public CustomUser securedLoadUserDetail(String username) {
    
    
    return userRoleRepository.loadUserByUserName(username);
}

À ce moment, Spring Security exécutera la politique de sécurité de @PreAuthorize avant d'exécuter la méthode et exécutera la politique de sécurité de @PostAuthorize après avoir exécuté la méthode.

Résumer

D'après notre expérience, voici deux conseils :

  1. Par défaut, l'utilisation des annotations de sécurité dans les méthodes est implémentée par le proxy Spring AOP, ce qui signifie : si nous appelons la méthode 2 dans la même classe qui utilise les annotations de sécurité dans la méthode 1, les annotations de sécurité sur la méthode 2 seront invalides.

  2. Le contexte Spring Security est lié aux threads, ce qui signifie que le contexte de sécurité ne sera pas transmis aux threads enfants.

public boolean isValidUsername4(String username) {
    
    
    // 以下的方法将会跳过安全认证
    this.getUsername();
    return true;
}

Je suppose que tu aimes

Origine blog.csdn.net/u011738045/article/details/120528417
conseillé
Classement