Hello World で学ぶ Spring Security の仕組み

  • 6
    いいね
  • 0
    コメント

自己紹介

  • opengl-8080
  • 主に Qiita で技術メモを書いたり
  • 関西の SIer 勤務

今日お話しすること

簡単な Hello World を通じて、 Spring Security の仕組みの基礎的な部分を説明

  • どのようなクラスが、どのように連携しあっているのか
  • 設定ファイルがどのように関係しているのか

背景

  • 個人的に Spring Security の勉強を開始
  • ちょっと Hello World を書こうとしたが手こずる
    • この設定はなんで必要?
    • ・・・と書くとなぜ~~~が有効に?
    • この設定って最小限の Hello World で必要?

抽象化された設定

  • Spring Security の設定は高度に抽象化されている
  • 設定が簡潔になる一方で、裏で何が行われているかが分かりづらい
  • 仕組みの理解や、カスタマイズがしづらくなる

※個人の所感です


対象者

Hello World を通じて Spring Security の仕組みを学ぶことで、

  • Spring Security をこれから勉強する人の参考に(なれるように)
  • 仕組みを知らずに Spring Security を使ってた人の参考に(なれるように)

Hello World アプリ(前提)

Spring Boot は使わない

  • Spring Security の基礎を学ぶのが目的
  • 素の Spring Security だけを使う

Java Config は使わない

  • xml で設定を記述する
  • 結局 Java Config もやってることは同じ

Servlet 3.0 の機能は使わない

  • Servlet 3.0 の機能を利用すれば web.xml なしで設定が可能
  • 仕組みの基礎を学ぶのが目的なので、こちらもやはり使わないようにする

Hello World アプリ(環境構築)

ソース

https://github.com/opengl-8080/spring-security-hello-world

動作確認環境

  • Java 1.8.0_121
  • Tomcat 8.0.35

war ファイルの入手

  • こちら から spring-security.war をダウンロード
  • ソースからビルドする場合は、ソースをダウンロードしてプロジェクトのルートで gradlew war を実行。

動作確認

  • Tomcat に spring-security.war をデプロイ
  • http://localhost:8080/spring-security にアクセス

Hello World アプリ(動作)

http://localhost:8080/spring-security にアクセス

spring-security.jpg

User, Password に foo と入力してログイン

spring-security.jpg

403 エラーになる

次は bar でログイン

spring-security.jpg

spring-security.jpg

index ページが表示される。

logout ボタンをクリックすればログアウトができる。


Hello World アプリ(実装内容)

