[JAVA] Mise en œuvre de la fonction d'authentification avec Spring Security ①

Actuellement, j'étudie le framework et je m'occupe de Spring Boot. Lors de la mise en œuvre de la fonction de connexion, il semble être une norme d'utiliser la fonction d'authentification de Spring Security, je l'ai donc implémentée en utilisant ceci. À ce moment-là, j'ai eu beaucoup de mal, et il m'a fallu beaucoup de temps pour le mettre en œuvre, alors j'ai essayé de le résumer moi-même.

1. Image de Spring Security

SpringBoot_Di_Security_DB.png

Image très simple Je suis désolé, mais l'image ressemble à ceci. En utilisant la fonction appelée DI (Dependency Injection) de SpringBoot, ** Spring Security est lu de l'extérieur et échangé avec DB **. Je n'expliquerai pas DI en détail, mais je pense que c'est comme pouvoir utiliser les fonctions d'un objet à tout moment en mettant un objet externe dans une boîte appelée conteneur DI. Dans ce cas, cet objet est "SpringSecurity". De plus, Spring Security a une méthode pour se connecter à DB, mais puisque Spring Data JDBC est réellement responsable, dans la figure ci-dessus, JDBC sera inséré entre Spring Security et DB.

2. Flux de mise en œuvre.

Je vais le mettre en œuvre immédiatement, mais je vais expliquer brièvement le flux de mise en œuvre.

  1. Afficher la liste dans MySQL.
  2. Implémentation de l'écran de connexion.
  3. Implémentation de la fonction d'authentification Spring Security.

Ça ressemble à ça. Puisque le n ° 3 est le volume principal et le plus grand cette fois, il est plus facile à résoudre lorsqu'une erreur survient plus tard si vous passez au n ° 3 après avoir sûrement implémenté les n ° 1 et n ° 2. Dans mon cas, lorsque j'ai essayé d'implémenter le n ° 3 depuis le début, j'ai eu une erreur lors de la lecture de MySQL, ou j'ai fait une erreur en redirigeant l'écran de connexion. ..

3. Afficher la liste dans MySQL.

Commençons le développement. ** Assurez-vous que vous pouvez utiliser "STS" et "MySQL" comme prérequis. ** **

3-1, Créez un projet.

"Fichier" -> "Nouveau" -> "Spring Boot" -> "Spring Starter Project" Reportez-vous à l'image ci-dessous et faites correspondre le nom de l'application, le nom du groupe, la version JAVA, etc.  SpringBoot_Di_Security_DB_2.png

SpringBoot_Di_Security_DB_3.png

・ Confirmation du projet. C'est OK si les fichiers suivants sont créés.  SpringBoot_Di_Security_DB_4.png

-Démarrez le projet. Démarrez dans l'ordre "Clic droit sur le projet" -> "Exécuter" -> "Application Spring Boot". Si vous le faites, vous obtiendrez l'erreur suivante.

console



Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-01-16 15:39:27.382 ERROR 49572 --- [  restartedMain] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.

Reason: Failed to determine a suitable driver class


Action:

Consider the following:
	If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
	If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

Lorsque j'ai traduit «Impossible de configurer une source de données ...», le paramètre de source de données a échoué. Il dit que le conducteur ne peut pas être identifié. De plus, lors de la traduction de "Si vous voulez une base de données intégrée ...", il est dit que si vous voulez utiliser la base de données, déployez-la dans le chemin de classe, et si vous voulez charger la base de données, activez le profil. À partir de là, vous pouvez comprendre que vous devez écrire des paramètres dans le profil pour utiliser MySQL que vous souhaitez utiliser cette fois.

Si vous utilisez DB, modifiez "application.property".

3-2, Editez application.property.

<img width="220" alt="SpringBoot_Di_Security_DB_6.png SpringBoot_Di_Security_DB_5.png " src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420031/bcbf58f1-9d17-16f3-472e-013050535ca7.png ">

application.property



