[JAVA] Implementierte Authentifizierungsfunktion mit Spring Security ①

Derzeit studiere ich das Framework und beschäftige mich mit Spring Boot. Bei der Implementierung der Anmeldefunktion scheint es ein Standard zu sein, die Authentifizierungsfunktion von Spring Security zu verwenden, daher habe ich sie mit dieser implementiert. Zu dieser Zeit hatte ich große Probleme und es dauerte lange, bis ich es implementiert hatte. Deshalb habe ich versucht, es selbst zusammenzufassen.

1. Bild der Frühlingssicherheit

SpringBoot_Di_Security_DB.png

Sehr einfaches Bild Es tut mir leid, aber das Bild sieht so aus. Verwenden Sie die DI-Funktion (Dependency Injection) von SpringBoot, um ** Spring Security von außen zu lesen und mit der Datenbank zu interagieren **. Ich werde DI nicht im Detail erklären, aber ich denke, dass Sie durch Einfügen eines externen Objekts in eine Box namens DI-Container immer die Funktionen des Objekts verwenden können. In diesem Fall ist dieses Objekt "SpringSecurity". Darüber hinaus verfügt Spring Security über eine Methode zum Herstellen einer Verbindung zur Datenbank. Da jedoch Spring Data JDBC tatsächlich verantwortlich ist, wird JDBC in der obigen Abbildung zwischen Spring Security und DB eingefügt.

2. Implementierungsablauf.

Ich werde es sofort implementieren, aber ich werde den Ablauf der Implementierung kurz erläutern.

  1. Liste in MySQL anzeigen.
  2. Implementierung des Anmeldebildschirms.
  3. Implementierung der Spring Security-Authentifizierungsfunktion.

Es sieht aus wie das. Da diesmal Nr. 3 das Haupt- und das größte Volume ist, ist es einfacher zu lösen, wenn später ein Fehler auftritt, wenn Sie nach der sicheren Implementierung von Nr. 1 und Nr. 2 zu Nr. 3 wechseln. In meinem Fall, als ich von Anfang an versuchte, Nr. 3 zu implementieren, trat beim Lesen von MySQL ein Fehler auf, oder ich habe einen Fehler beim Umleiten des Anmeldebildschirms gemacht. Vor der Implementierung von Nr. 3 ist ein Fehler aufgetreten, und es hat einige Zeit gedauert, ihn zu beheben. ..

3. Liste in MySQL anzeigen.

Beginnen wir mit der Entwicklung. ** Stellen Sie sicher, dass Sie "STS" und "MySQL" als Voraussetzungen verwenden können. ** ** **

3-1, Erstellen Sie ein Projekt.

"Datei" -> "Neu" -> "Spring Boot" -> "Spring Starter Project" Beziehen Sie sich auf das Bild unten und stimmen Sie mit dem App-Namen, dem Gruppennamen, der JAVA-Version usw. überein.  SpringBoot_Di_Security_DB_2.png

SpringBoot_Di_Security_DB_3.png

・ Bestätigung des Projekts. Es ist in Ordnung, wenn die folgenden Dateien erstellt werden.  SpringBoot_Di_Security_DB_4.png

-Starten Sie das Projekt. Beginnen Sie in der Reihenfolge "Rechtsklick auf das Projekt" -> "Ausführen" -> "Spring Boot-Anwendung". In diesem Fall wird der folgende Fehler angezeigt.

Konsole



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

Bei der Übersetzung von "Fehler beim Konfigurieren einer DataSource ..." ist die Datenquelleneinstellung fehlgeschlagen. Es heißt, dass der Fahrer nicht identifiziert werden kann. Wenn Sie "Wenn Sie eine eingebettete Datenbank möchten ..." übersetzen, heißt es außerdem, dass Sie die Datenbank im Klassenpfad bereitstellen und das Profil aktivieren möchten, wenn Sie die Datenbank laden möchten. Daraus können Sie irgendwie verstehen, dass Sie Einstellungen in Ihr Profil schreiben müssen, um das MySQL zu verwenden, das Sie dieses Mal verwenden möchten.

