Spring Boot 1.5.9.RELEASE Java 8 Maven 4.0.0
Utilisez Spring Security pour vérifier et vous authentifier avec les informations de connexion dans la base de données. DB utilise H2DB et ORM utilise Doma.
Générez un projet avec Spring Inirializr.
Puisque nous utiliserons Doma pour ORM cette fois, définissez le traitement des annotations.
Seuls ceux qui ont été modifiés par rapport à la valeur par défaut sont répertoriés.
pom.xml(※Extrait)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seasar.doma.boot/doma-spring-boot-starter -->
<dependency>
<groupId>org.seasar.doma.boot</groupId>
<artifactId>doma-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
UserEntity.java
package com.example.springbootsecuritysample.entity;
import java.util.Collection;
import org.seasar.doma.Entity;
import org.seasar.doma.Id;
import org.seasar.doma.jdbc.entity.NamingType;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import lombok.Getter;
import lombok.Setter;
/**
*Entité dans la table USER
* @author T.Harao
*
*/
@Entity(naming = NamingType.SNAKE_UPPER_CASE)
@Getter
@Setter
public class UserEntity implements UserDetails {
@Id
private String userId;
private String password;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getUsername() {
return userId;
}
/**
*Renvoie le mot de passe à vérifier par UserDetailsService
*Si vous utilisez Lombok, si le champ contient "mot de passe"
*GetPassword avec @Getter()N'est pas nécessaire car il générera
*/
@Override
public String getPassword() {
return password;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
UserDao.java
package com.example.springbootsecuritysample.dao;
import org.seasar.doma.Dao;
import org.seasar.doma.Select;
import org.seasar.doma.boot.ConfigAutowireable;
import com.example.springbootsecuritysample.entity.UserEntity;
/**
*DAO accédant à la table USER
* @author T.Harao
*
*/
@Dao
@ConfigAutowireable
public interface UserDao {
@Select
public UserEntity selectByUserId(String userId);
}
AuthService.java
package com.example.springbootsecuritysample.service;
import org.springframework.beans.factory.annotation.Autowired;
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 com.example.springbootsecuritysample.dao.UserDao;
import com.example.springbootsecuritysample.entity.UserEntity;
/**
*Service qui gère l'authentification
* @author T.Harao
*
*/
@Service
public class AuthService implements UserDetailsService {
@Autowired
private UserDao dao;
/**
*Chargement de l'utilisateur
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username == null || "".equals(username)) {
throw new UsernameNotFoundException("L'ID utilisateur n'a pas été saisi");
}
UserEntity user = dao.selectByUserId(username);
if(user == null) {
throw new UsernameNotFoundException("L'ID utilisateur n'est pas valide.");
}
return user;
}
}
IndexForm.java
package com.example.springbootsecuritysample.form;
import org.hibernate.validator.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
/**
*Formulaire utilisé par IndexController
* @author T.Harao
*
*/
@Getter
@Setter
public class IndexForm {
@NotEmpty
private String userId;
@NotEmpty
private String password;
}
IndexController.java
package com.example.springbootsecuritysample.controller;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.example.springbootsecuritysample.form.IndexForm;
/**
*S'identifier
* @author T.Harao
*
*/
@Controller
@RequestMapping({"/", "/index"})
public class IndexController {
@ModelAttribute
public IndexForm initForm(){
return new IndexForm();
}
/**
*Affichage initial
* @param mv
* @return
*/
@RequestMapping(value = {"/", "/index"}, method = RequestMethod.GET)
public ModelAndView index(ModelAndView mv) {
mv.setViewName("index/index");
return mv;
}
/**
*Au moment de l'erreur d'authentification
* @param mv
* @return
*/
@RequestMapping(value = {"/", "/index"}, method = RequestMethod.POST)
public ModelAndView login(@ModelAttribute @Validated IndexForm form, BindingResult result, ModelAndView mv) {
if(!result.hasErrors()) {
mv.addObject("errorMessage", "Informations de connexion incorrectes");
}
mv.setViewName("index/index");
return mv;
}
}
MenuController.java
package com.example.springbootsecuritysample.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
/**
*menu
* @author T.Harao
*
*/
@Controller
@RequestMapping("/menu")
public class MenuController {
/**
*Affichage initial
* @param mv
* @return
*/
@RequestMapping(value = {"/", "/index"}, method = RequestMethod.GET)
public ModelAndView index(ModelAndView mv) {
mv.setViewName("menu/index");
return mv;
}
}
FailureHandler.java
package com.example.springbootsecuritysample.config.handler;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
/**
*Gestionnaire lorsque l'authentification échoue
* @author T.Harao
*
*/
@Component
public class FailureHandler implements AuthenticationFailureHandler {
/**
*Lorsque l'authentification échoue
*/
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
//「/Transférer à
RequestDispatcher dispatch = request.getRequestDispatcher("/");
dispatch.forward(request, response);
}
}
SuccessHandler.java
package com.example.springbootsecuritysample.config.handler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
/**
*Gestionnaire en cas d'authentification réussie
* @author T.Harao
*
*/
@Component
public class SuccessHandler implements AuthenticationSuccessHandler {
/**
*Lorsque l'authentification est réussie
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
//「/menu/Rediriger vers
response.sendRedirect(request.getContextPath() + "/menu/");
}
}
SecurityConfig.java
package com.example.springbootsecuritysample.config;
import org.springframework.beans.factory.annotation.Autowired;
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.crypto.password.NoOpPasswordEncoder;
import com.example.springbootsecuritysample.config.handler.FailureHandler;
import com.example.springbootsecuritysample.config.handler.SuccessHandler;
import com.example.springbootsecuritysample.service.AuthService;
/**
*les paramètres de sécurité
* @author T.Harao
*
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthService service;
@Autowired
private FailureHandler failureHandler;
@Autowired
private SuccessHandler successHandler;
/**
*Paramètres de sécurité Web
*/
@Override
public void configure(WebSecurity web) throws Exception {
//Ressources statiques(images、css、javascript)Et l'accès à la console H2DB ignore les paramètres de sécurité
web.ignoring().antMatchers("/css/**", "/fonts/**", "/images/**", "/js/**", "/h2-console/**");
}
/**
*Paramètres HttpSecurity
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//Paramètres d'autorisation
http.authorizeRequests()
//Définissez une URL accessible sans authentification
.antMatchers("/", "/index/**").permitAll()
//Paramètres autres que ceux ci-dessus requis pour l'authentification
.anyRequest().authenticated();
//Paramètres de connexion
http.formLogin()
//Définissez le chemin pour le traitement de l'authentification
.loginProcessingUrl("/index/login")
//Définissez le chemin du formulaire de connexion
.loginPage("/")
.loginPage("/index/**")
//Définissez l'URL à rediriger lorsque l'authentification est réussie
.defaultSuccessUrl("/menu/")
//Définissez l'URL à transférer lorsque l'authentification échoue
.failureForwardUrl("/")
//Définissez l'URL à transférer lorsque l'authentification a réussi
//.successForwardUrl("/")
//Définit la classe de gestionnaire à appeler lorsque l'authentification est réussie
//.successHandler(successHandler)
//Définir l'URL pour rediriger lorsque l'authentification échoue
//.failureUrl("/menu/")
//Définir une classe de gestionnaire à appeler en cas d'échec de l'authentification
//.failureHandler(failureHandler)
//Définir le nom d'utilisateur et le nom du paramètre de mot de passe
.usernameParameter("userId").passwordParameter("password");
}
/**
*Réglage
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//Définissez "NoOpPasswordEncoder" car le mot de passe est enregistré dans la base de données en texte brut.
auth.userDetailsService(service)
.passwordEncoder(NoOpPasswordEncoder.getInstance());
}
}
layout.html
<!DOCTYPE html>
<html
xmlns = "http://www.w3.org/1999/xhtml"
xmlns:th = "http://www.thymeleaf.org"
xmlns:layout = "http://www.ultraq.net.nz/thymeleaf/layout"
>
<head>
<meta charset="UTF-8" />
<title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">Test de sécurité de printemps</title>
<link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" media="all" />
<link rel="stylesheet" type="text/css" href="/css/bootstrap-theme.min.css" th:href="@{/css/bootstrap-theme.min.css}" media="all" />
<script type="text/javascript" src="/js/jquery-1.12.4.min.js" th:src="@{/js/jquery-1.12.4.min.js}"></script>
<script type="text/javascript" src="/js/bootstrap.min.js" th:src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
<div class="contents" layout:fragment="contents"></div>
</body>
</html>
index/index.html
<!DOCTYPE html>
<html
xmlns = "http://www.w3.org/1999/xhtml"
xmlns:th = "http://www.thymeleaf.org"
xmlns:layout = "http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout"
>
<head>
<title>S'identifier</title>
</head>
<body>
<div layout:fragment="contents">
<form class="form-horizontal" method="POST" action="/index/login/" th:action="@{/index/login}" th:object="${indexForm}">
<div th:text="${errorMessage}?: ''" class="col-sm-offset-2 text-danger"></div>
<div class="form-group">
<p th:if="${#fields.hasErrors('*{userId}')}" th:errors="*{userId}" class="col-sm-offset-2 text-danger"></p>
<label for="user-id" class="col-sm-2 control-label">Identifiant d'utilisateur</label>
<div class="col-sm-5">
<input type="text" class="form-control" id="user-id" th:field="*{userId}" placeholder="Identifiant d'utilisateur" />
</div>
</div>
<div class="form-group">
<p th:if="${#fields.hasErrors('*{password}')}" th:errors="*{password}" class="col-sm-offset-2 text-danger"></p>
<label for="password" class="col-sm-2 control-label">mot de passe</label>
<div class="col-sm-5">
<input type="password" class="form-control" id="password" th:field="*{password}" placeholder="mot de passe" />
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary col-sm-2 col-sm-offset-2" name="login" value="S'identifier" />
<input type="reset" class="btn btn-default col-sm-2 col-sm-offset-1" name="clear" value="clair" />
</div>
</form>
</div>
</body>
</html>
menu/index.html
<!DOCTYPE html>
<html
xmlns = "http://www.w3.org/1999/xhtml"
xmlns:th = "http://www.thymeleaf.org"
xmlns:layout = "http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layout"
>
<head>
<title>menu</title>
</head>
<body>
<div layout:fragment="contents">
<h2>menu</h2>
</div>
</body>
</html>
application.yaml
#spring
spring:
profiles:
active: dev
datasource:
url: jdbc:h2:./db
#server
server:
contextPath: /security-sample
#doma
doma:
dialect: h2
application-dev.yaml
#spring
spring:
h2:
console:
enabled: true
thymeleaf:
cache: false
application-production.yaml
#spring
spring:
h2:
console:
enabled: false
thymeleaf:
cache: true
selectByUserId.sql
select
user_id
,password
from
user
where
user_id = /*userId*/''
schema.sql
--drop table if exists user;
create table if not exists user (
user_id varchar(30) not null primary key
,password varchar(30) not null
);
data.sql
insert into user (user_id,password) values ('test','pass');
La structure des dossiers est la suivante.
Accédez à [http: // localhost: 8080 / security-sample /](http: // localhost: 8080 / security-sample /) et accédez à Entrez «test» comme ID utilisateur et «pass» comme mot de passe pour accéder à l'écran de menu. Écran de connexion Écran de menu
Le traitement lorsque l'authentification réussit ou échoue est décrit dans la partie suivante de SecurityConfig.java
.
SecurityConfig.java
/**
*Paramètres HttpSecurity
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//Paramètres d'autorisation
http.authorizeRequests()
//Définissez une URL accessible sans authentification
.antMatchers("/", "/index/**").permitAll()
//Paramètres autres que ceux ci-dessus requis pour l'authentification
.anyRequest().authenticated();
//Paramètres de connexion
http.formLogin()
//Définissez le chemin pour le traitement de l'authentification
.loginProcessingUrl("/index/login")
//Définissez le chemin du formulaire de connexion
.loginPage("/")
.loginPage("/index/**")
//Définissez l'URL à rediriger lorsque l'authentification est réussie
.defaultSuccessUrl("/menu/")
//Définissez l'URL à transférer lorsque l'authentification échoue
.failureForwardUrl("/")
//Définissez l'URL à transférer lorsque l'authentification a réussi
//.successForwardUrl("/")
//Définit la classe de gestionnaire à appeler lorsque l'authentification est réussie
//.successHandler(successHandler)
//Définir l'URL pour rediriger lorsque l'authentification échoue
//.failureUrl("/menu/")
//Définir une classe de gestionnaire à appeler en cas d'échec de l'authentification
//.failureHandler(failureHandler)
//Définir le nom d'utilisateur et le nom du paramètre de mot de passe
.usernameParameter("userId").passwordParameter("password");
}
J'ai commenté, mais lorsque l'authentification réussit et échoue Vous pouvez rediriger, transférer et déléguer le traitement à la classe de gestionnaire.
Le projet créé cette fois est en ici
Recommended Posts