1. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
これで怖くない!?
コードリーディングで学ぶ
Spring Security
(株)カサレアル 多⽥真敏
2018年11⽉30⽇
中央線Meetup #2
1
2. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
このセッションについて
▸ Spring Securityの認証・認可の仕組みを、
ソースコードをもとに解説します
▸ 中級者向け
▸ ライブラリのソースコードを読んだことがある⽅
▸ 認証と認可の区別がつく⽅
▸ サーブレットAPIが分かる⽅
2
3. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
⾃⼰紹介
▸ 多⽥真敏(@suke_masa)
▸ 研修トレーナー@カサレアル
▸ Spring / Java EE / Microservices
/ Cloud Foundry
▸ Pivotal認定講師
▸ ⽇本Springユーザ会スタッフ
▸ ⽇本GlassFishユーザー会運営メンバー
3
4. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
Thymeleaf 3のドキュメントを(ちょっと)和訳しました!
4
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf_ja.html
5. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
⽬次
① Spring Securityとは
② アーキテクチャをざっくり理解する
③ ソースコードを読んでより深く理解する
④ おまけ
5
6. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
⽬次
① Spring Securityとは
② アーキテクチャをざっくり理解する
③ ソースコードを読んでより深く理解する
④ おまけ
6
7. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
Spring Securityとは
▸ Springのサブプロジェクト
▸ 認証・認可を中⼼に、セキュリティにまつわる様々な
機能を提供する
▸ 何重ものサーブレットフィルターで
機能を実現している
▸ 5.0でリアクティブ対応機能を
新規に開発した
7
8. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
Spring Securityの歴史
8
年 説明
2003 Acegi Securityとして誕⽣
2004 Apache Licenseで公開→Springに取り込まれる
2008 Spring Security 2.0としてリリース
2009 Spring Security 3.0
2015 Spring Security 4.0
2017 Spring Security 5.0
2018 Spring Security 5.1 ←今ココ
Thanks to Wikipedia
9. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
Spring Securityは複雑?
▸ 数あるSpringプロダクトの中でもかなり複雑な
⽅だと思います(発表者の主観)
9
⼤まかにでも内部のアーキテクチャを理解すれば
怖くなくなる・・・かも?
10. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
⽬次
① Spring Securityとは
② アーキテクチャをざっくり理解する
③ ソースコードを読んでより深く理解する
④ おまけ
10
11. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
今回は
▸ 従来のサーブレット版を前提に解説します
▸ リアクティブ版は今回はスコープ外
11
12. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
ざっくり分かるSpring Securityアーキテクチャ
12
springSecurityFilterChain
(フィルター)
Filter
1
Filter
2
Filter
N
Authentication
Manager
(認証)
AccessDecision
Manager
(認可)
リクエスト
レスポンス
サーブ
レット
…
※本当はspringSecurityFilterChainが2つあるのですが、
時間短縮のため省略しています
13. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
フィルター群
13
...
DEBUG: /login at position 1 of 12 ...: 'WebAsyncManagerIntegrationFilter'
DEBUG: /login at position 2 of 12 ...: 'SecurityContextPersistenceFilter'
DEBUG: /login at position 3 of 12 ...: 'HeaderWriterFilter'
DEBUG: /login at position 4 of 12 ...: 'CsrfFilter'
DEBUG: /login at position 5 of 12 ...: 'LogoutFilter'
DEBUG: /login at position 6 of 12 ...: 'UsernamePasswordAuthenticationFilter'
DEBUG: /login at position 7 of 12 ...: 'RequestCacheAwareFilter'
DEBUG: /login at position 8 of 12 ...: 'SecurityContextHolderAwareRequestFilter'
DEBUG: /login at position 9 of 12 ...: 'AnonymousAuthenticationFilter'
DEBUG: /login at position 10 of 12 ...: 'SessionManagementFilter'
DEBUG: /login at position 11 of 12 ...: 'ExceptionTranslationFilter'
DEBUG: /login at position 12 of 12 ...: 'FilterSecurityInterceptor'
...
▸ application.propertiesで
logging.level.org.springframework.security=debug
とするとログに出⼒される
14. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
重要なフィルター抜粋
14
クラス名 説明
① SecurityContext
PersistenceFilter
セッションに格納していた
SecurityContextをThreadLocalに移す
② LogoutFilter ログアウト処理を⾏う
③
UsernamePassword
AuthenticationFilter
フォーム認証を⾏う
④
ExceptionTranslation
Filter
発⽣した例外を受け取ってエラー
画⾯を表⽰する
⑤
FilterSecurity
Interceptor
アクセス制限を⾏う
15. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
⽬次
① Spring Securityとは
② アーキテクチャをざっくり理解する
③ ソースコードを読んでより深く理解する
④ おまけ
15
16. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
Spring Securityコードリーディングのポイント
▸ 各フィルターから読むとよい
▸ 今回は前述のフィルター5つに絞って紹介
16
17. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
①SecurityContextPersistenceFilter(1/2)
17
// デフォルト実装はHttpSessionSecurityContextRepository
private SecurityContextRepository repo;
HttpRequestResponseHolder holder =
new HttpRequestResponseHolder(request, response);
// SecurityContextをHttpSessionから取り出す
SecurityContext contextBeforeChainExecution =
repo.loadContext(holder);
try {
// ThreadLocalにSecurityContextを保存する
SecurityContextHolder.setContext(contextBeforeChainExecution);
https://github.com/spring-projects/spring-security/blob/master/web/src/main/java/org/springframework/
security/web/context/SecurityContextPersistenceFilter.java#L98
33. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
Filterなの?Interceptorなの?
33
<<abstract>>
AbstractSecurity
Interceptor
FilterSecurity
Interceptor
MethodSecurity
Interceptor
<<interface>>
javax.servlet.
Filter
<<interface>>
org.aopalliance.intercept.
MethodInterceptor
フィルターとして実⾏される
(URL単位の認可制御)
AOPとして実⾏される
(メソッドへの認可制御)
34. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
AccessDecisionManagerの構造
34
<<interface>>
AccessDecision
Manager
Affirmative
Based
(1票でもあればOK)
Consensus
Based
(多数決)
Unanimous
Based
(全会⼀致)
<<interface>>
AccessDecision
Voter
*
意思決定者
投票者
35. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
⽬次
① Spring Securityとは
② アーキテクチャをざっくり理解する
③ ソースコードを読んでより深く理解する
④ おまけ
35
36. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
kawasimaさんのQiita
36https://qiita.com/kawasima/items/8dd7eda743f2fdcad78e
37. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
kawasimaさんのQiita
37https://qiita.com/kawasima/items/8dd7eda743f2fdcad78e
38. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
kawasimaさんのQiita
38https://qiita.com/kawasima/items/8dd7eda743f2fdcad78e
39. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
kawasimaさんのQiita
39https://qiita.com/kawasima/items/8dd7eda743f2fdcad78e
_⼈⼈⼈⼈⼈⼈⼈⼈⼈⼈⼈⼈⼈_
> 割愛させていただきます <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄
40. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
40
😭
しゃーない、
⾃分で作るか・・・
41. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
使⽤技術
41
▸ Ninja Framework
▸ FreeMarker
▸ JPA
▸ JSR 250 (@RolesAllowed)
▸ Spring MVC (w/Spring Boot)
▸ Thymeleaf
▸ JPA
▸ Spring Security
@kawasima @suke_masa
42. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
基本⽅針
▸ オペレーション=URL・メソッド
▸ 各オペレーションにパーミッションを指定
42
43. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
URL単位のアクセス許可
43
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http.authorizeRequests()
.mvcMatchers("/signup").permitAll()
.mvcMatchers(GET, "/issues/").hasAuthority("readIssue")
.mvcMatchers(GET, "/issue/new").hasAuthority("writeIssue")
.mvcMatchers(POST, "/issues/").hasAuthority("writeIssue")
.mvcMatchers("/users").hasAuthority("manageUser")
.anyRequest().authenticated();
...
}
...
}
URLパターンごとに
パーミッションを指定
44. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
ビジネスロジックのアクセス許可
44
@Service
public class IssueServiceImpl implements IssueService {
...
@PreAuthorize("hasAuthority('readIssue')")
@Transactional(readOnly = true)
public List<Issue> findAll() {
return issueRepository.findAll();
}
@PreAuthorize("hasAuthority('writeIssue')")
@Transactional
public void register(Issue issue, String account) {
issueRepository.register(issue, account);
}
}
AOPでパーミッションが
チェックされる
AOPで実⾏直前に
パーミッションをチェック
45. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
ビュー層での権限による出し分け
45
<html xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
...
<a href="#" class="header item">
RBAC Example
</a>
<a th:href="@{/}" sec:authorize="isAuthenticated()">
Home
</a>
<a th:href="@{/issues/}"
sec:authorize="isAuthenticated() and hasAuthority('readIssue')">
Issue
</a>
<a th:href="@{/users/}"
sec:authorize="isAuthenticated() and hasAuthority('manageUser')">
Users
</a>
...
パーミッションがある場合のみ
リンクを表⽰
(thymeleaf-extras-springsecurity5の機能)
46. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
ソースコード
▸ https://github.com/MasatoshiTada/rbac-
example-springsecurity
46
47. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
今⽇のまとめ
▸ Spring Security、なかなか複雑ですね
▸ でもコードリーディングって楽しいですね!
▸ 興味があればAuthenticationManagerや
AccessDecisionManagerも読むと⾯⽩いです
▸ RBACサンプルを作ったのでぜひ⾒てください!
47
48. (C) CASAREAL, Inc. All rights reserved.
#中央線Meetup
Enjoy Spring Security!!
▸ ご清聴ありがとうございました!
48