[JAVA] Avec Spring Boot, hachez le mot de passe et utilisez l'enregistrement des membres et la sécurité Spring pour implémenter la fonction de connexion.

Aperçu

Présentation de la mise en œuvre de l'authentification des utilisateurs à l'aide de la sécurité Spring. Tout d'abord, après avoir expliqué comment hacher le mot de passe et vous inscrire en tant que nouveau membre, Nous allons vous montrer comment authentifier les utilisateurs à l'aide de la sécurité Spring.

Cette fois, nous avons confirmé l'opération dans l'environnement suivant.

DB

Créer une table pour stocker les noms d'utilisateur et les mots de passe

Tout d'abord, créez une table pour stocker votre nom d'utilisateur et votre mot de passe. Cette fois, nous allons créer une table USER avec le nom d'utilisateur (NAME), le mot de passe (PASSWORD) et l'ID sous forme de colonnes. Exécutez l'instruction SQL suivante pour créer la table USER.

CREATE TABLE USER(ID INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(64) NOT NULL, PASSWORD VARCHAR(64) NOT NULL);

L'important ici est de définir le nombre de caractères dans MOT DE PASSE à 60 ou plus. Le mot de passe est haché et enregistré dans la base de données, mais si le mot de passe est haché avec BCryptPasswordEncoder utilisé dans ce hachage, le nombre de caractères sera de 60 caractères, donc au moins 60 caractères sont requis pour la colonne de mot de passe cette fois.

Préparation de la sécurité du printemps

Ajout de la dépendance de sécurité Spring

Tout d'abord, injectez les dépendances de sécurité Spring pour utiliser la sécurité Spring. Ajoutez la dépendance suivante à Pom.xml.

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

L'injection d'une dépendance de sécurité Spring fera apparaître l'écran de connexion par défaut de la sécurité Spring lorsque vous lancerez l'application. À ce stade, l'écran de connexion par défaut suivant s'affiche. スクリーンショット 2018-12-30 23.27.10.png

Maintenant, affichons l'écran de connexion que vous avez créé dans la section suivante.

Faites afficher l'écran de connexion que vous avez créé

Ici, créez un écran de connexion, créez un contrôleur et créez WebSecurityConfig.java.

Tout d'abord, créez un écran de connexion.

Login.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>S'identifier</title>
</head>
<body>
<form th:action="/" method="POST">

    <table align="center">
        <tr>
            <td>
Nom d'utilisateur:
            </td>
            <td>
                <input type="text" id="user" name="user"/>
            </td>
        </tr>
        <tr>
            <td>
mot de passe:
            </td>
            <td>
                <input type="password" id="password" name="password"/>
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td align="right">
                <button type="submit">S'identifier</button>
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td align="right">
                <a href="/RegistrationForm">s'inscrire</a>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

Ensuite, créez un contrôleur.

LoginController.java


import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LoginController {

	@RequestMapping("/login")
	public String showLoginForm(Model model) {

		//Transition vers l'écran de connexion.
		return "Login";
	}
}

Ensuite, configurez avec java config. Créez une classe WebSecurityConfig pour la configuration. Cette classe hérite de WebSecurityConfigurerAdapter.

WebSecurityConfig.java


import org.springframework.context.annotation.Configuration;
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;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//Spécifiez la page de connexion.
		//Tous les accès à la page de connexion sont autorisés.
		http.formLogin()
	        .loginPage("/login")
		    .permitAll();

		http.authorizeRequests()
			.anyRequest().authenticated();
	}
}

Dans loginPage (), spécifiez le chemin spécifié dans RequestMapping de la méthode showLoginForm () de la classe LoginController. En appelant permitAll (), vous pouvez accéder à la page de connexion même si vous n'êtes pas authentifié. Appelez anyRequest (). Authenticated () pour authentifier toutes les requêtes.

Lorsque vous avez terminé cette étape, l'écran de connexion que vous avez créé s'affiche comme indiqué ci-dessous. スクリーンショット 2019-01-06 18.42.06.png

Ensuite, nous mettrons en œuvre la fonction d'enregistrement des membres.

Mettre en œuvre la fonction d'inscription des membres

Hachez le mot de passe et enregistrez-le dans la base de données.

Ce chapitre décrit comment hacher le mot de passe et l'enregistrer dans la base de données. Cependant, comment créer un formulaire d'inscription d'adhésion et comment recevoir la valeur d'entrée du formulaire sont les mêmes que lorsque le mot de passe n'est pas haché, je vais donc l'omettre. Cette section se concentre sur la façon de hacher les mots de passe. Si vous voulez voir tout le code source, veuillez consulter github pour le code source.

