使用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

广告
将在 10 秒后关闭
bannerAds