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.Filter
DelegatingFilterProxy
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
springSecurityFilterChain
DelegatingFilterProxy
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 Filter
s de SecurityFilterChain
Filtre
enregistré par défaut
SecurityContextPersistenceFilter
CsrfFilter
AnonymousAuthenticationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
--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 plusieursFilter
s
--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 placeapplicationContext.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
Filter
s 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