ファイル構成
|-build.gradle : Gradle のビルドファイル
|
`-src/main/webapp/
  |
  |-index.jsp : インデックスページ
  |
  `-WEB-INF/
    |
    |-applicationContext.xml : Spring 設定ファイル
    |
    `-web.xml : Servlet 設定ファイル
  • 全4ファイル
    • 1つはビルドファイルなので、実際デプロイされるのは3ファイル
  • Java ソース一切なしの超シンプル構成
build.gradle
apply plugin: 'war'

sourceCompatibility = '1.8'
targetCompatibility = '1.8'
compileJava.options.encoding = 'UTF-8'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.springframework.security:spring-security-web:4.2.1.RELEASE'
    compile 'org.springframework.security:spring-security-config:4.2.1.RELEASE'
}

war.baseName = 'spring-security'

task wrapper(type: Wrapper) {
    gradleVersion = '3.2.1'
}
index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>
      Hello Spring Security!!
    </title>
  </head>
  <body>
    <h1>
      Hello Spring Security!!
    </h1>

    <form action="logout" method="post">
      <input type="submit"
             value="logout" />
      <input type="hidden"
             name="${_csrf.parameterName}"
             value="${_csrf.token}" />
    </form>
  </body>
</html>
  • ログイン後に表示されるトップページ
  • メッセージとログアウトボタンがあるだけ
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

  <filter>
    <filter-name>
      springSecurityFilterChain
    </filter-name>
    <filter-class>
      org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
  </filter>

  <filter-mapping>
    <filter-name>
      springSecurityFilterChain
    </filter-name>
    <url-pattern>
      /*
    </url-pattern>
  </filter-mapping>
</web-app>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/security
         http://www.springframework.org/schema/security/spring-security.xsd">

  <sec:http>
    <sec:intercept-url
            pattern="/login"
            access="permitAll" />
    <sec:intercept-url
            pattern="/**"
            access="isAuthenticated() and hasAuthority('BAR')" />
    <sec:form-login />
    <sec:logout />
  </sec:http>

  <sec:authentication-manager>
    <sec:authentication-provider>
      <sec:user-service>
        <sec:user name="foo"
                  password="foo"
                  authorities="" />
        <sec:user name="bar"
                  password="bar"
                  authorities="BAR" />
      </sec:user-service>
    </sec:authentication-provider>
  </sec:authentication-manager>
</beans>

Hello World を読み解く

  1. サーバー起動~リクエスト受付
  2. Spring Security の入り口
  3. ログイン処理
  4. アクセス制御
  5. ログアウト処理

Hello World を読み解く

  1. サーバー起動~リクエスト受付
  2. Spring Security の入り口
  3. ログイン処理
  4. アクセス制御
  5. ログアウト処理

Spring コンテナの初期化

web.xml
<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>
  • <listener>
    • Servlet の機能で、アプリケーション起動時に実行する処理を定義できる
  • ContextLoaderListener
    • Spring コンテナを初期化するクラス
    • デフォルトで XmlWebApplicationContext が使用される
    • 設定ファイルとして WEB-INF/applicationContext.xml が使用される

DelegatingFilterProxy の登録

web.xml
  <filter>
    <filter-name>
      springSecurityFilterChain
    </filter-name>
    <filter-class>
      org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
  </filter>

  <filter-mapping>
    <filter-name>
      springSecurityFilterChain
    </filter-name>
    <url-pattern>
      /*
    </url-pattern>
  </filter-mapping>
  • DelegatingFilterProxy という Filter を springSecurityFilterChain という名前で登録
    • Filter は Servlet の提供する機能
    • リクエストの前後に任意の処理を挟むことができる
  • url-pattern/* を指定して、全てのリクエストを処理

DelegatingFilterProxy の役割

DelegatingFilterProxyの役割.png

  • DelegatingFilterProxy は、 Spring コンテナから次の条件に一致する Bean を検索する
    • Bean の名前が自身の Filter 名(springSecurityFilterChain)と一致する
    • javax.servlet.Filter インターフェースを実装している
  • 取得した Bean に処理を委譲する
  • DelegatingFilterProxy が処理を委譲したクラスは Spring コンテナから取得した Bean なので、 Spring コンテナの機能を利用することができる
    • DI
    • AOP
    • etc...
  • DelegatingFilterProxy の役割は、 Servlet コンテナと Spring コンテナの橋渡し

Spring Security の設定

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>

  <sec:http>
    <sec:intercept-url
            pattern="/login"
            access="permitAll" />
    <sec:intercept-url
            pattern="/**"
            access="isAuthenticated() and hasAuthority('BAR')" />
    <sec:form-login />
    <sec:logout />
  </sec:http>

  ...
  • applicationContext.xml は Spring の設定ファイル
    • <bean> タグを使って Bean を定義する
    • Spring Security 専用の設定ファイルというわけではない
  • Spring Security の設定を簡潔に記述できるようにするため、専用のタグが用意されている
    • リファレンスでは namespace と呼んでいる
    • xmlns:sec で読み込んでいる

<http> が肝

applicationContext.xml
  <sec:http>
    ...
  </sec:http>
  • この <http> が Spring Security の設定の肝
  • 重要な Bean が大量に登録される

FilterChainProxy

  • <http> タグが登録する Bean の1つ
  • Filter インターフェースを継承している
  • springSecurityFilterChain という名前で Spring コンテナに登録される
  • DelegatingFilterProxy が委譲する Bean の正体

まとめ (サーバー起動~リクエスト受付)

test

  1. サーブレットコンテナが起動し、 web.xmlListener として登録されている ContextLoaderListener が実行される。
  2. XmlWebApplicationContext のインスタンスが生成され、 /WEB-INF/applicationContext.xml が読み込まれる。
  3. <http> タグによって FilterChainProxy のインスタンスが "springSecurityFilterChain" という名前で Spring コンテナに登録される。
  4. web.xmlFilter として登録されている DelegateFilterProxy が、サーブレットコンテナによって生成される。
  5. リクエストがあると、 DelegateFilterProxy が呼ばれ、自身の名前("springSecurityFilterChain")で Spring コンテナから Bean を取得する(FilterChainProxy が取得される)。
  6. FilterChainProxy に処理が委譲される。

※分かりやすさ優先のため厳密には正しくないところもあります。雰囲気で見てください。


Hello World を読み解く

  1. サーバー起動~リクエスト受付
  2. Spring Security の入り口
  3. ログイン処理
  4. アクセス制御
  5. ログアウト処理

SecurityFilterChain

  • <http> が登録する重要なクラスの1つ
  • 名前の通り、 Filter を Chain (連鎖)させている
  • FilterChainProxy は、受け取ったリクエストを SecurityFilterChain が持つ Filter 達に委譲する
  • デフォルトで登録される Filter の例
    • SecurityContextPersistenceFilter
    • CsrfFilter
    • AnonymousAuthenticationFilter
    • ExceptionTranslationFilter
    • FilterSecurityInterceptor
    • etc...

Spring Security と Filter

SpringSecurityとFilter.jpg

  • Spring Security は Filter の組み合わせで実現されている
  • 機能ごとに Filter が用意されており、その FilterSecurityFilterChain に登録するかどうかで機能の有効・無効を切り替えられる

URL パターンごとの SecurityFilterChain

patternごとのSecurityFilterChain.jpg

  • SecurityFilterChain は URL パターン単位で定義することができる
    • /api/** にマッチする URL へのアクセスの場合は REST API 用に設定した SecurityFilterChain を、
    • それ以外の URL (/**) へのアクセスは、通常の画面アクセス用に設定した SecurityFilterChain を使用する
    • といったことができる
  • 例えば、「Form ログイン」のような機能は REST API でのアクセスでは不要になる

設定ファイルは次のようになる。

applicationContext.xml
  <sec:http pattern="/api/**">
    ...
  </sec:http>

  <sec:http pattern="/**">
    ...
  </sec:http>
  • <http> タグの pattern 属性で指定する
    (Ant 形式で指定できる)
  • 設定は上から順番に適用されるので、より限定的な設定をしているものを上に持ってくる
    /** の設定が /api/** より上にあると、 /api/** へのアクセスが先に /** の設定にマッチしてしまう)

まとめ (Spring Security の入り口)

  • <http> は、 SecurityFilterChain を Bean として登録する
  • SecurityFilterChain は、複数の Filter を保持している
  • Spring Security は、機能ごとに Filter が用意されている
  • Filter を組み合わせることで、必要な機能だけを持つ SecurityFilterChain を定義できる
  • SecurityFilterChain は URL パターン単位で定義できるので、
    • REST API 用の SecurityFilterChain
    • 通常の画面アクセス用の SecurityFilterChain
      という設定ができる

patternごとのSecurityFilterChain.jpg


Hello World を読み解く

  1. サーバー起動~リクエスト受付
  2. Spring Security の入り口
  3. ログイン処理
  4. アクセス制御
  5. ログアウト処理

Form ログインの有効化

applicationContext.xml
  <sec:http>
    ...
    <sec:form-login />
    ...
  </sec:http>
  • <form-login> タグを追加すると、 Form ログインが有効になる
  • Form ログインで必要になる FilterSecurityFilterChain に追加される

デフォルトのログインページ

spring-security.jpg

  • <form-login>login-page 属性が指定されていない場合、 DefaultLoginPageGeneratingFilter という Filter が登録される
  • /login に GET メソッドのリクエストがあると簡易なログインページを生成して返す
  • 動作確認をサクッと試したい場合に便利
    • Remember-Me 認証を有効にしたら自動的に Remember-Me 用のチェックボックスが追加されたりする

ログインリクエストの処理

  • ログイン処理は UsernamePasswordAuthenticationFilter という Filter によって行われる
  • /login に POST メソッドによるリクエストがくると、認証処理を開始する
  • ただし、実際の認証処理は AuthenticationManager に委譲する

AuthenticationManagerに委譲.png

ここから「委譲」がたくさん出てきてややこしいので注意!


AuthenticationManager

applicationContext.xml
  <sec:authentication-manager><sec:authentication-provider>
      <sec:user-service>
        <sec:user name="foo" ... />
        <sec:user name="bar" ... />
      </sec:user-service>
    </sec:authentication-provider>
  </sec:authentication-manager>
  • <authentication-manager> タグを宣言することで、 AuthenticationManager の実装クラスである ProviderManager が Spring コンテナに登録される
  • 認証処理の入り口となるクラス
  • ただし、 ProviderManager 自身は認証処理は行わず、 AuthenticationProvider委譲する

ProviderManagerとAuthenticationProvider.png


ProviderManager と AuthenticationProvider

AuthenticationProviderの実装クラス達.png

  • AuthenticationProvider は、認証の種類ごとに多くの実装クラスが存在している
  • ProviderManager はアプリケーションがサポートする認証方式に従い、複数の AuthenticationProvider のインスタンスを保持している
  • それぞれの AuthenticationProvider に対して、現在の認証リクエストがサポート対象かどうかを判断させ、サポートしている場合に AuthenticationProvider による認証処理が行われる
  • ProviderManager は、複数の AuthenticationProvider をまとめあげ管理する役割を担っている(まさに ProviderManager

パスワード認証を行う AuthenticationProvider

applicationContext.xml
  <sec:authentication-manager>
    <sec:authentication-provider><sec:user-service>
        <sec:user name="foo" ... />
        <sec:user name="bar" ... />
      </sec:user-service>
    </sec:authentication-provider>
  </sec:authentication-manager>
  • <authentication-provider> タグを使用することで、 DaoAuthenticationProvider というクラスが AuthenticationProvider の実装として登録される
  • DaoAuthenticationProvider は、ユーザー名とパスワードの組み合わせを使った認証処理を行う
  • その際、ユーザー情報の取得に Dao (Data Access Object) を使用する
  • Dao に当たる部分は、 UserDetailsService委譲する

UserDetailsServiceに委譲.png


UserDetailsService

UserDetailsService
public interface UserDetailsService {

    UserDetails
        loadUserByUsername(String username)
            throws UsernameNotFoundException;
}
  • ユーザー名をもとにユーザー情報(UserDetails)を返すメソッドを持つ
  • ユーザーが見つからなかった場合は UsernameNotFoundException をスローする
  • Spring Security にはこのインターフェースを実装したクラスがいくつか用意されている

InMemoryUserDetailsManager

メモリ内にユーザー情報を保存しておく実装

JdbcUserDetailsManager

JDBC 経由でデータベースからユーザー情報を検索してくる実装


InMemoryUserDetailsManager を使用する

applicationContext.xml
  <sec:authentication-manager>
    <sec:authentication-provider>
      <sec:user-service><sec:user name="foo" ... />
        <sec:user name="bar" ... />
      </sec:user-service>
    </sec:authentication-provider>
  </sec:authentication-manager>
  • <user-service> タグを使用すると、 UserDetailsService の実装として InMemoryUserDetailsManager が Spring コンテナに登録される

UserDetails

UserDetails.java
public interface UserDetails extends Serializable {

    String getUsername();
    String getPassword();
    Collection<? extends GrantedAuthority>
        getAuthorities();

    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();
}
  • UserDetails は、ログインユーザーの詳細情報を提供するインターフェース
  • ユーザー名やパスワード、付与された権限のコレクション、期限切れやロックなどの状態を取得できる
  • このインターフェースを実装したクラスとして、 User というクラスが用意されている

User を使用する

applicationContext.xml
  <sec:authentication-manager>
    <sec:authentication-provider>
      <sec:user-service>
        <sec:user name="foo" ... /><sec:user name="bar" ... /></sec:user-service>
    </sec:authentication-provider>
  </sec:authentication-manager>
  • <user> タグを使用すると、 User クラスを使ってユーザー情報が生成される
  • 生成されたユーザー情報は、 <user-service> すなわち InMemoryUserDetailsManager に保存される

ここまでの流れを整理

ログイン処理整理.png

  1. /login に POST リクエストがくると、 UsernamePasswordAuthenticationFilter が認証処理を行う
  2. 認証処理は AuthenticationManager に委譲される
  3. AuthenticationManager の実装クラスである ProviderManager は、所有する AuthenticationProvider に認証処理を委譲する
  4. <authentication-provider> タグで登録された DaoAuthenticationProvider は、ユーザー名とパスワードをもとに認証処理を行う
  5. その際、ユーザー情報の検索は UserDetailsService に委譲する
  6. <user-service> タグで登録された InMemoryUserDetailsManager は、 <user> タグで定義されたユーザー情報(UserDetails)をメモリ上に保存している

上記の関係性が、下の設定に込められている。

applicationContext.xml
  <sec:authentication-manager>
    <sec:authentication-provider>
      <sec:user-service>
        <sec:user name="foo" ... />
        <sec:user name="bar" ... />
      </sec:user-service>
    </sec:authentication-provider>
  </sec:authentication-manager>

認証に成功したら

AuthenticationProvider.java
public interface AuthenticationProvider {

    Authentication authenticate(Authentication authentication)
        throws AuthenticationException;
}
  • AuthenticationProvider の認証処理が成功すると、ログインしたユーザーの情報を保持した Authentication オブジェクトが返却される
  • この Authentication オブジェクトはセッションに保存され、次回以降のリクエストなどで参照されるようになる

まとめ (ログイン処理)

  • <form-login> で Form 認証が有効になる
  • UsernamePasswordAuthenticationFilter が追加され、認証処理を開始する
  • AuthenticationManager は認証処理を制御する
  • AuthenticationProvider が具体的な認証処理を行う
  • UserDetailsService はユーザー情報を検索する Dao
  • UserDetails はユーザーの詳細情報を提供する
  • 認証に成功すると、 Authentication オブジェクトがセッションに保存される

Hello World を読み解く

  1. サーバー起動~リクエスト受付
  2. Spring Security の入り口
  3. ログイン処理
  4. アクセス制御
  5. ログアウト処理

FilterSecurityInterceptor

  • <http> タグを定義することで追加される重要な Filter の1つ
  • セキュアオブジェクトの処理を実行する前後に処理を挟む
  • HTTP リクエストに関するアクセス制御は、この FilterSecurityInterceptor の中で開始される

セキュアオブジェクト

  • セキュリティ保護対象 のことを、 Spring Security のリファレンスでは セキュアオブジェクト(Secure Object) と呼んでいる
  • 「Object」とあるが、特定の Java オブジェクトのことではなく、「対象」という本来の Object の意味で使われている(たぶん)
  • 「特定の URL への HTTP リクエスト」や「メソッドの実行」などがセキュアオブジェクトにあたる

アクセス制御の委譲

AccessDecisionManagerに委譲.png

  • FilterSecurityInterceptor 自身はアクセス制御についてのチェックは行わない
  • アクセス制御の判定は AccessDecisionManager に委譲する

投票によるアクセス制御

投票によるアクセス制御

  • Spring Security が提供する AccessDecisionManager の実装クラスは、「投票」によってアクセス制御を行う
  • AccessDecisionManagerAccessDecisionVoter にアクセスの可否を投票させる
    • 付与:アクセス可
    • 拒否:アクセス不可
    • 棄権:サポート対象外
  • AccessDecisionManager は、投票結果を集計して結論を出す
    • 可の場合は何もしない
    • 不可の場合は AccessDeniedException をスローする

AccessDecisionManager の実装クラス

AccessDecisionManagerと実装クラス.png

  • AccessDecisionManager には実装クラスが3つ用意されている
  • AffirmativeBased
    • 「付与」が1つでもあればアクセス可
    • デフォルトはこのクラスが使用される
  • ConsensusBased
    • 「拒否」<「付与」の場合はアクセス可
  • UnanimousBased
    • 全て「付与」の場合はアクセス可

式ベースのアクセス制御

applicationContext.xml
  <sec:http>
    <sec:intercept-url
            pattern="/login"
            access="permitAll" />
    <sec:intercept-url
            pattern="/**"
            access="isAuthenticated() and hasAuthority('BAR')" />
    ...
  </sec:http>
  • AccessDecisionVoter の実装には、デフォルトでは WebExpressionVoter が使用される
  • Expression すなわち式ベースでアクセス可否を制御する
  • アクセス制御の式は <intercept-url> タグの access 属性で指定する
  • pattern 属性には、その制御を適用する URL のパターンを指定する

Spring Expression Language (SpEL)

applicationContext.xml
  access="permitAll"
  access="isAuthenticated() and hasAuthority('BAR')"
  • アクセス制御の式には Spring Expression Language という Spring 独自の式言語を使用する
  • 式を評価した結果が boolean になるようにする
    • true ならアクセス可
    • false ならアクセス不可
  • Spring Security 用に関数や定数が拡張されている
    • permitAll:常に true
    • isAuthenticated():認証済みなら true
    • hasAuthority():指定した権限を持っていれば true

まとめ (アクセス制御)

  • FilterSecurityInterceptor でアクセス制御が開始される
  • 実際の制御は AccessDecisionManager が行う
  • 標準の実装は「投票」によってアクセス可否を判定している
  • AccessDecisionVoter が投票を行い、 AccessDecisionManager が投票結果を集計し結論を出す
  • デフォルトでは WebExpressionVoter による SpEL を利用した式ベースのアクセス制御が有効になっている

Hello World を読み解く

  1. サーバー起動~リクエスト受付
  2. Spring Security の入り口
  3. ログイン処理
  4. アクセス制御
  5. ログアウト処理

ログアウトを有効にする

applicationContext.xml
  <sec:http>
    ...
    <sec:logout />
  </sec:http>
  • <logout> タグを使用すると、 LogoutFilter が追加される
  • /logout に POST リクエストがくると、 LogoutFilter がログアウトの処理を行う

全体ふりかえり

サーバー起動~リクエスト受付

test

Spring Security の入り口

SpringSecurityとFilter.jpg

ログイン処理

ログイン処理整理.png

アクセス制御

投票によるアクセス制御


これだけの意味がこの設定に込められている

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app ...>
  <listener>
    <listener-class>
      org.springframework.web.context.ContextLoaderListener
    </listener-class>
  </listener>

  <filter>
    <filter-name>
      springSecurityFilterChain
    </filter-name>
    <filter-class>
      org.springframework.web.filter.DelegatingFilterProxy
    </filter-class>
  </filter>

  <filter-mapping>
    <filter-name>
      springSecurityFilterChain
    </filter-name>
    <url-pattern>
      /*
    </url-pattern>
  </filter-mapping>
</web-app>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:sec="http://www.springframework.org/schema/security"
       ...>

  <sec:http>
    <sec:intercept-url
            pattern="/login"
            access="permitAll" />
    <sec:intercept-url
            pattern="/**"
            access="isAuthenticated() and hasAuthority('BAR')" />
    <sec:form-login />
    <sec:logout />
  </sec:http>

  <sec:authentication-manager>
    <sec:authentication-provider>
      <sec:user-service>
        <sec:user name="foo"
                  password="foo"
                  authorities="" />
        <sec:user name="bar"
                  password="bar"
                  authorities="BAR" />
      </sec:user-service>
    </sec:authentication-provider>
  </sec:authentication-manager>
</beans>

いかがでしたでしょうか?
Spring Security 簡単そうと思いました?


【悲報】まだ Hello World


今日話していない機能とか要素とか

  • GrantedAuthority
  • Role の階層化
  • メソッドのセキュリティ
  • CSRF
  • Memember-Me
  • パスワードエンコード
  • 各種カスタマイズ方法
  • テスト
  • etc...

でも、今日の話が知識の下地としてできていれば
乗り越えられるはず(たぶん)


以上