使用Spring Boot进行身份验证的方法
■环境
– 环境的意思是周围的自然和社会条件。
– 环境指的是我们生活和工作的周围环境。
– 环境是指我们所处的自然和人造条件。
– 环境是指我们所处的周围条件和氛围。
Spring Boot 1.2.5 Release,Java 8,Maven 3.3.1。
■摘要
为了进行Spring Boot的身份验证,我们需要整理所需的模块和设置。
我们将使用Spring Security的身份验证和授权机制。
■pom.xml的文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- ■Spring Boot本体 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<!-- ■Spring Boot関連 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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>
<!-- ■Javaライブラリ -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.4</version>
<scope>provided</scope>
</dependency>
<!-- ■フロントエンドフレームワーク -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
■详细
创建登录界面
当用户点击登录按钮时,将会向/login发起POST请求。
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ログイン</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="../webjars/bootstrap/3.3.1/css/bootstrap.min.css" type="text/css"></link>
<link rel="stylesheet" href="../css/common.css" type="text/css"></link>
<!--[if lt IE 9]>
<script type="text/javascript" src="../javascript/ie8/html5shiv.js"></script>
<script type="text/javascript" src="../javascript/ie8/respond.js"></script>
<script type="text/javascript" src="../javascript/ie8/jquery-1.11.3.min.js"></script>
<![endif]-->
<!--[if gte IE 9]><!-->
<script type="text/javascript" src="../webjars/jquery/2.1.4/jquery.min.js"></script>
<!--<![endif]-->
<script type="text/javascript" src="../webjars/bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<p><h1 id="title">ログイン</h1></p>
</div>
<div class="row">
<div class="col-md-3 col-lg-3"></div>
<div class="col-md-6 col-lg-6">
<div class="well well-sm">
<form id="login_form" method="post" th:action="@{'/login'}">
<fieldset id="login_field">
<div class="form-group">
<label>ログインID</label>
<input type="text" class="form-control" id="login_id" name="login_id" placeholder="ログインIDを入力してください" autofocus="" required="" />
</div>
<div class="form-group">
<label>パスワード</label>
<input type="password" class="form-control" id="login_password" name="login_password" placeholder="パスワードを入力してください" required="" />
</div>
<div class="form-group">
<input id="login_button" type="submit" value="ログイン" />
</div>
</fieldset>
</form>
</div>
</div>
<div class="col-md-3 col-lg-3"></div>
</div>
</div>
</body>
</html>
创建Spring Security的配置类
这个设置类会处理来自/login的POST请求。
package com.sample.config;
import com.sample.framework.security.SamplAuthenticationFailureHandler;
import com.sample.login.service.UserDetailsServiceImpl;
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.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
/**
* Spring Security設定クラス.
*/
@Configuration
@EnableWebMvcSecurity // Spring Securityの基本設定
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
// セキュリティ設定を無視するリクエスト設定
// 静的リソース(images、css、javascript)に対するアクセスはセキュリティ設定を無視する
web.ignoring().antMatchers(
"/images/**",
"/css/**",
"/javascript/**",
"/webjars/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 認可の設定
http.authorizeRequests()
.antMatchers("/", "/index").permitAll() // indexは全ユーザーアクセス許可
.anyRequest().authenticated(); // それ以外は全て認証無しの場合アクセス不許可
// ログイン設定
http.formLogin()
.loginProcessingUrl("/login") // 認証処理のパス
.loginPage("/index") // ログインフォームのパス
.failureHandler(new SampleAuthenticationFailureHandler()) // 認証失敗時に呼ばれるハンドラクラス
.defaultSuccessUrl("/menu") // 認証成功時の遷移先
.usernameParameter("login_id").passwordParameter("login_password") // ユーザー名、パスワードのパラメータ名
.and();
// ログアウト設定
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout**")) // ログアウト処理のパス
.logoutSuccessUrl("/index"); // ログアウト完了時のパス
}
@Configuration
protected static class AuthenticationConfiguration
extends GlobalAuthenticationConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
// 認証するユーザーを設定する
auth.userDetailsService(userDetailsService)
// 入力値をbcryptでハッシュ化した値でパスワード認証を行う
.passwordEncoder(new BCryptPasswordEncoder());
}
}
}
在configure方法中,我们会获取下面输入的登录ID和密码,并进行身份验证。
// ログイン設定
http.formLogin()
.loginProcessingUrl("/login") // 認証処理のパス
.loginPage("/index") // ログインフォームのパス
.failureHandler(new SampleAuthenticationFailureHandler()) // 認証失敗時に呼ばれるハンドラクラス
.defaultSuccessUrl("/menu") // 認証成功時の遷移先
.usernameParameter("login_id").passwordParameter("login_password") // ユーザー名、パスワードのパラメータ名
.and();
实际的认证处理是隐式调用内部类AuthenticationConfiguration。
自动装配的UserDetailsServiceImpl类在第2步中被引入。
@Configuration
protected static class AuthenticationConfiguration
extends GlobalAuthenticationConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
// 認証するユーザーを設定する
auth.userDetailsService(userDetailsService)
// 入力値をbcryptでハッシュ化した値でパスワード認証を行う
.passwordEncoder(new BCryptPasswordEncoder());
}
}
我现在不解释,但是我会贴上在认证失败时被调用的处理程序类。
package com.sample.framework.security;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sample.framework.util.SampleErrorMessageMap;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
/**
* Spring Securityの認証失敗時に呼ばれるハンドラクラス
*/
public class SampleAuthenticationFailureHandler implements
AuthenticationFailureHandler {
/* (非 Javadoc)
* @see org.springframework.security.web.authentication.AuthenticationFailureHandler
* #onAuthenticationFailure(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse, org.springframework.security.core.AuthenticationException)
*/
@Override
public void onAuthenticationFailure(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException authenticationException)
throws IOException, ServletException {
String errorId = "";
// ExceptionからエラーIDをセットする
if(authenticationException instanceof BadCredentialsException){
errorId = SampleErrorMessageMap.MSG_ERROR_0001;
}
// ログイン画面にリダイレクトする
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/"
+ httpServletRequest.getParameter("identifier") + "/index?error=" + errorId);
}
}
创建一个实现UserDetailsService类的实现类。
在2中创建的配置类中被调用。
由于重写了loadUserByUsername方法,它将在内部自动被调用。在这个方法中,将根据登录页面输入的登录ID获取认证用户的信息。
package com.sample.login.service;
import java.util.ArrayList;
import java.util.List;
import com.sample.db.domain.entity.loginuser.custom.MLoginUser;
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.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* UserDetailsServiceの実装クラス
* Spring Securityでのユーザー認証に使用する
*/
@Component
public class UserDetailsServiceImpl implements UserDetailsService {
/* (非 Javadoc)
* @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
*/
@Override
public UserDetails loadUserByUsername(String login_id)
throws UsernameNotFoundException {
// 認証を行うユーザー情報を格納する
MLoginUser user = null;
try {
// 入力したユーザーIDから認証を行うユーザー情報を取得する
// 処理内容は省略
} catch (Exception e) {
// 取得時にExceptionが発生した場合
throw new UsernameNotFoundException("It can not be acquired User");
}
// ユーザー情報を取得できなかった場合
if(user == null){
throw new UsernameNotFoundException("User not found for login id: " + login_id);
}
// ユーザー情報が取得できたらSpring Securityで認証できる形で戻す
return new LoginUser(user);
}
}
创建一个用于存储认证用户信息的类。
在第三项中,有以下描述。
// ユーザー情報が取得できたらSpring Securityで認証できる形で戻す
return new LoginUser(user);
在Spring Security中,可以进行身份验证的形式是指使用Spring Security提供的User类或继承自该类的类。
package com.sample.login.service.data;
import java.util.List;
import com.sample.db.domain.entity.loginuser.custom.MLoginUser;
import org.springframework.security.core.authority.AuthorityUtils;
/**
* 認証ユーザーの情報を格納するクラス
*/
public class LoginUser
extends org.springframework.security.core.userdetails.User {
/**
* ログインユーザー
*/
private final MLoginUser mLoginUser;
/**
* その他、ログイン後に利用したい情報があればここで宣言する
*/
・・・
/**
* コンストラクタ
* @param user
*/
public LoginUser(MLoginUser user) {
// スーパークラスのユーザーID、パスワードに値をセットする
// 実際の認証はスーパークラスのユーザーID、パスワードで行われる
super(user.getLoginUserId(), user.getPassword(),
AuthorityUtils.createAuthorityList("ROLE_USER"));
this.mLoginUser = user;
}
/**
*
* @return
*/
public MLoginUser getUser() {
return mLoginUser;
}
}
package com.sample.db.domain.entity.loginuser.custom;
import javax.persistence.Entity;
@Entity
public class MLoginUser implements java.io.Serializable {
private String loginUserId;
private String password;
public MLoginUser() {
}
}
• 总结
• 概括
• 简述
• 归纳
• 综合
• 摘要
1.在登录页面上输入用户ID和密码,将其发送到认证处理去验证。
通过Spring Security的配置类捕获POST请求并进行认证处理。
3. 在UserDetailsService类的loadUserByUsername方法中获取身份验证所需的信息,并以Spring Security可认证的形式返回。
在登录页面上,对输入的密码和获取的密码进行核对。
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
// 認証するユーザーを設定する
auth.userDetailsService(userDetailsService)
// 入力値をbcryptでハッシュ化した値でパスワード認証を行う
.passwordEncoder(new BCryptPasswordEncoder());
}
由于上述情况下获取的密码已经通过bcrypt进行了哈希处理,所以我们将通过bcrypt对登录界面输入的密码进行哈希化并进行验证。
■参考文献
第一次尝试Spring Boot