#//  jdbc:mysql://localhost:3306/login_app est l'URL de MySQl. Après cela, le fuseau horaire est défini. Pour plus d'informations[Ici](https://qiita.com/KKZ@github/items/e3f594b04c9233a86419)
spring.datasource.url=jdbc:mysql://localhost:3306/login_app?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#//Vous êtes connecté en tant qu'utilisateur root.
spring.datasource.username=root
spring.datasource.password=
#//Pilote MySQL
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.jpa.database=MYSQL
spring.session.store-type=jdbc

3-3, Lancement de MySQL.

Connectez-vous à MySQL à l'invite de commande ou à PowerShell. Ci-dessous, la commande que vous tapez réellement est la "commande d'exécution", et celle qui montre simplement le résultat de l'affichage lorsque la commande est exécutée est "l'exemple d'exécution de commande". Veuillez continuer en vous y référant.

Commande d'exécution



mysql -uroot

create database login_app;

use login_app;

CREATE TABLE user(
    user_id INT AUTO_INCREMENT,
    user_name VARCHAR(255),
    password VARCHAR(255),
    PRIMARY KEY(user_id)
);

desc user;

INSERT INTO user (user_name, password) VALUES
(
    'user1',
    'pass1+'
),
(
    'yama',
    'kawa'
);

select * from user;

Exemple d'exécution de commande



PS C:\Users\MGT-RD18> mysql -uroot
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2246
Server version: 5.7.28-log MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
mysql>
mysql> create database login_app;
Query OK, 1 row affected (0.02 sec)

mysql> use login_app;
Database changed
mysql>
mysql>

mysql>
mysql> CREATE TABLE user(
    ->     user_id INT AUTO_INCREMENT,
    ->     user_name VARCHAR(255),
    ->     password VARCHAR(255),
    ->     PRIMARY KEY(user_id)
    -> );
Query OK, 0 rows affected (0.05 sec)

mysql>
mysql> desc user;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| user_id   | int(11)      | NO   | PRI | NULL    | auto_increment |
| user_name | varchar(255) | YES  |     | NULL    |                |
| password  | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql>
mysql> INSERT INTO user (user_name, password) VALUES
    -> (
    ->     'user1',
    ->     'pass1+'
    -> ),
    -> (
    ->     'yama',
    ->     'kawa'
    -> );
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql>
mysql> select * from user;
+---------+-----------+----------+
| user_id | user_name | password |
+---------+-----------+----------+
|       1 | user1     | pass1+   |
|       2 | yama      | kawa     |
+---------+-----------+----------+
2 rows in set (0.00 sec)

mysql>


Enfin, si le résultat de "select * from user;" est comme ci-dessus, c'est OK. À ce stade, l'application doit s'exécuter.

3-4, Démarrez le projet.

Démarrez dans l'ordre "Clic droit sur le projet" -> "Exécuter" -> "Application Spring Boot". Ensuite, il devrait démarrer normalement. S'il n'y a pas d'erreur, c'est OK.

Exemple de sortie de console



 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)

2020-01-16 16:38:52.112  INFO 50328 --- [  restartedMain] SpringLogin.app.SpringLoginApplication   : Starting SpringLoginApplication on MGT-RD18 with PID 50328 (started by MGT-RD18 in C:\project\pour le test\SpringLogin)
2020-01-16 16:38:52.127  INFO 50328 --- [  restartedMain] SpringLogin.app.SpringLoginApplication   : No active profile set, falling back to default profiles: default
2020-01-16 16:38:52.174  INFO 50328 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-01-16 16:38:52.174  INFO 50328 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-01-16 16:38:52.822  INFO 50328 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2020-01-16 16:38:52.837  INFO 50328 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 12ms. Found 0 JDBC repository interfaces.
2020-01-16 16:38:53.137  INFO 50328 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-01-16 16:38:53.397  INFO 50328 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-01-16 16:38:53.413  INFO 50328 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-01-16 16:38:53.413  INFO 50328 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.29]
2020-01-16 16:38:53.491  INFO 50328 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-01-16 16:38:53.491  INFO 50328 --- [  restartedMain] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1317 ms
2020-01-16 16:38:53.761  INFO 50328 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-01-16 16:38:53.871  WARN 50328 --- [  restartedMain] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
2020-01-16 16:38:54.058  INFO 50328 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2020-01-16 16:38:54.109  INFO 50328 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-01-16 16:38:54.113  INFO 50328 --- [  restartedMain] SpringLogin.app.SpringLoginApplication   : Started SpringLoginApplication in 2.453 seconds (JVM running for 3.661)
2020-01-16 16:39:08.470  INFO 50328 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-01-16 16:39:08.470  INFO 50328 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-01-16 16:39:08.485  INFO 50328 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 15 ms