Wenn Sie DB verwenden, bearbeiten Sie "application.property".

3-2, Application.property bearbeiten.

<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 ist die URL von MySQl. Danach wird die Zeitzone eingestellt. Für mehr Informationen[Hier](https://qiita.com/KKZ@github/items/e3f594b04c9233a86419)
spring.datasource.url=jdbc:mysql://localhost:3306/login_app?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
#//Sie sind als Root angemeldet.
spring.datasource.username=root
spring.datasource.password=
#//MySQL-Treiber
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.jpa.database=MYSQL
spring.session.store-type=jdbc

3-3, Start von MySQL.

Melden Sie sich an der Eingabeaufforderung oder bei PowerShell bei MySQL an. Im Folgenden ist der Befehl, den Sie tatsächlich eingeben, der "Ausführungsbefehl", und derjenige, der einfach das Anzeigeergebnis anzeigt, wenn der Befehl ausgeführt wird, ist das "Befehlsausführungsbeispiel". Bitte fahren Sie fort, während Sie sich darauf beziehen.

Ausführungsbefehl



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;

Beispiel für die Befehlsausführung



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>


Wenn das Ergebnis von "select * from user;" wie oben ist, ist es OK. Zu diesem Zeitpunkt sollte die App ausgeführt werden.

3-4, Starten Sie das Projekt.

Beginnen Sie in der Reihenfolge "Rechtsklick auf das Projekt" -> "Ausführen" -> "Spring Boot-Anwendung". Dann sollte es normal beginnen. Wenn kein Fehler vorliegt, ist dies in Ordnung.

Beispiel für die Konsolenausgabe



 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: 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\zum 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


In diesem Zustand wurde die App selbst gestartet, aber ich kann sie bei localhost: 8080 nicht überprüfen. Der Grund ist, dass ich keine Ansicht oder Steuerung zum Anzeigen erstellt habe.

3-5, Ansicht und Controller erstellen und die Seite vorerst anzeigen.

Das fertige Bild ist wie folgt. Es wird verwirrend sein, wenn Sie alles plötzlich machen, also werden wir es auch hier Schritt für Schritt machen. Dieses Mal ist es nur das Ziel, die Ansicht vorerst anzuzeigen.

SpringBoot_Di_Security_DB_6.png

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 {

    //Führen Sie die Get-Methode aus, wenn Sie auf die Adresse von userList zugreifen.
    @GetMapping("/userList")
    public String getUserList(Model model) {
    	
    	//Die Ansicht kann durch Angabe des Dateinamens unter Vorlage aufgerufen werden.
        return "userList";
    }
}

templates/userList.html



<!DOCTYPE html>
<!--Beschreiben Sie Folgendes, um Thymeleaf zu verwenden. Danach th:Wenn Sie xxx festlegen, können Sie die Thymeleaf-Methode verwenden.-->
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>
</head>
<body>
    <!--Inhaltsteil-->
    <div>
    	<h1>Benutzerliste</h1>
        <table>
            <tr>
                <th>user_id</th>
                <th>user_name</th>
                <th>password</th>
            </tr>
            <!--Benutzerliste vom Controller empfangen th:Drehen Sie die Elemente des Arrays in jeder Anweisung.-->
            <!--Da eine Instanz der User-Klasse im Argument user gespeichert ist, kann der Wert durch Angabe des Feldnamens abgerufen werden.-->
            <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>

・ Sobald Sie es geschrieben haben, sollten Sie es anzeigen können.

3-6, Zeigen Sie die App im Browser an.

・ Wenn der folgende Bildschirm angezeigt wird, ist er in Ordnung. Derzeit kann die Liste selbst nicht angezeigt werden, da das DB-Verbindungsobjekt nicht implementiert ist.

SpringBoot_Di_Security_DB_7.png

3-7, Implementierte Objekte für die DB-Verbindung.

-Das Kompositionsbild der Datei ist wie folgt. ** Roter Rahmen ist neu </ font>, Gelber Rahmen ist eine zu bearbeitende Datei </ font>. ** ** **

SpringBoot_Di_Security_DB_8.png

-Auch ich habe ein Bild des Verarbeitungsablaufs gemacht, also beziehen Sie sich bitte darauf. (Das einfache Bild tut mir jedes Mal leid ...)

SpringBoot_Di_Security_DB_9.png

・ Der Code lautet wie folgt.

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 der Controller-Klasse
@Controller
public class HomeController {

	//Erstellen Sie eine Instanz und speichern Sie sie in einem DI-Container.
    @Autowired
    UserService userService;

    //Führen Sie die Get-Methode aus, wenn Sie auf die Adresse von userList zugreifen.
    @GetMapping("/userList")
    public String getUserList(Model model) {

    	//@Rufen Sie die userService-Methode basierend auf der von Autowired erstellten Instanz auf.
        List<User> userList = userService.selectMany();
        //Übergeben Sie die von userService empfangenen Daten an die Ansichtsseite.
        model.addAttribute("userList", userList);

    	//Die Ansicht kann durch Angabe des Dateinamens unter Vorlage aufgerufen werden.
        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 //Eine Annotation, die zurückgesetzt wird, wenn eine Ausnahme in einer Methode auftritt, dh unmittelbar vor dem Auftreten des Fehlers zurückgegeben wird.
@Service //Annotation der Serviceklasse. Die Serviceklasse ist dafür verantwortlich, die vom DAO empfangenen Daten zu konvertieren und an den Controller weiterzuleiten.
public class UserService {

    @Autowired
    @Qualifier("UserDaoJdbcImpl") //DAO scheint der Standard für die Implementierung der Schnittstelle zu sein und macht die Implementierungsdatei explizit.
    UserDao dao;

    //Führen Sie Daos Methode aus. Übergeben Sie den Rückgabewert als Listentyp an den Controller.
    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 {

    //Holen Sie sich alle Daten in der Benutzertabelle.
    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 der DB-Verbindungsklasse.
public class UserDaoJdbcImpl implements UserDao {

	//DI JdbcTemplate für DB-Verbindung.
    @Autowired
    JdbcTemplate jdbc;

    //Holen Sie sich alle Daten in der Benutzertabelle.
    @Override
    public List<User> selectMany() throws DataAccessException {

    	//Stellen Sie SQL mit der queryForList-Methode aus. Im Fall von queryForList wird das Ergebnis in Form einer Liste vom Kartentyp zurückgegeben.
    	//Map ist ein Objekt vom Typ Array, das aus einer Reihe von Schlüsseln und Werten besteht.
        List<Map<String, Object>> getList = jdbc.queryForList("SELECT * FROM user");
        
        //Erstellen Sie eine Instanz von ArrayList für die Speicherung, um sie in den Benutzertyp zu konvertieren.
        List<User> userList = new ArrayList<>();

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

            User user = new User();
            // map.Get Value basierend auf Key mit get. Wenden Sie es auf den Setter der Benutzerklasse an.
            //In diesem Fall DB-Benutzer_Der der Spalte mit dem Namen id zugeordnete Datensatz wird erfasst.
            user.setUserId((int) map.get("user_id"));
            user.setPassword((String) map.get("password"));
            user.setUserName((String) map.get("user_name"));

            // userList(Listentyp-Array)Benutzerinstanz hinzufügen zu.
            userList.add(user);
        }
        //Liste an Service zurücksenden.
        return userList;
    }


}


java:SpringLogin.app.model/User.java



package SpringLogin.app.model;

import lombok.Data;

@Data //Getter mit einer Anmerkung, weil Lombok verwendet wird,Sie können einen Setter erstellen.
public class User {

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

}


・ Wenn Sie den Code geschrieben haben, überprüfen Sie ihn in Ihrem Browser. Wenn Sie die App in Eclipse noch nicht gestartet haben, starten Sie sie vor dem Überprüfen. Es ist in Ordnung, wenn der Bildschirm wie folgt aussieht.

SpringBoot_Di_Security_DB_10.png

Sie können jetzt MySQL verwenden! ** Da es lang geworden ist, werde ich mit [Nächstes Mal] fortfahren (https://qiita.com/YJ2222/items/11ff28972da21da421d5). ** ** **

Recommended Posts