Expliquez les bases du fonctionnement de Spring Security à travers un bref Hello World
――Quels types de classes fonctionnent ensemble et comment
En apprenant comment fonctionne Spring Security via Hello World
--Dispose d'une bonne connaissance de Servlet et JSP
Filter etc., vous pouvez écrire web.xml pour créer une application Servlet--Si vous utilisez la fonction de Servlet 3.0, vous pouvez la définir sans web.xml. ――Le but est d'apprendre les bases du mécanisme, alors ne l'utilisez pas non plus.
https://github.com/opengl-8080/spring-security-hello-world
-Téléchargez spring-security.war depuis ici
gradlew war à la racine de votre projet.--Déployez spring-security.war sur Tomcat
--Accès http: // localhost: 8080 / spring-security
Accédez à http: // localhost: 8080 / spring-security

Entrez foo dans User, Password pour vous connecter

Erreur 403
Ensuite, connectez-vous avec bar


La page d'index s'affiche.
Vous pouvez vous déconnecter en cliquant sur le bouton de déconnexion.
organisation des fichiers
|-build.gradle :Fichier de construction Gradle
|
`-src/main/webapp/
|
|-index.jsp :Sommaire
|
`-WEB-INF/
|
|-applicationContext.xml :Fichier de configuration Spring
|
`-web.xml :Fichier de configuration du servlet
--Tous les 4 fichiers ―― One est un fichier de construction, donc trois fichiers sont effectivement déployés.
build.gradle
apply plugin: 'war'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
compileJava.options.encoding = 'UTF-8'
repositories {
mavenCentral()
}
dependencies {
compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
}
war.baseName = 'spring-security'
task wrapper(type: Wrapper) {
gradleVersion = '3.2.1'
}
index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>
Hello Spring Security!!
</title>
</head>
<body>
<h1>
Hello Spring Security!!
</h1>
<form action="logout" method="post">
<input type="submit"
value="logout" />
<input type="hidden"
name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
</body>
</html>
--Page supérieure affichée après la connexion
_csrf est défini car il est activé par défaut, mais comme il n'apparaîtra pas dans l'explication suivante, une explication détaillée sera omise.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>
springSecurityFilterChain
</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>
springSecurityFilterChain
</filter-name>
<url-pattern>
/*
</url-pattern>
</filter-mapping>
</web-app>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<sec:http>
<sec:intercept-url
pattern="/login"
access="permitAll" />
<sec:intercept-url
pattern="/**"
access="isAuthenticated() and hasAuthority('BAR')" />
<sec:form-login />
<sec:logout />
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo"
password="foo"
authorities="" />
<sec:user name="bar"
password="bar"
authorities="BAR" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
web.xml
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>ContextLoaderListener
--Classe qui initialise le conteneur Spring
--Par défaut, XmlWebApplicationContext est utilisé
--WEB-INF / applicationContext.xml est utilisé comme fichier de configurationweb.xml
<filter>
<filter-name>
springSecurityFilterChain
</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>
springSecurityFilterChain
</filter-name>
<url-pattern>
/*
</url-pattern>
</filter-mapping>
DelegatingFilterProxy avec le nom springSecurityFilterChain
--Filter est une fonction fournie par Servlet/ * pour ʻurl-pattern` pour traiter toutes les requêtes
--DelegatingFilterProxy recherche dans le conteneur Spring les beans qui correspondent aux critères suivants:
springSecurityFilterChain)javax.servlet.FilterDelegatingFilterProxy a délégué le traitement est un bean obtenu à partir du conteneur Spring, les fonctions du conteneur Spring peuvent être utilisées.
DelegatingFilterProxy est de relier le conteneur Servlet et le conteneur Spring.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
...>
<sec:http>
<sec:intercept-url
pattern="/login"
access="permitAll" />
<sec:intercept-url
pattern="/**"
access="isAuthenticated() and hasAuthority('BAR')" />
<sec:form-login />
<sec:logout />
</sec:http>
...
--ʻApplicationContext.xmlest le fichier de configuration Spring --Définissez un bean en utilisant la balise
xmlns: sec<http> est la cléapplicationContext.xml
<sec:http>
...
</sec:http>
--Ce <http> est la clé pour configurer Spring Security
--Un grand nombre de grains importants sont enregistrés
FilterChainProxy
--Un des beans enregistrés par la balise <http>
--Hériter de l'interface Filter
springSecurityFilterChainDelegatingFilterProxy
ContextLoaderListener, qui est enregistré comme Listener dans web.xml, est exécuté.XmlWebApplicationContext est créée et / WEB-INF / applicationContext.xml est chargé.<http> enregistre une instance de FilterChainProxy avec le conteneur Spring avec le nom" "springSecurityFilterChain" .DelegateFilterProxy, qui est enregistré comme Filter dans web.xml, est généré par le conteneur de servlet.DelegateFilterProxy est appelé pour récupérer le bean du conteneur Spring avec son propre nom ("springSecurityFilterChain") ( FilterChainProxy est obtenu).FilterChainProxy.SecurityFilterChain
--Une des classes importantes que <http> enregistre
FilterChainProxy délègue la demande reçue aux Filters de SecurityFilterChainFiltre enregistré par défaut
SecurityContextPersistenceFilterCsrfFilterAnonymousAuthenticationFilterExceptionTranslationFilterFilterSecurityInterceptor
--Spring Security est réalisé par une combinaison de Filter
Filter est préparé pour chaque fonction, et vous pouvez activer / désactiver la fonction en enregistrant le Filter dans le SecurityFilterChain.
--SecurityFilterChain peut être défini pour chaque modèle d'URL
/ api / **, utilisez le jeu SecurityFilterChain pour l'API REST./ **), utilisez le jeu SecurityFilterChain pour un accès normal à l'écran.
--Peut être dit
--Par exemple, des fonctions telles que "Connexion par formulaire" ne sont plus nécessaires lors de l'accès avec l'API REST.Le fichier de configuration ressemble à ceci:
applicationContext.xml
<sec:http pattern="/api/**">
...
</sec:http>
<sec:http pattern="/**">
...
</sec:http>
--Spécifiez dans l'attribut pattern de la balise <http>
(Peut être spécifié au format Ant)
/ ** est supérieur à / api / **, l'accès à / api / ** correspondra d'abord au paramètre / **)--<http>enregistre SecurityFilterChain comme un bean
--SecurityFilterChain contient plusieursFilters
--Spring Security fournit un filtre pour chaque fonction
Filter, vous pouvez définir SecurityFilterChain avec seulement les fonctions nécessaires.SecurityFilterChain peut être défini pour chaque modèle d'URL,
--SecurityFilterChain pour l'API REST
--SecurityFilterChain pour un accès normal à l'écran
Peut être mis en place
applicationContext.xml
<sec:http>
...
<sec:form-login />
...
</sec:http>
Filtre requis pour la connexion par formulaire est ajouté à SecurityFilterChain
--Si l'attribut «login-page» de «/ login
Filter appelé ʻUsernamePasswordAuthenticationFilter`/ login, le processus d'authentification démarre.
Veuillez noter que beaucoup de "délégation" sort d'ici et c'est déroutant! </ span>
AuthenticationManager
applicationContext.xml
<sec:authentication-manager> ★
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" ... />
<sec:user name="bar" ... />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<authentication-manager>, ProviderManager, qui est une classe d'implémentation de ʻAuthenticationManager, est enregistré dans le conteneur Spring. --Classe qui est l'entrée du processus d'authentification --Cependant, ProviderManager lui-même n'effectue pas de traitement d'authentification et ** délègue ** à ʻAuthenticationProvider.

--ʻAuthenticationProvider a de nombreuses classes d'implémentation pour chaque type d'authentification --ProviderManager contient plusieurs instances de ʻAuthenticationProvider selon la méthode d'authentification prise en charge par l'application.
--Chaque ʻAuthenticationProvider est fait pour juger si la demande d'authentification actuelle est prise en charge, et si elle est prise en charge, le processus d'authentification est effectué par ʻAuthenticationProvider.
--ProviderManager est responsable de la gestion de plusieurs ʻAuthenticationProvider ensemble (exactement ProviderManager`).
applicationContext.xml
<sec:authentication-manager>
<sec:authentication-provider> ★
<sec:user-service>
<sec:user name="foo" ... />
<sec:user name="bar" ... />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<authentication-provider>, une classe appelée DaoAuthenticationProvider est enregistrée comme une implémentation de ʻAuthenticationProvider. --DaoAuthenticationProvider` effectue le traitement d'authentification en utilisant une combinaison de nom d'utilisateur et de mot de passe.
UserDetailsService
UserDetailsService
public interface UserDetailsService {
UserDetails
loadUserByUsername(String username)
throws UsernameNotFoundException;
}
--Dispose d'une méthode qui renvoie les informations utilisateur (ʻUserDetails`) en fonction du nom d'utilisateur
InMemoryUserDetailsManager Implémentation pour enregistrer les informations utilisateur en mémoire
JdbcUserDetailsManager Implémentation qui récupère les informations utilisateur de la base de données via JDBC
applicationContext.xml
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service> ★
<sec:user name="foo" ... />
<sec:user name="bar" ... />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
<user-service> entraîne l'enregistrement de ʻInMemoryUserDetailsManager dans le conteneur Spring en tant qu'implémentation de ʻUserDetailsService.UserDetails
UserDetails.java
public interface UserDetails extends Serializable {
String getUsername();
String getPassword();
Collection<? extends GrantedAuthority>
getAuthorities();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
--ʻUserDetails` est une interface qui fournit des informations détaillées sur l'utilisateur connecté.
applicationContext.xml
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" ... /> ★
<sec:user name="bar" ... /> ★
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
--Lors de l'utilisation de la balise <user>, les informations utilisateur sont générées à l'aide de la classe ʻUser`.
<user-service>, c'est-à-dire ʻInMemoryUserDetailsManager`.
/ login, ʻUsernamePasswordAuthenticationFilter` effectue le processus d'authentification.ProviderManager, qui est une classe d'implémentation de ʻAuthenticationManager, délègue le processus d'authentification à son propre ʻAuthenticationProvider.DaoAuthenticationProvider enregistré avec la balise <authentication-provider> effectue un traitement d'authentification basé sur le nom d'utilisateur et le mot de passe. enregistré avec la balise stocke les informations utilisateur (ʻUserDetails) définies avec la balise <user> en mémoire.Les relations ci-dessus sont incluses dans les paramètres ci-dessous.
applicationContext.xml
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo" ... />
<sec:user name="bar" ... />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
AuthenticationProvider.java
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
réussit, l'objet ʻAuthentication qui contient les informations de l'utilisateur connecté est renvoyé.
--Cet objet ʻAuthentication` est enregistré dans la session et sera référencé dans les futures requêtes, etc.--<form-login>active l'authentification par formulaire
--ʻUsernamePasswordAuthenticationFilter est ajouté et le processus d'authentification démarre --ʻAuthenticationManager contrôle le processus d'authentification
--ʻAuthenticationProvider effectue un processus d'authentification spécifique --ʻUserDetailsService récupère les informations utilisateur Dao
--ʻUserDetails` fournit des informations détaillées sur l'utilisateur
FilterSecurityInterceptor
Filters importants ajoutés en définissant la balise <http>
--- Insérez le processus avant et après l'exécution du processus de ** Secure Object **FilterSecurityInterceptor
--FilterSecurityInterceptor lui-même ne vérifie pas le contrôle d'accès

fournie par Spring Security contrôle l'accès par "** vote **". --ʻAccessDecisionManager laisse ʻAccessDecisionVoter` voter pour l'accès
--ʻAccessDecisionManager` a trois classes d'implémentation
AffirmativeBased
--Accessible s'il y a même une "subvention"
--Cette classe est utilisée par défautConsensusBased
--Accessible si "Rejeter" <"Donner"UnanimousBased
--Accessible si tous sont "accordés"applicationContext.xml
<sec:http>
<sec:intercept-url
pattern="/login"
access="permitAll" />
<sec:intercept-url
pattern="/**"
access="isAuthenticated() and hasAuthority('BAR')" />
...
</sec:http>
--ʻWebExpressionVoter est utilisé par défaut pour implémenter AccessDecisionVoter
--ʻExpression` C'est-à-dire contrôler l'accessibilité en fonction d'expressions
de la balise pattern spécifie le modèle de l'URL à laquelle le contrôle s'applique.Spring Expression Language (SpEL)
applicationContext.xml
access="permitAll"
access="isAuthenticated() and hasAuthority('BAR')"
--Utilisez le propre langage d'expression de Spring appelé Spring Expression Language pour les expressions de contrôle d'accès
--Assurez-vous que le résultat de l'évaluation de l'expression est booléen
--Si true, accessible </ font>
--Si false, inaccessible </ font>
permitAll: Toujours vrai
--ʻIsAuthenticated () : true si authentifié --hasAuthority () : true` si vous avez l'autorité spécifiéeFilterSecurityInterceptor, et ʻAccessDecisionManager agrège les résultats du vote et tire une conclusion.WebExpressionVoter est activé.applicationContext.xml
<sec:http>
...
<sec:logout />
</sec:http>
--Utiliser la balise <logout> ajoute un LogoutFilter
/ logout, LogoutFilter gère la déconnexion.



web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<filter>
<filter-name>
springSecurityFilterChain
</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>
springSecurityFilterChain
</filter-name>
<url-pattern>
/*
</url-pattern>
</filter-mapping>
</web-app>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
...>
<sec:http>
<sec:intercept-url
pattern="/login"
access="permitAll" />
<sec:intercept-url
pattern="/**"
access="isAuthenticated() and hasAuthority('BAR')" />
<sec:form-login />
<sec:logout />
</sec:http>
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="foo"
password="foo"
authorities="" />
<sec:user name="bar"
password="bar"
authorities="BAR" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
</beans>
Recommended Posts