spring.svg

【Spring Security】はじめの一歩

SpringBoot

はじめに

Spring Security は、認証や認可、CSRF などの攻撃に対する対策を提供するフレームワークです。 少し難しいかもしれませんが、Spring でアプリケーションを構築する上で非常に強力な味方となってくれるため、概要だけでも知っておくとよいかもしれません。

まず最初の記事として、導入と触りの部分のみを説明していきます。

導入

Spring Security を利用するために、build.gradleに以下を追加します。 spring initializr を使用する場合は Spring Security を選択してください。

Gradle
dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-security'
  testImplementation 'org.springframework.security:spring-security-test'
}

ひとまずこれで完了です。 現時点ではとりあえず設定等は必要ありません。

静的な認証情報

動作確認のために、以下のような簡単な Controller を作成します。 作成後、ブラウザでhttp://localhost:8080/helloにアクセスしてください。

HelloController.java
@RestController
@RequestMapping("/hello")
public class HelloController {
  @GetMapping
  public String sayHello() {
    return "Hello!";
  }
}

本来であればHello!と画面に表示されるのですが、Spring Security が導入されていれば、ログイン画面が表示されるはずです。 これは Spring Security の基本機能で、対象アプリケーションへのアクセスには必ず認証が必要となり、Spring Security が用意したログイン画面へとリダイレクトされます。

ID はデフォルトでuser、パスワードは以下のようにコンソールに表示されているものを入力します。 ログインすれば、本来の目的であるHello!が画面に表示されます。

Console
Using generated security password: 250d4073-c5cb-4502-a837-0ca510dfc92a

この ID とパスワードは、設定ファイル(application.propertiesまたはapplication.yml)の以下プロパティで変更可能です。

application.properties
spring.security.user.name=hoge
spring.security.user.password=fuga

認証情報はセッションに登録され、JSESSIONIDという名前でセッション ID が Cookie に保存されます。 これらが有効な間は認証は不要となります。

アーキテクチャ

ここで簡単にアーキテクチャについて触れておきます。

参照:https://docs.spring.io/spring-security/reference/servlet/architecture.html

Spring Security は、サーブレットフィルターの仕組みを使用しており、Security Filter として Spring Security 用の Filter を順に実行します。 どのような Security Filter があるかは、上記 URL の「Security Filters」を参照してください。以下はいくつかピックアップしたものです。

Security Filter説明
ForceEagerSessionCreationFilterセッションがない場合に強制的に作成する。
(必ずセッションがある状態を保つ)
CsrfFilterCSRF トークンの生成、検証を行う。
LogoutFilterログアウト処理を行う。
UsernamePasswordAuthenticationFilterForm で送信された情報(username, password)から認証処理を行う。
DefaultLoginPageGeneratingFilterログインページの設定が無い場合に、デフォルトのログインページを生成する。

静的な認証情報の動きから想定するに、DefaultLoginPageGeneratingFilterで Spring Security で用意されたログインページが返され、 UsernamePasswordAuthenticationFilterでログインページの Form から送信された情報を基に認証処理を行っています。

また実際には、ログインページを表示した時点でForceEagerSessionCreationFilterによりセッションが生成されており、 合わせてCsrfFilterにより CSRF トークンが生成されています。 ディベロッパツールで DOM を見てみると、_csrfとして CSRF トークンが埋め込まれていることが確認できると思います。

このように様々な Security Filter によって Spring Security は構成されています。 Form によるログインの動きについては、以下を参考にしてください。

参考:https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/form.html

設定

Spring Security は認証などを自動でやってくれて便利と思うかもしれませんが、初期状態のまま使用することはあまりないでしょう。 実際には認可が不要なページがあったり、ログインページを変えたり、認証方法を変えたりと、変更しなければならないところはたくさんあるはずです。

Spring Security では、@Configureとして対応するBeanを登録することで上記のような設定を行います。 例えば、認可の有無を設定するには以下のようにします。

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
  @Bean
  SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests(authorize -> authorize
          .requestMatchers("/hello").permitAll()
          .anyRequest().authenticated())
        .formLogin();
    return http.build();
  }
}

上記では/helloは認可なし(permitAll())としており、その他のリクエストは認可あり(authenticated())としています。 その他詳細については割愛しますが、このようにして設定を変更することを覚えておいてください。

おわりに

この記事では Spring Security の基本的なところについて触れていきました。 Spring Security に限った話ではありませんが、フレームワークはいろいろなことを自動でやってくれるので便利ですが、 具体的にどのようなことをしているか知っていないと困ることもあります。

例えば認証・認可の方法や CSRF などのセキュリティー対策がどのように行われているかは知っておくべきことです。 これを使えばできるとわかっていても、どういう仕組みなのかを知らない人ってけっこういるイメージです。

今回は本当に触りの部分だけでしたが、次回以降で具体的な使用方法について説明していければと思っています。