LoginSignup
1
2

Spring Security の実装

Last updated at Posted at 2024-04-23

概要

VS CodeSpringBootアプリケーションを作成し簡易なSpringSecurityを実装する。
また、インメモリにユーザ情報を持たせアクセス制御も行う
image.png

参考記事
Spring Security 6.0 入門
初めての人のためのSpring Security

目次

  1. 環境情報
  2. Spring Bootアプリケーションの作成
  3. View作成
  4. Controller作成
  5. Spring Securityの設定
  6. 参考資料
  7. 付録(権限ごとのViewの表示変更)

環境情報

項目 バージョン
Java 17
SpringBoot 3.2.4
SpringSecurity 6

SpringBootアプリケーションの作成

VS Codeで以下の依存関係を追加したSpringBootアプリケーションを作成する

dependencies 備考
Spring Web 自己完結型の HTTP サーバーを作成できる
Thymeleaf Javaのウェブ開発用テンプレートエンジン
SpringSecurity Spring Securityを用いた認証・認可に利用

参考: VS CodeでSpring Bootアプリケーション作成 とDB連携

View作成

権限によるアクセス制御を実装するため、
「index.html」, 「user.html」, 「admin.html」の3つのページを用意する。

index.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ホーム</title>
</head>

<body>
  <h1>index.html</h1>
  <a href="./user.html" th:href="@{/user}">ユーザページ</a>
</body>

</html>
user.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ユーザーページ</title>
</head>

<body>
  <h1>user.html</h1>
  <a href="./admin.html"th:href="@{/admin}">管理者ページ</a><br>
  <a href="./logout.html" th:href="@{/logout}">ログアウト</a>
  </form>
</body>

</html>
admin.html
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>管理者ページ</title>
</head>

<body>
  <h1>admin.html</h1>
  <a href="./user.html" th:href="@{/}">ユーザーページ</a><br>
  <a href="./logout.html" th:href="@{/logout}">ログアウト</a>
</body>

</html>

Controller作成

「LoginController.java」を作成する

LoginController.java
package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("")
public class LoginController {

  @GetMapping("/user")
  public String user(){
    return "/user";
  }

  @GetMapping("/admin")
  public String admin(){
    return "/admin";
  }
}

アプリケーションを起動し、「http://localhost:8080/」 に接続するとSpring Securityによりログイン画面が表示される
(SpringSecurityにはデフォルトで「/login」と「/logout」が用意されている
現時点では、SpringSecurityの設定を行なっていないため、全てのページに対してSecurityがかかっている状態)
image.png

Username: user
Password: 起動時のコンソールに出力される(実行ごとに異なる)
image.png

「Sign in」するとユーザーページ(index.html)に遷移する
サインイン後は、全てのページへのアクセスが可能となる

SpringSecurityの設定

「SecurityConfig.java」を作成し、ユーザー情報と各ページの参照権限を設定する

アクセス制御設定

ユーザー/ページ 未ログイン user1 admin
index.html ⚪️ ⚪️ ⚪️
user.html ⚪️ ⚪️
admin.html ⚪️
SecurityConfig.java
package com.example.demo.common;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

  // パスワードの暗号化
  @Bean
  PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  @Bean
  InMemoryUserDetailsManager userDetailsService() {
    // 管理者設定
    UserDetails admin = User
        .withUsername("admin")
        .password(passwordEncoder().encode("admin"))
        .roles("ADMIN")
        .build();

    // ユーザー設定
    UserDetails user = User
        .withUsername("user")
        .password(passwordEncoder().encode("user"))
        .roles("USER")
        .build();
    return new InMemoryUserDetailsManager(admin, user);
  }

  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

    http
        // ログインページの許可設定
        .formLogin(login -> login // フォーム認証を使う
            .defaultSuccessUrl("/user") // 認証成功時のデフォルトの遷移先
            .permitAll())

        // リクエストの許可設定
        .authorizeHttpRequests(authz -> authz
            // index.html の参照権限
            .requestMatchers("/")
            .permitAll()
            // user.html の参照権限
            .requestMatchers("/user")
            .hasAnyRole("USER","ADMIN")
            // admin.html の参照権限
            .requestMatchers("/admin")
            .hasRole("ADMIN"));

    return http.build();
  }

}

アプリケーションを再起動し、以下内容が実装できたことを確認する

  1. http://localhost:8080/ に接続
  2. 表示されたindex.html で「ユーザーページ」を押下
  3. ログイン画面が表示される
  4. 「user」, 「admin」でログインし、アクセス制御が正しく行われていることを確認する

今回のコードサンプル(GitHub)

参考資料

SpringSecurityのアーキテクチャー
インメモリ認証(InMemoryUserDetailsManager)
User(org.springframework.security.core.userdetails.User)

付録

ログインしているユーザーの権限によって、Viewで表示させるコンテンツを変更する
htmlタグに以下の記載を追加
xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
管理者ページへのリンクに以下の記載を追加
sec:authorize="hasAuthority('ROLE_ADMIN')"

上記の記載により、ADMIN権限でログインした場合のみリンクが表示されるようになる

user.html
<!DOCTYPE html>
<!-- 修正 -->
<html lang="ja" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> 

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>ユーザーページ</title>
</head>

<body>
  <h1>user.html</h1>
  <!-- 修正 -->
  <a sec:authorize="hasAuthority('ROLE_ADMIN')" href="./admin.html" th:href="@{/admin}">管理者ページ</a><br>
  <a href="./logout.html" th:href="@{/logout}">ログアウト</a>
</body>

</html>
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2