Alle Artikel wurden kurz vorgestellt, aber als ich tatsächlich meine Hände bewegte, gab es viele Dinge, die ich unerwartet tat. .. .. Ich dachte, es wäre hilfreich für Frühlingsanfänger wie mich. Ich wäre Ihnen dankbar, wenn Sie darauf hinweisen könnten.
■ Was ist Frühlingssicherheit? -DB-Authentifizierung, LDAP-Authentifizierung, CAS-Authentifizierung, JAAS-Authentifizierung, X509-Authentifizierung und Standardauthentifizierung werden als von Security bereitgestellte Authentifizierungsmethoden unterstützt. Dieses Mal wird die DB-Authentifizierung durchgeführt.
■ Erwartete Ergebnisse
・ 1. Hinzufügen von build.gradle-Inhalten ・ 2. Authentifizierungseinstellungen in der Sicherheitskonfiguration ・ 3. Implementierung der UserDetailsService-Schnittstelle (Erfassung von Authentifizierungsinformationen (Realm erstellen)) ・ 4. Erstellen Sie die LoginUser-Klasse ・ 5. Erstellung des Controllers ・ 6. HTML erstellen
Es gibt sechs Hauptschritte.
Ich habe die Demo früher auf [github] gepostet. Wenn Sie möchten, lesen Sie sie bitte.
■■■ Anmeldeinformationen ■■■
Ziel anfordern: http: // localhost: 8080 / loginForm
email:[email protected]
password:password
■■■■■■■■■■■■■
*** Ich bezog mich auf das Beispielprojekt von "Site Supreme Principle Spring Boot2 Thorough Utilization **".
■ Umweltinformationen jdk:11 Datenbank: postgresql (Docker, daher keine Installation erforderlich) ┗ Über den Docker dieser Demo [hier] IDE:IntelliJ Build-System: Gradle
Lassen Sie uns den Quellcode erklären.
build.gradle
plugins {
id 'org.springframework.boot' version '2.1.3.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compile "org.springframework.boot:spring-boot-starter-validation"
runtimeOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor "org.seasar.doma.boot:doma-spring-boot-starter:1.1.1"
compile("org.seasar.doma.boot:doma-spring-boot-starter:1.1.1") {
exclude group: "org.springframework.boot"
}
compile 'org.apache.commons:commons-lang3'
//spring security
compile 'org.springframework.boot:spring-boot-starter-security'
// thymeleaf(rollen/Steuern von Thymeleaf-Vorlagen durch Berechtigungen)
compile "org.thymeleaf.extras:thymeleaf-extras-springsecurity5"
compile "org.modelmapper:modelmapper:0.7.5"
}
apply plugin: 'idea'
idea.module.inheritOutputDirs = true
processResources.destinationDir = compileJava.destinationDir
compileJava.dependsOn processResources
Es werden nur die Teile kommentiert, die sich auf die Federsicherheit beziehen. Dies ist nur eine Ergänzung.
SecurityConfig.java
package com.example.demo;
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.builders.WebSecurity;
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;
import javax.sql.DataSource;
import static com.example.demo.common.WebConst.*;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DataSource dataSource;
@Autowired
UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
*Authentifizieren Sie keine statischen Dateien
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/favicon.ico", "/css/**", "/js/**", "/images/**", "/fonts/**", "/shutdown" /* for Demo */);
}
/**
*Einstellungen, die einen eindeutigen Authentifizierungsbereich verwenden, der die UserDetailsService-Schnittstelle implementiert
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/loginFrom").permitAll()//Anmeldeformular erlaubt
.antMatchers("/user/**").permitAll()
.antMatchers("/new").permitAll()//Zum Test(Benutzer Registration)* Löschen, wenn Sie fertig sind
.antMatchers("/index").permitAll()//Zum Test(Übergangsbildschirm nach Benutzerregistrierung) * Löschen, wenn fertig
.antMatchers("/user/create").permitAll()//Funktion für Test * Löschen, wenn Sie fertig sind
.anyRequest().authenticated();//In allen anderen Fällen ist der Zugriff ohne Authentifizierung nicht zulässig
http.formLogin()
.loginProcessingUrl("/login")//URL zum Anmelden
.loginPage("/loginFrom")//URL des Anmeldebildschirms
.failureUrl("/login?error")//URL, wenn die Authentifizierung fehlschlägt
.successForwardUrl("/success")//URL bei erfolgreicher Authentifizierung
.usernameParameter("email")//Benutzerparametername
.passwordParameter("password");//Name des Passwortparameters
http.logout()
.logoutUrl("/logout**")//URL beim Abmelden (diesmal nicht implementiert)
.logoutSuccessUrl("/login");//URL, wenn die Abmeldung erfolgreich ist
}
}
PasswordEncoder
.
-Es erbt von WebSecurityConfigurerAdapter
und überschreibt die configure ()
Methode. Legen Sie darin die ** URL des Authentifizierungsprozesses ** und die Parameter fest.
-Wenn Sie eine Anfrage an die ** Authentifizierungsverarbeitungs-URL ** senden, wird die Verarbeitung an die innere Klasse namens AuthenticationConfiguration übergeben, und es scheint, dass die eigentliche Authentifizierungsverarbeitung durchgeführt wird. (Auszug aus der folgenden AuthenticationConfiguration-Klasse)AuthenticationConfiguration.java
@Configuration
@Import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
...Kürzung...
@Override
public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService(
T userDetailsService) throws Exception {
return super.userDetailsService(userDetailsService)
.passwordEncoder(this.defaultPasswordEncoder);
}
...
┗ Das Konzept des Reiches Demzufolge
Im Websystem wird der Bereich, auf den dieselbe Authentifizierungsrichtlinie angewendet wird, als Realm bezeichnet, und der Name, der jeden Realm identifiziert, wird als Realmname bezeichnet.
Da es eine Beschreibung gibt, denke ich, dass es ausreicht, die Verarbeitung für jeden Benutzer (nicht beschränkt auf) zu erkennen, um die Authentifizierung zu bestehen.
Um kurz zu beschreiben, was der diesmal erstellte Bereich auf Japanisch tut, ** [Durchsuchen Sie die Datenbank mit dem Benutzernamen als Schlüssel, geben Sie die Informationen des Benutzers zurück, falls vorhanden, und lösen Sie eine Ausnahme aus, wenn sie nicht vorhanden ist. ] ** ** ist.
UserDaoRealm.java
package com.example.demo.security;
import com.example.demo.common.security.BaseRealm;
import com.example.demo.domain.dao.UserDao;
import com.example.demo.domain.dao.UserRoleDao;
import com.example.demo.domain.dto.User;
import com.example.demo.domain.dto.UserRole;
import lombok.extern.slf4j.Slf4j;
import org.seasar.doma.jdbc.NoResultException;
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.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
@Component
@Slf4j
public class UserDaoRealm extends BaseRealm {
@Autowired
UserDao userDao;
@Autowired
UserRoleDao userRoleDao;
@Override
protected UserDetails getLoginUser(String email) {
User user = null;
List<GrantedAuthority> authorityList = null;
try{
user = new User();
user.setEmail(email);
//Benutzer abrufen und in Sitzung speichern
user = userDao.select(user)
.orElseThrow(() -> new UsernameNotFoundException("no user found. [id=]" + email + "]"));
//Kontaktbehörde einholen
List<UserRole> userRoles = userRoleDao.selectByUserId(user.getId(), toList());
//Setzen Sie dem Rollenschlüssel ein Präfix und setzen Sie es zusammen
Set<String> roleKeys = userRoles.stream().map(UserRole::getRole_key).collect(toSet());
//Sammeln Sie Autorisierungsschlüssel
Set<String> permissionKeys = userRoles.stream().map(UserRole::getPermissionKey).collect(toSet());
//Übergeben Sie sowohl Rollen als auch Berechtigungen als erteilte Berechtigung
Set<String> authorities = new HashSet<>();
authorities.addAll(roleKeys);
authorities.addAll(permissionKeys);
authorityList = AuthorityUtils.createAuthorityList(authorities.toArray(new String[0]));
}catch (Exception e){
//Tun Sie nichts, wenn 0 Ausnahmen ausgelöst werden
//Andernfalls schließen Sie es in eine Authentifizierungsfehlerausnahme ein
if(!(e instanceof NoResultException)){
throw new UsernameNotFoundException("could not select user,", e);
}
}
return new LoginUser(user, authorityList);
}
}
-Die abstrakte Klasse "BaseRealm" wird durch Implementierung von "UserDetailsService" erstellt.
Es erbt von "BaseRealm" und erstellt "UserDaoRealm".
-Doma wird zum Erfassen von Informationen von userDao verwendet. Für Details [hier]
-Implementieren Sie LoginUser
mit NO.4.
LoginUser.java
package com.example.demo.security;
import com.example.demo.domain.dto.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
@Data
public class LoginUser extends org.springframework.security.core.userdetails.User {
/**
*Konstrukteur
*
* @param user
* @param authorities
*/
public LoginUser(User user, Collection<? extends GrantedAuthority> authorities){
super(String.valueOf(user.getEmail()), user.getPassword(), authorities);
}
}
Es erbt nur von org.springframework.security.core.userdetails.User
und definiert den Konstruktor.
Sie müssen lediglich die folgende URL auf dem Controller zuordnen. · Login Formular ・ Anmeldevorgang (um die Eingabe zu überprüfen und dann an die Federsicherheit weiterzuleiten) · Erfolgreicher Login
LoginController.java
package com.example.demo.web.controller;
import com.example.demo.common.controller.AbstractHtmlController;
import com.example.demo.common.controller.BaseController;
import com.example.demo.web.form.LoginForm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import static com.example.demo.common.WebConst.*;
@Controller
public class LoginController extends AbstractHtmlController {
@Override
public String getFunctionName() {
return "A_LOGIN";
}
@ModelAttribute
LoginForm loginForm(){return new LoginForm();}
/**
*Anzeige des Anmeldebildschirms
* @Zeigen Sie den Anmeldebildschirm an, wenn Sie die Methode return get verwenden
*/
@GetMapping("/loginForm")
public String loginFrom(){
return "login/login";
}
/**
*Überprüfen Sie die Eingabe
*
* @param form
* @param br
* @return
*/
@PostMapping("/login")
public String index(@Validated @ModelAttribute LoginForm form, BindingResult br) {
//Wenn ein Fehler bei der Eingabeprüfung auftritt, kehren Sie zum ursprünglichen Bildschirm zurück
if (br.hasErrors()) {
return "login/login";
}
//20190309 Wenn die Eingabeprüfung erfolgreich ist, leiten Sie den in der Sicherheitskonfiguration festgelegten Authentifizierungsprozess weiter
//20190309 Muss die Post-Methode sein, daher müssen Sie Forward verwenden
return "forward:" + LOGIN_PROCESSING_URL;
}
/**
*erfolgreicher Login
*/
@PostMapping("/success")
public String loginsuccess(@ModelAttribute LoginForm loginForm, Model model,RedirectAttributes redirectAttributes){
model.addAttribute("msg","loginSuccess");
return "/login/success";
}
}
login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Springboot</title>
<meta charset="utf-8" />
</head>
<body>
<h1 th:text="Einloggen"></h1>
<div th:if="${param.error}" class="alert alert-danger">
Der Benutzername oder das Passwort ist falsch.
</div>
<form th:action="@{'/login'}" action="../user/index.html" th:object = "${loginForm}" method="post">
<div class="form-group" th:classappend="${#fields.hasErrors('email')}? 'has-error'">
<label for="email" class="control-label">email</label>
<input id="email" type="text" class="form-control" th:field="*{email}" name="email">
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="error-massages">error!</span>
</div>
<div class="form-group" th:classappend="${#fields.hasErrors('password')}? 'has-error'">
<label for="password" class="control-label">password</label>
<input id="password" type="password" class="form-control" th:field="*{password}" name="password">
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}" class="error-massages">error!</span>
</div>
<input type="submit" class="btn btn-default" value="Einloggen"/>
</form>
</body>
</html>
Bei th: if =" $ {param.error} "
wird der Fehlerparameter empfangen und eine Zeichenfolge ausgegeben.
Wenn die Anmeldeschaltfläche mit "th: action =" @ {'/ login'} "gedrückt wird, wird der Anmeldevorgang an spring security übergeben.
Dieses Mal konzentrierte ich mich auf wichtige und frühlingshafte Sicherheitsanmeldungen. Das nächste Mal möchte ich versuchen, ** den anzuzeigenden Bildschirm je nach Behörde zu wechseln **. Danke fürs Zuhören.