Dans cet état, l'application elle-même a démarré, mais je ne peux pas la vérifier sur localhost: 8080. La raison est que je n'ai pas créé de vue ou de contrôleur à afficher.

3-5, Créer une vue et un contrôleur et afficher la page pour le moment.

L'image terminée est la suivante. Ce sera déroutant si vous faites tout soudainement, nous allons donc le faire étape par étape ici également. Le but cette fois est simplement d'afficher la vue pour le moment.

SpringBoot_Di_Security_DB_6.png

-Créez le fichier requis et écrivez le code suivant.

java:SpringLogin.app.controller/HomeController.java



package SpringLogin.app.controller;

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

@Controller
public class HomeController {

    //Exécutez la méthode Get lors de l'accès à l'adresse de userList.
    @GetMapping("/userList")
    public String getUserList(Model model) {
    	
    	//La vue peut être appelée en spécifiant le nom du fichier sous le modèle.
        return "userList";
    }
}

templates/userList.html



<!DOCTYPE html>
<!--Décrivez ce qui suit pour utiliser thymeleaf. Après cela, e:Si vous le définissez sur xxx, vous pouvez utiliser la méthode thymeleaf.-->
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
</head>
<body>
    <!--Partie contenu-->
    <div>
    	<h1>Liste d'utilisateur</h1>
        <table>
            <tr>
                <th>user_id</th>
                <th>user_name</th>
                <th>password</th>
            </tr>
            <!--Recevoir userList du contrôleur e:Tournez les éléments du tableau dans chaque instruction.-->
            <!--Puisqu'une instance de la classe User est stockée dans l'argument user, la valeur peut être récupérée en spécifiant le nom du champ.-->
            <tr th:each="user : ${userList}">
                <td th:text="${user.userId}"></td>
                <td th:text="${user.userName}"></td>
                <td th:text="${user.password}"></td>
            </tr>

        </table>
    </div>
</body>
</html>

・ Une fois que vous l'avez écrit, vous devriez pouvoir l'afficher.

3-6, Affichez l'application sur le navigateur.

-Assurez-vous que l'application Spring Boot est en cours d'exécution sur Eclipse et accédez aux éléments suivants. http://localhost:8080/userList

・ Si l'écran suivant s'affiche, c'est OK. Actuellement, la liste elle-même ne peut pas être affichée car l'objet de connexion à la base de données n'est pas implémenté.

SpringBoot_Di_Security_DB_7.png

3-7, Objets implémentés pour la connexion DB.

-L'image de composition du fichier est la suivante. ** Le cadre rouge est nouveau </ font>, Le cadre jaune est le fichier à éditer </ font>. ** **

SpringBoot_Di_Security_DB_8.png

-Aussi, j'ai fait une image du flux de traitement, alors veuillez vous y référer. (Je suis désolé pour l'image simple à chaque fois ...)

SpringBoot_Di_Security_DB_9.png

· Le code est comme suit.

java:SpringLogin.app.controller/HomeController.java



package SpringLogin.app.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import SpringLogin.app.service.UserService;
import SpringLogin.app.model.User;

//Annotation de classe de contrôleur
@Controller
public class HomeController {

	//Créez une instance et stockez-la dans un conteneur DI.
    @Autowired
    UserService userService;