Cette fois, BCryptPasswordEncoder est utilisé comme méthode de hachage. Ici, la classe PassswordEncoder est incluse dans deux packages, org.springframework.security.crypto.password et org.springframework.security.authentiction.encoding, mais ce dernier est obsolète, donc le premier J'utiliserai celui-là. Tout d'abord, ajoutez BCryptPasswordEncoder au bean avec java config.

WebSecurityConfig.java


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//Spécifiez la page de connexion.
		//Tous les accès à la page de connexion sont autorisés.
		http.formLogin()
			.loginPage("/login")
			.permitAll();

		http.authorizeRequests()
			.anyRequest().authenticated();
	}

	@Bean
	PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
}

Cette fois, les informations sur le membre sont insérées dans la base de données en définissant le mot de passe et le nom d'utilisateur dans les arguments de la méthode insertMemberInfo () de l'interface de mappage créée et en l'appelant. Hachez le mot de passe saisi dans le formulaire avant d'appeler la méthode insertMemberInfo ().

RegisterMemberService.java


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.webapp.certificationtest.mapper.RegisterMemberMapper;

@Service
@Transactional
public class RegisterMemberService {

	@Autowired
	RegisterMemberMapper registerMemberMapper;

	@Autowired
	PasswordEncoder passwordEncoder;

	/**
	 *Enregistrez les informations des membres dans DB.
	 */
	public void registerMember(MemberRegistrationEntity entity) {

		//Hash le mot de passe et insérezMemberInfo()Défini sur l'objet à passer.
		entity.setPassword(passwordEncoder.encode(entity.getPassword()));

		registMemberMapper.insertMemberInfo(entity);
	}
}

Ici, nous déclarons d'abord PasswordEncoder avec @ </ span> Autowired. Ensuite, après avoir appelé encode () de PasswordEncoder pour hacher le mot de passe, insérez le mot de passe dans la base de données.

Authentifier les utilisateurs à l'aide de la sécurité Spring

Ajouter des paramètres avec WebSecurityConfig

Tout d'abord, ajoutez-le à WebSecurityConfig.java.

WebSecurityConfig.java



import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//Spécifiez la page de connexion.
		//Tous les accès à la page de connexion sont autorisés.
		http.formLogin()
			.loginPage("/login")
			.loginProcessingUrl("/authenticate")
			.usernameParameter("userName")
			.passwordParameter("password")
			.defaultSuccessUrl("/")
			.permitAll();

        //Ajouté lorsque la fonction d'enregistrement des membres est implémentée
		http.authorizeRequests()
			.antMatchers("/RegistrationForm").permitAll()
			.antMatchers("/Register").permitAll()
			.antMatchers("/Result").permitAll()
			.anyRequest().authenticated();
	}

	@Bean
	PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
}

Spécifiez l'URL à déplacer vers le processus d'authentification avec loginProcessingUrl (). Assurez-vous que cette URL correspond à la valeur de l'attribut action de la balise form du formulaire de connexion. Dans usernameParameter (), spécifiez la valeur de l'attribut name de la balise d'entrée qui place le nom d'utilisateur en html. Dans passwordParameter (), spécifiez la valeur de l'attribut name de la balise d'entrée qui place le mot de passe en html. Spécifie l'URL de la page vers laquelle accéder si la connexion réussit avec defaultSuccessUrl ().

Ensuite, modifiez l'action et saisissez le nom du formulaire dans Login.html.

Login.html


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>S'identifier</title>
</head>
<body>
<form th:action="/authenticate" method="POST">

    <table align="center">
        <tr>
            <td>
Nom d'utilisateur:
            </td>
            <td>
                <input type="text" id="user" name="userName"/>
            </td>
        </tr>
        <tr>
            <td>
mot de passe:
            </td>
            <td>
                <input type="password" id="password" name="password"/>
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td align="right">
                <button type="submit">S'identifier</button>
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td align="right">
                <a href="/RegistrationForm">s'inscrire</a>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

Ensuite, créez une classe pour mettre le nom d'utilisateur et le mot de passe obtenus à partir de la table USER.

Account.java


/**
 *Une classe qui stocke les informations de membre requises pour la connexion.
 */
public class Account {

	private String name;

	private String password;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

}

Ensuite, écrivez un mappeur qui obtient le nom d'utilisateur et le mot de passe de la table USER.

LoginMapper.java


import com.webapp.certificationtest.Account;

