Spring BootでSpring Securityを使って認証を実装する方法

spring

タイトルの通りです。

Spring Boot+Spring Security+Thymeleafの組み合わせなので執筆時点(2017/11)では一番モダンな認証機能になるのかと思います。

今回紹介するソースは、Spring Frameworkの公式チュートリアルを参考に作った(ほぼそのまま)ものです。

[スポンサーリンク]

はじめに

今回紹介するソースは上記で書いたとおり、コチラの公式チュートリアルに沿って作っていきました。

実際に上記のサイト通りに作ってみるとSpring Securityの基本的なところだけに的を絞ったシンプルなソースだなぁというのが率直な感想でした。(実運用では使えないくらいシンプルです。)

ただし、このソースがSpring Securityの基礎になるので、今からSpring Bootで認証機能を実装しようと思っている人には、基礎を理解するという意味では非常に勉強になると思います。

pom.xml

Spring Boot+Security+Thymeleafを使うためのdependencyはこちらです。

pom.xmlへこちらを追加してください。

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
    <relativePath/>
  </parent>

  <dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring4</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
  </dependencies>

その前に

今回の認証機能ですが、Spring Bootのプロジェクト上に作っていくのでまずはSpring Bootのプロジェクトを作っていきましょう。

過去に書いたコチラのSpring Bootの雛形を作成するが参考になればと思います。また、今回紹介しているソースをあげているGitHubも参考にしてみてください。

画面を作ってみる

さて、認証機能を作成する前にまずは画面を作っていきましょう。

今回作成する画面は3つ。

ページ名内容
home.htmlhello.htmlへのリンクを持っているページです。このページは未認証状態でもみれます。
login.htmlユーザIDとパスワードを入力するためのページです。このページも未認証状態でもみれます。
hello.html認証がOKなユーザのみが見れるページ

イメージとしては、homeページからhelloページに遷移しようとするけど認証がまだ通っていないからloginページが表示される。というような遷移になります。

もちろんloginページで認証がOKならそのままhelloページが表示されます。

もし認証がNGなら、再度loginページが表示されて認証NGのエラーメッセージが表示される。

というのが一連の流れになります。

home.html

main/resources/templatesの下にこちらのhtmlを作っていきましょう。

こちらのページは、hello.htmlへアクセスするリンクが表示されます。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>

        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>

login.html

こちらもmain/resources/templatesの下に作っていきましょう。

ハイライトしている部分の${param.error}が認証でエラーになったかどうかを判断しています。パスワードが間違っていてエラーになった場合は、もう一度この画面へ遷移してきてこのエラーが表示されるという仕組みです。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example </title>
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <form th:action="@{/login}" method="post">
            <div><label> User Name : <input type="text" name="username"/> </label></div>
            <div><label> Password: <input type="password" name="password"/> </label></div>
            <div><input type="submit" value="Sign In"/></div>
        </form>
    </body>
</html>

hello.html

ハイライト部分でログイン画面で入力したユーザ名を表示しています。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>
    </body>
</html>

htmlを表示するためのconfig設定

さて、上記のhtmlですがhtmlを作成しただけでは画面に表示することができませんん。

通常だとコントローラクラスを作って、htmlと1対1にする必要がありますが、今回は単純にhtmlを表示するだけなのでコントローラクラスの作成は省略していきましょう。

代わりにこちらのクラスを用意していきます。

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

}

こちらの設定はSpring Securityの設定ではなく、Spring MVCの設定となります。

これでコントローラを作らずにhtmlを画面上に表示させることができるようになりました。

Spring Securityの設定

ではいよいよ最後です。

ここが一番重要な部分ですね。Spring Securityをどのように動かすのかを設定したconfigクラスになります。

一昔前までだとXMLが主流でしたが、最近ではconfigはJavaクラスに定義することが一般的になってきています。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

8行目の設定は、/ と /homeは誰でもアクセスできるという設定です。

11行目でログインページの設定をしています。

23行目でユーザ名とパスワードとロール(権限)を設定していますが、この書き方はサンプルならではなですね。通常の業務だとあまり見ない書き方です。

その他細かいところはGoogleで調べてもらった方が早いと思います。(いつかこのブログでも書くかもしれません)

とりあえずこちらでSpring Securityの設定は完了です。

細かくいうとSpring Bootを動かすためのSpringBootApplicationを持ったクラスも必要になるのですが今回は省略します。

実際に動くソースは次のサンプルソースで公開しているのでそちらを参考にしてみてください。

もしくは、今回のソースは全てSpring Frameworkの公式チュートリアルを基に作っていますので、そちらを見てもらった方がはやいです。

サンプルソース

上記のロジックはコチラのGitHubで公開しています。

バージョン

Spring Bootのバージョンは、1.5.2です。
Javaは8を使っています。

さいごに

ユーザ名とパスワードをconfigクラスに定義している部分をみるといかにもサンプルコードだなぁという風にみえるかもしれませんが、Spring Securityの大まかな流れを理解するためには非常に役立つソースコードだと思います。

特に実際に動かしてみるとSpring Securityの動作の理解も早くなるので、公式チュートリアルはやってみる価値は大いにあると思います。

それでは!