    //Exécutez la méthode Get lors de l'accès à l'adresse de userList.
    @GetMapping("/userList")
    public String getUserList(Model model) {

    	//@Appelez la méthode userService en fonction de l'instance créée par Autowired.
        List<User> userList = userService.selectMany();
        //Passez les données reçues de userService vers le côté Affichage.
        model.addAttribute("userList", userList);

    	//La vue peut être appelée en spécifiant le nom du fichier sous le modèle.
        return "userList";
    }

}

java:SpringLogin.app.service/UserService.java



package SpringLogin.app.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import SpringLogin.app.repository.UserDao;
import SpringLogin.app.model.User;

@Transactional //Annotation qui est annulée lorsqu'une exception se produit dans une méthode, c'est-à-dire qu'elle est renvoyée immédiatement avant que l'erreur ne se produise.
@Service //Annotation de classe de service. La classe Service est chargée de convertir les données reçues du DAO et de les transmettre au contrôleur.
public class UserService {

    @Autowired
    @Qualifier("UserDaoJdbcImpl") //DAO semble être la norme pour implémenter l'interface, et rend le fichier d'impliments explicite.
    UserDao dao;

    //Exécutez la méthode de Dao. Transmettez la valeur de retour en tant que type de liste au contrôleur.
    public List<User> selectMany() {
        return dao.selectMany();

    }

}

java:SpringLogin.app.repository/UserDao.java



package SpringLogin.app.repository;

import java.util.List;

import org.springframework.dao.DataAccessException;

import SpringLogin.app.model.User;

public interface UserDao {

    //Obtenir toutes les données dans le tableau des utilisateurs.
    public List<User> selectMany() throws DataAccessException;

}


java:SpringLogin.app.repository/UserDaoJdbcImpl.java



package SpringLogin.app.repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import SpringLogin.app.model.User;
import SpringLogin.app.repository.UserDao;

@Repository("UserDaoJdbcImpl") //Annotation de classe de connexion DB.
public class UserDaoJdbcImpl implements UserDao {

	//DI JdbcTemplate pour la connexion DB.
    @Autowired
    JdbcTemplate jdbc;

    //Obtenir toutes les données dans le tableau des utilisateurs.
    @Override
    public List<User> selectMany() throws DataAccessException {

    	//Exécutez SQL avec la méthode queryForList. Dans le cas de queryForList, le résultat est renvoyé sous la forme de Liste de type Map.
    	//Map est un objet de type tableau qui est un ensemble de clé et de valeur.
        List<Map<String, Object>> getList = jdbc.queryForList("SELECT * FROM user");
        
        //Créez une instance de ArrayList pour le stockage à convertir en type User.
        List<User> userList = new ArrayList<>();

        for (Map<String, Object> map : getList) {

            User user = new User();
            // map.Obtenez une valeur basée sur la clé avec get. Appliquez-le au Setter de la classe User.
            //Dans ce cas, l'utilisateur DB_L'enregistrement associé à la colonne appelée id est acquis.
            user.setUserId((int) map.get("user_id"));
            user.setPassword((String) map.get("password"));
            user.setUserName((String) map.get("user_name"));

            // userList(Tableau de type liste)Ajouter une instance utilisateur à.
            userList.add(user);
        }
        //Remettre la liste en service.
        return userList;
    }


}


java:SpringLogin.app.model/User.java



package SpringLogin.app.model;

import lombok.Data;

@Data //Obtient avec une annotation car lombok est utilisé,Vous pouvez créer un Setter.
public class User {

    private int userId;
    private String password;
    private String userName;

}


・ Une fois que vous avez écrit le code, vérifiez-le sur votre navigateur. Si vous n'avez pas démarré l'application dans Eclipse, démarrez-la avant de vérifier. Ce n'est pas grave si l'écran ressemble à celui ci-dessous.

SpringBoot_Di_Security_DB_10.png

Vous pouvez maintenant utiliser MySQL! ** Comme c'est devenu long, je continuerai à La prochaine fois. ** **

Recommended Posts