Le tutoriel le plus simple et le plus complet de Spring Security (avec démo)

1. Introduction à Spring Security

Spring Security est un cadre de sécurité qui fournit une protection de sécurité déclarative pour les applications basées sur Spring. Il fournit une solution de sécurité complète qui gère la vérification d'identité et l'autorisation au niveau de la demande Web et au niveau de l'invocation de méthode. Parce qu'il est basé sur le framework Spring, Spring Security utilise pleinement l'injection de dépendances et les technologies orientées aspect.

Spring Security résout principalement les problèmes de sécurité sous deux aspects :

  1. Niveau de requête Web : utilisez les filtres de la spécification Servlet pour protéger les requêtes Web et restreindre l'accès au niveau de l'URL.

  2. Niveau d'invocation de méthode : utilisez Spring AOP pour protéger les invocations de méthode, en vous assurant que seuls les utilisateurs disposant des autorisations appropriées peuvent accéder aux méthodes sécurisées.

Si vous souhaitez avoir une compréhension approfondie des concepts connexes et des principes de mise en œuvre de Spring Security, vous pouvez cliquer sur le portail == " Principes de base de Spring Security

Deuxièmement, la démonstration de sécurité au niveau des requêtes Web de Spring Security

1. Créez un nouveau projet Spring et ajoutez des dépendances springsecurity au fichier pom.

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. Créer une classe de configuration pour Spring Security

package com.spring.security.springsecurity.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity  //启用Web安全功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                //访问"/"和"/home"路径的请求都允许
                .antMatchers("/", "/home","/staff","/staff/*")
                .permitAll()
                //而其他的请求都需要认证
                .anyRequest()
                .authenticated()
                .and()
                //修改Spring Security默认的登陆界面
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        //基于内存来存储用户信息
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("user").password(new BCryptPasswordEncoder().encode("123")).roles("USER").and()
                .withUser("admin").password(new BCryptPasswordEncoder().encode("456")).roles("USER","ADMIN");
    }
}

Analyse de code :

Annotation @EnableWebSecurity : Activer la fonction de sécurité Web (mais elle est inutile en soi, la classe de configuration Spring Security doit également implémenter WebSecurityConfigurer ou hériter de la classe WebSecurityConfigurerAdapter, cette dernière est utilisée dans cette démo, car elle est plus facile à configurer et à utiliser).

Annotation @EnableWebMvcSecurity : obsolète dans Spring 4.0.

Classe WebSecurityConfigurerAdapter : vous pouvez spécifier les détails de la sécurité Web en surchargeant les trois méthodes configure() de cette classe.

1. configure(WebSecurity) : en surchargeant cette méthode, la chaîne de filtrage de Spring Security peut être configurée.

2. configure(HttpSecurity) : en remplaçant cette méthode, vous pouvez configurer la manière de protéger les requêtes via des intercepteurs.

Comment configurer le chemin de protection

méthode

peut faire

accès(chaîne)

Autorise l'accès si l'expression SpEL donnée est évaluée à true

anonyme()

Autoriser l'accès des utilisateurs anonymes

authentifié()

Autoriser les utilisateurs authentifiés à accéder

Nier tous ()

Refuser inconditionnellement tout accès

entièrement authentifié ()

Si l'utilisateur est entièrement authentifié (non authentifié par la fonction Remember-me), l'accès est autorisé

hasAnyAuthority(chaîne…)

Autoriser l'accès si l'utilisateur dispose de l'une des autorisations accordées

aUnRôle(Chaîne…)

Autoriser l'accès si l'utilisateur a l'un des rôles donnés

aAutorité(chaîne)

Autoriser l'accès si l'utilisateur a l'autorisation donnée

hasIpAddress (chaîne)

Autoriser l'accès si la demande provient de l'adresse IP donnée

aRôle(Chaîne)

Autoriser l'accès si l'utilisateur a le rôle donné

ne pas()

Annuler les résultats des autres méthodes d'accès

autorise tout()

accès inconditionnel

souviens-toi de moi()

Autoriser l'accès si l'utilisateur est authentifié par la fonction Se souvenir de moi

Toutes les expressions SpEL prises en charge par Spring Security sont les suivantes :

expression sûre

Résultats des calculs

authentification

Objet d'authentification de l'utilisateur

Nier tous

le résultat est toujours faux

hasAnyRole(liste des rôles)

true si l'utilisateur dispose de l'une des autorisations spécifiées

aRôle(rôle)

true si l'utilisateur a reçu l'autorisation spécifiée

hasIpAddress (adresse IP)

Adresse de l'utilisateur

estAnonyme()

Est-ce un utilisateur anonyme

est authentifié()

pas un utilisateur anonyme

est entièrement authentifié

Authentification non anonyme ni souvenir de moi

estRemembreMoi()

certification souvenir de moi

autorise tout

toujours vrai

principal

Objet d'information principal de l'utilisateur

