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 :
-
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.
-
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.