public interface LoginMapper {

	public Account findAccount(String name);
}

LoginMapper.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.webapp.certificationtest.mapper.LoginMapper">

    <select id="findAccount" resultType="com.webapp.certificationtest.Account"
                             parameterType="String">
        SELECT
           NAME,
           PASSWORD
        FROM
           USER
        WHERE
           NAME = #{userName}

    </select>

</mapper>

Ensuite, créez une classe pour stocker les informations utilisateur. Il hérite de la classe User.

DbUserDetails.java


import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;

public class DbUserDetails extends User {
	//Informations de l'utilisateur.
	private final Account account;

	public DbUserDetails(Account account,
			Collection<GrantedAuthority> authorities) {

		super(account.getName(), account.getPassword(),
				true, true, true, true, authorities);

		this.account = account;
	}

	public Account getAccount() {
		return account;
	}

}

Le deuxième argument du constructeur de classe DbUserDetails donne une liste d'autorisations à accorder à l'utilisateur.

Ensuite, créez la classe Service. Cette classe Service obtient la valeur de la table User et génère des UserDetails. L'authentification est effectuée en faisant correspondre les informations saisies par l'utilisateur dans le formulaire de connexion avec les détails de l'utilisateur générés ici.

DbUserDetailsService.java


import java.util.Collection;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.webapp.certificationtest.mapper.LoginMapper;

@Service
public class DbUserDetailsService implements UserDetailsService {

	@Autowired
	LoginMapper loginMapper;

	@Override
	@Transactional(readOnly = true)
	public UserDetails loadUserByUsername(String mailAddress)
			throws UsernameNotFoundException {
		//Obtenez des informations utilisateur de DB.
		Account account = Optional.ofNullable(loginMapper.findOne(mailAddress))
				.orElseThrow(() -> new UsernameNotFoundException("User not found."));

		return new DbUserDetails(account, getAuthorities(account));
	}

	/**
	 *Définissez la plage d'autorité donnée à cet utilisateur lorsque l'authentification est réussie.
	 * @compte param Informations utilisateur obtenues auprès de DB.
	 * @return Une liste de plages de privilèges.
	 */
	private Collection<GrantedAuthority> getAuthorities(Account account) {
		//Définissez la plage d'autorité donnée à l'utilisateur lorsque l'authentification est réussie.
		return AuthorityUtils.createAuthorityList("ROLE_USER");
	}

}

Si rien ne peut être extrait de la table User, lancez une UsernameNotFoundExceptionw. Dans l'argument UsernameNotFoundException, spécifiez le message lorsque le nom d'utilisateur n'existe pas dans la table User. Dans getAuthorities (), définissez les autorisations données à l'utilisateur obtenues à partir de la table User. Modifiez cette méthode si nécessaire. Si vous souhaitez donner plusieurs autorisations, ajoutez-les à l'argument de createAuthorityList () séparés par des virgules.

Ensuite, ajoutez à WebSecurityConfig.java pour l'authentification.

WebSecurityConfig.java


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	UserDetailsService userDetailsService;

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//Spécifiez la page de connexion.
		//Tous les accès à la page de connexion sont autorisés.
		http.formLogin()
			.loginPage("/login")
			.loginProcessingUrl("/authenticate")
			.usernameParameter("userName")
			.passwordParameter("password")
			.defaultSuccessUrl("/")
			.permitAll();

		http.csrf().disable().authorizeRequests()
			.antMatchers("/RegistrationForm").permitAll()
			.antMatchers("/Register").permitAll()
			.antMatchers("/Result").permitAll()
			.anyRequest().authenticated();
	}

	@Bean
	PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Autowired
	void configureAuthenticationManager(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService)
			.passwordEncoder(passwordEncoder());
	}
}

Enfin, ajoutez-le à LoginController.java.

LoginController.java


import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LoginController {

	/**
	 *Transit vers le formulaire de connexion.
	 */
	@RequestMapping("/login")
	public String showLoginForm(Model model) {

		//Transition vers l'écran de connexion.
		return "Login";
	}

	/**
	 *Accédez à la page principale.
	 *Si la connexion réussit, cette méthode sera appelée.
	 */
	@RequestMapping("/")
	public String login(Model model) {

		//Page d'accueil.
		return "index";
	}

}

Créez un écran à afficher après la connexion.

index.html


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Page d'accueil</title>
</head>
<body>
Ceci est la page principale.
</body>
</html>

Contrôle de fonctionnement

Vérifiez le fonctionnement.

Inscription des membres

Le premier est l'inscription des membres.