3. configure(AuthenticationManagerBuilder) : en surchargeant cette méthode, le service user-detail (détails de l'utilisateur) peut être configuré.

Comment configurer les détails de l'utilisateur

méthode

décris

compteExpiré(booléen)

Définit si le compte a expiré

compte verrouillé (booléen)

Définit si le compte est verrouillé

et()

pour la configuration de la connexion

autorités (GrantedAuthority…)

Accorder une ou plusieurs autorisations à un utilisateur

autorités (Liste)

Accorder une ou plusieurs autorisations à un utilisateur

autorités (chaîne…)

Accorder une ou plusieurs autorisations à un utilisateur

informations d'identificationExpiré (booléen)

Définit si l'identifiant a expiré

désactivé (booléen)

Définit si le compte a été désactivé

mot de passe (chaîne)

Définir le mot de passe de l'utilisateur

rôles(chaîne…)

Attribuer un ou plusieurs rôles à un utilisateur

Il existe trois façons de stocker les informations utilisateur :

** 1. Utiliser le stockage utilisateur basé sur la mémoire : ** Grâce à inMemoryAuthentication()des méthodes, nous pouvons activer, configurer et remplir arbitrairement le stockage utilisateur basé sur la mémoire. Et, nous pouvons appeler withUser()la méthode pour ajouter un nouvel utilisateur au magasin d'utilisateurs en mémoire, le paramètre de cette méthode est username. withUser()La méthode renvoie UserDetailsManagerConfigurer.UserDetailsBuilder, qui fournit plusieurs méthodes pour configurer davantage l'utilisateur, y compris des méthodes pour définir le mot de passe de l'utilisateur password()et accorder une ou plusieurs autorisations de rôle pour un utilisateur donné roles(). Notez que la roles()méthode est authorities()un raccourci pour la méthode. roles()Les valeurs données à la méthode sont précédées d'un ROLE_préfixe et accordées à l'utilisateur en tant qu'autorisation. Par conséquent, l'autorité de l'utilisateur du code d'appel est la suivante : ROLE_USER,ROLE_ADMIN。而à l'aide de la passwordEncoder()méthode permettant de spécifier un encodeur de mot de passe (encodeur), nous pouvons chiffrer et stocker le mot de passe de l'utilisateur.

**2. Authentification basée sur des tables de base de données : **Les données utilisateur sont généralement stockées dans une base de données relationnelle et accessibles via JDBC. Pour configurer Spring Security pour utiliser un magasin d'utilisateurs soutenu par JDBC, nous pouvons utiliser la jdbcAuthentication()méthode et configurer son DataSource afin que nous puissions accéder à la base de données relationnelle.

**3. Authentification basée sur LDAP : **Pour que Spring Security utilise l'authentification basée sur LDAP, nous pouvons utiliser la ldapAuthentication()méthode.

3. Code de couche contrôleur et code frontal

Le code SecurityController est le suivant :

package com.spring.security.springsecurity.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class SecurityController {

    @GetMapping(value = {"/home","/"})
    public String home(){
        return "home";
    }

    @GetMapping(value = "/hello")
    public String hello(){
        return "hello";
    }

    @GetMapping(value = "/login")
    public String login(){
        return "login";
    }
}

home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>

        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>

bonjour.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>
    </body>
</html>

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example </title>
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <form th:action="@{/login}" method="post">
            <div><label> User Name : <input type="text" name="username"/> </label></div>
            <div><label> Password: <input type="password" name="password"/> </label></div>
            <div><input type="submit" value="Sign In"/></div>
        </form>
    </body>
</html>

4. Résultats et analyse des opérations

Lorsque nous visitons localhost:8080/hello directement, la page saute à http://localhost:8080/login , c'est parce que la classe SecurityConfig configure uniquement les requêtes pour les chemins "/" et "/home" sans se connecter. , tandis que d'autres requêtes nécessitent une authentification. (Remarque : j'ai changé le port ici en 8081 parce que j'ai fait des ajustements. Vous pouvez accéder au port 8080 comme d'habitude.)

À ce stade, nous entrons dans l'interface de connexion, nous configurons le nom d'utilisateur et le mot de passe en fonction du stockage en mémoire dans SecurityConfig, et nous allons passer avec succès à l'interface hello

Troisièmement, la démo de sécurité au niveau de l'invocation de méthode de Spring Security

Spring Security fournit trois annotations de sécurité différentes :

  • La propre annotation @Secured de Spring Security ;
  • Annotation @RolesAllowed de JSR-250 ;
  • Annotations basées sur des expressions, notamment @PreAuthorize, @PostAuthorize, @PreFilter et @PostFilter.

annotation

décris

@PreAuthorize

Restreindre l'accès aux méthodes en fonction de l'évaluation des expressions avant l'invocation de la méthode

@PostAuthorize

L'invocation de la méthode est autorisée, mais une exception de sécurité sera levée si l'expression est évaluée à false

@PostFilter

L'invocation de la méthode est autorisée, mais le résultat de la méthode doit être filtré par expression

@PreFilter

Les appels de méthode sont autorisés, mais les valeurs d'entrée doivent être filtrées avant d'entrer dans la méthode

1. Activer la sécurité des méthodes basées sur les annotations

Dans Spring, si vous souhaitez activer la sécurité des méthodes basées sur les annotations, la clé consiste à utiliser @EnableGlobalMethodSecurity sur la classe de configuration, par exemple :

package com.spring.security.springsecurity.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

}

Ici, nous définissons secureEnabled = true, puis Spring créera un point de coupure et empêchera les méthodes annotées avec @Secured d'entrer dans l'aspect. De même, jsr250Enabled = true et prePostEnabled = true, activent respectivement @RolesAllowed et les annotations basées sur l'expression.

Après avoir configuré la classe MethodSecurityConfig à ce stade, nous pouvons ajouter une méthode au SecurityController basée sur le code d'appel :

    @GetMapping(value = "/admin")
    @Secured("ROLE_ADMIN")
    public String admin(){
        return "admin";
    }

L'interface admin.html est la suivante :

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>admin</title>
</head>
<body>
    <h1>admin page</h1>
</body>
</html>

À ce stade, comment accéder au chemin http://localhost:8081/admin en tant qu'utilisateur user, et une erreur 403 se produira.

Si vous accédez au chemin http://localhost:8081/admin en tant qu'utilisateur admin, l'interface suivante s'affichera, indiquant un accès réussi.

Je suppose que tu aimes

Origine blog.csdn.net/m0_54850467/article/details/123683180
conseillé
Classement