スクリーンショット 2019-01-06 18.42.06.png

Entrez votre nom d'utilisateur et votre mot de passe pour vous inscrire. スクリーンショット 2019-01-06 18.45.41.png

スクリーンショット 2019-01-06 18.30.41.png

Lorsque l'enregistrement de l'adhésion est terminé, le mot de passe est haché et inséré dans la base de données de cette manière. スクリーンショット 2019-01-06 18.31.55.png

S'identifier

Vient ensuite la connexion.

Entrez le nom d'utilisateur et le mot de passe que vous avez enregistrés précédemment. スクリーンショット 2019-01-06 18.46.52.png

J'ai pu me connecter et accéder à la page principale. スクリーンショット 2019-01-06 18.30.57.png

Le code source jusqu'à présent est répertorié sur github, donc si vous voulez les voir tous, veuillez le voir. Si vous avez des questions, n'hésitez pas à me contacter sur Twitter.

Recommended Posts

Avec Spring Boot, hachez le mot de passe et utilisez l'enregistrement des membres et la sécurité Spring pour implémenter la fonction de connexion.
Essayez d'implémenter la fonction de connexion avec Spring Boot
[Introduction à Spring Boot] Fonction d'authentification avec Spring Security
Fonction de connexion avec Spring Security
Implémentez la fonction de connexion simplement avec le nom et le mot de passe dans Rails (3)
Implémenter la fonction de pagination avec Spring Boot + Thymeleaf
Créez une fonction de connexion / déconnexion avec Spring Security selon le guide officiel de Spring [pour les débutants]
Mémo d'utilisation de Spring Security: coopération avec Spring MVC et Boot
Spring Boot avec les paramètres du filtre de sécurité Spring et les points addictifs
Implémentez une API Rest simple avec Spring Security avec Spring Boot 2.0
Tentative de SSR Vue.js avec Spring Boot et GraalJS
Comment implémenter le processus d'authentification en spécifiant le nom d'utilisateur et le mot de passe dans Spring Boot
Implémenter GraphQL avec Spring Boot
Implémenter l'API REST avec Spring Boot et JPA (Application Layer)
Implémenter l'API REST avec Spring Boot et JPA (couche d'infrastructure)
Implémentez la fonction de connexion dans Rails simplement avec le nom et le mot de passe (1)
Jusqu'à INSERT et SELECT sur Postgres avec botte de printemps et feuille de thym
Connectez-vous à la base de données avec spring boot + spring jpa et effectuez l'opération CRUD
Implémenter l'API REST avec Spring Boot et JPA (Domain Layer Edition)
Implémentez une API Rest simple avec Spring Security & JWT avec Spring Boot 2.0
J'ai essayé d'implémenter un client OAuth avec Spring Boot / Security (connexion LINE)
Partie 1: Essayez d'utiliser la connexion OAuth 2.0 prise en charge par Spring Security 5 avec Spring Boot
Mise en œuvre de la fonction d'authentification avec Spring Security ②
Implémentez la fonction d'authentification avec Spring Security ③
Mise en œuvre de la fonction d'authentification avec Spring Security ①
Implémentez la connexion, l'enregistrement des utilisateurs et l'authentification à deux facteurs avec Docker x Laravel 8 Jetstream
J'ai utilisé Docker pour solidifier le modèle à développer avec Spring Boot.
"Professeur, je souhaite implémenter une fonction de connexion au printemps" ① Hello World
HTTPS avec Spring Boot et Let's Encrypt
Fonction d'authentification avec Play Framework [Enregistrement et authentification]
Comment implémenter TextInputLayout avec la fonction de validation
Implémenter CRUD avec Spring Boot + Thymeleaf + MySQL
Implémentation de la fonction de connexion par Spring Security (securityConfig)
Ajoutez une botte de printemps et un dégradé à éclipse
Obtenez une authentification BASIC avec Spring Boot + Spring Security
Hash des mots de passe avec Spring Boot + Spring Security (avec sel, avec étirement)
Comment utiliser MyBatis2 (iBatis) avec Spring Boot 1.4 (Spring 4)
Comment utiliser h2db intégré avec Spring Boot
Essayez l'authentification LDAP avec Spring Security (Spring Boot) + OpenLDAP
Essayez d'automatiser la migration avec Spring Boot Flyway
[Java] Article pour ajouter une validation avec Spring Boot 2.3.1.
Je voulais classer la botte à ressort dans un multi-projet
Créez un serveur Spring Cloud Config en toute sécurité avec Spring Boot 2.0