Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
Spring Security 4.1 の新機能
2016/09/03
新日鉄住金ソリューションズ株式会社
井岡 正和
日本Springユーザ会
SpringOne Platform 2016 報告会
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
自己紹介
 井岡 正和 (いおか まさかず)
 Spring ベースの社内標準FW開発・保守担当
 SpringOne の参加は3回目
 プライベートでは、iOS・Android のアプリを開発
http://www.slideshare.net/KoUmetani/spring2015-56309694
去年もSpring Security 関連について
紹介させていただきました。
2
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
今日紹介する内容
 Spring Security 4.1 の新機能について
 CookieCsrfTokenRepository
 Content Security Policy
 @AuthenticationPrincipal
 Path Variables in Web Security Expressions
 Referring to Beans in Web Security Expressions
 MvcRequestMatcher
3
参考セッション: To Spring Security 4.1 and Beyond
セッションで使用されたコード: https://github.com/rwinch/spring-security-4.1-and-beyond
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
(おさらい) Spring Security の基本的な使い方
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// @formatter:off
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/assets/**", "/webjars/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
// @formatter:on
WebSecurityConfigurerAdapter を継承
@EnableWebSecurity を追加
configure をオーバーライド
リソースへのアクセス許可
Basic認証を有効
その他のアクセスに認証
自分で指定したインデントがIDEのフォーマッタで崩れてしまうが、
「// @formatter:off」と「// @formatter:on」で囲うことで、
その中のコードはフォーマッターがかからなくなる。
4
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
Spring Security 4.1 の
新機能について
5
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
CookieCsrfTokenRepository
6
 CSRF トークンを Cookie に格納できるようになった
 デフォルトでは「XSRF-TOKEN」に格納される
AngularJS では、Cookie に XSRF-TOKEN があると、
自動的に X-XSRF-TOKEN ヘッダを付けてくれるらしい
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/assets/**", "/webjars/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
CSRF の CsrfTokenRepository に、
CookieCsrfTokenRepository を指定
JavaScript 等から読み込む場合は、
withHttpOnlyFalse() によって
CsrfTokenRepository を取得する。
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
Content Security Policy
7
 Content Security Policy の設定ができるようになった
 XSS やデータインジェクション等の攻撃を対策できる
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/assets/**", "/webjars/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.headers()
.contentSecurityPolicy("default-src 'self' " +
"https://ajax.googleapis.com; " +
"style-src 'self' 'unsafe-inline'");
}
ヘッダに Content Security Policy を設定
contentSecurityPolicy() の後ろに「.reportOnly()」
を追加すると、ポリシー違反の通知のみになる。 ここでの設定では、
自身のドメインと「https://ajax.googleapis.com」を許可
スタイルについては自身のドメインとインラインの<style>要素のみ許可
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
@AuthenticationPrincipal (1/2)
8
 認証ユーザを Controller の引数で取得できるようになった
@RestController
public class SecurityController {
@RequestMapping(value = "/principal")
public ResponseEntity<User> currentPrincipal(@AuthenticationPrincipal User user) {
return new ResponseEntity<User>(user, HttpStatus.OK);
}
これだけ!
 以前は、下記のようにして取得していた
@RequestMapping(value = "/principal")
public ResponseEntity<User> currentPrincipal() {
User user =
(User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
@RequestMapping(value = "/principal")
public ResponseEntity<User> currentPrincipal(Authentication authentication) {
User user = (User) authentication.getPrincipal();
大変!
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
@AuthenticationPrincipal (2/2)
9
 ただし、@AuthenticationPrincipal は直接使用せず、
@CurrentUser のように意味が伝わるアノテーションを
作成して使用したほうが保守性が上がる
@RestController
public class SecurityController {
@RequestMapping(value = "/principal")
public ResponseEntity<User> currentPrincipal(@CurrentUser User user) {
return new ResponseEntity<User>(user, HttpStatus.OK);
}
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {
}
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
Path Variables in Web Security Expressions
10
 Web Security Expressions で Path Variable を
使用できるようになった
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/assets/**", "/webjars/**").permitAll()
.antMatchers("/users/{userId}").access("#userId == principal.id.toString()")
.anyRequest().authenticated()
.and()
.httpBasic();
}
@RequestMapping と同じで
中括弧で変数を指定
「#変数名」で使用できる
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
Referring to Beans in Web Security Expressions
11
 Web Security Expressions で Bean を
使用できるようになった
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/assets/**", "/webjars/**").permitAll()
.antMatchers("/users/{userId}").access("@authz.check(#userId,principal)")
.anyRequest().authenticated()
.and()
.httpBasic();
}
「@Bean名」で使用できる
@Component
public class Authz {
public boolean check(Long userId, User user) {
return userId.equals(user.getId());
}
}
「authz」というBean名で登録される
@PreAuthorize や@PostAuthorize 等でも Bean を使用できる
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
MvcRequestMatcher
12
 「/admin」のアクセス制限をした場合に、
「/admin/」からもアクセス制限できるようになった
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/assets/**", "/webjars/**").permitAll()
.mvcMatchers("/admin").denyAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
antMatchers ではなく、
mvcMatchers を使用する
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/assets/**", "/webjars/**").permitAll()
.antMatchers("/admin").denyAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
下記のように antMatchers("/admin").denyAll() とした場合は、
「/admin/」でアクセスできる
Copyright ©2016 NS Solutions Corporation. All Rights Reserved.
おわりに
13
 とても簡単にセキュリティ設定ができるので、
強固なアプリケーションを作ってください!
 他にもいろいろな機能が 4.1 で追加されています
 http://docs.spring.io/spring-
security/site/docs/current/reference/htmlsingle/#new
Copyright ©2016 NS Solutions Corporation. All Rights Reserved. 14
NS Solutions、NS(ロゴ)、NSSOLは、新日鉄住金ソリューションズ株式会社の登録商標です。
Javaは、米国ORACLE Corp.の登録商標です。
その他本文記載の会社名及び製品名は、それぞれ各社の商標又は登録商標です。

Spring Security 4.1 の新機能

  • 1.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. Spring Security 4.1 の新機能 2016/09/03 新日鉄住金ソリューションズ株式会社 井岡 正和 日本Springユーザ会 SpringOne Platform 2016 報告会
  • 2.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. 自己紹介  井岡 正和 (いおか まさかず)  Spring ベースの社内標準FW開発・保守担当  SpringOne の参加は3回目  プライベートでは、iOS・Android のアプリを開発 http://www.slideshare.net/KoUmetani/spring2015-56309694 去年もSpring Security 関連について 紹介させていただきました。 2
  • 3.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. 今日紹介する内容  Spring Security 4.1 の新機能について  CookieCsrfTokenRepository  Content Security Policy  @AuthenticationPrincipal  Path Variables in Web Security Expressions  Referring to Beans in Web Security Expressions  MvcRequestMatcher 3 参考セッション: To Spring Security 4.1 and Beyond セッションで使用されたコード: https://github.com/rwinch/spring-security-4.1-and-beyond
  • 4.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. (おさらい) Spring Security の基本的な使い方 @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { // @formatter:off @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/assets/**", "/webjars/**").permitAll() .anyRequest().authenticated() .and() .httpBasic(); } // @formatter:on WebSecurityConfigurerAdapter を継承 @EnableWebSecurity を追加 configure をオーバーライド リソースへのアクセス許可 Basic認証を有効 その他のアクセスに認証 自分で指定したインデントがIDEのフォーマッタで崩れてしまうが、 「// @formatter:off」と「// @formatter:on」で囲うことで、 その中のコードはフォーマッターがかからなくなる。 4
  • 5.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. Spring Security 4.1 の 新機能について 5
  • 6.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. CookieCsrfTokenRepository 6  CSRF トークンを Cookie に格納できるようになった  デフォルトでは「XSRF-TOKEN」に格納される AngularJS では、Cookie に XSRF-TOKEN があると、 自動的に X-XSRF-TOKEN ヘッダを付けてくれるらしい @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/assets/**", "/webjars/**").permitAll() .anyRequest().authenticated() .and() .httpBasic() .and() .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); } CSRF の CsrfTokenRepository に、 CookieCsrfTokenRepository を指定 JavaScript 等から読み込む場合は、 withHttpOnlyFalse() によって CsrfTokenRepository を取得する。
  • 7.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. Content Security Policy 7  Content Security Policy の設定ができるようになった  XSS やデータインジェクション等の攻撃を対策できる @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/assets/**", "/webjars/**").permitAll() .anyRequest().authenticated() .and() .httpBasic() .and() .headers() .contentSecurityPolicy("default-src 'self' " + "https://ajax.googleapis.com; " + "style-src 'self' 'unsafe-inline'"); } ヘッダに Content Security Policy を設定 contentSecurityPolicy() の後ろに「.reportOnly()」 を追加すると、ポリシー違反の通知のみになる。 ここでの設定では、 自身のドメインと「https://ajax.googleapis.com」を許可 スタイルについては自身のドメインとインラインの<style>要素のみ許可
  • 8.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. @AuthenticationPrincipal (1/2) 8  認証ユーザを Controller の引数で取得できるようになった @RestController public class SecurityController { @RequestMapping(value = "/principal") public ResponseEntity<User> currentPrincipal(@AuthenticationPrincipal User user) { return new ResponseEntity<User>(user, HttpStatus.OK); } これだけ!  以前は、下記のようにして取得していた @RequestMapping(value = "/principal") public ResponseEntity<User> currentPrincipal() { User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); @RequestMapping(value = "/principal") public ResponseEntity<User> currentPrincipal(Authentication authentication) { User user = (User) authentication.getPrincipal(); 大変!
  • 9.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. @AuthenticationPrincipal (2/2) 9  ただし、@AuthenticationPrincipal は直接使用せず、 @CurrentUser のように意味が伝わるアノテーションを 作成して使用したほうが保守性が上がる @RestController public class SecurityController { @RequestMapping(value = "/principal") public ResponseEntity<User> currentPrincipal(@CurrentUser User user) { return new ResponseEntity<User>(user, HttpStatus.OK); } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented @AuthenticationPrincipal public @interface CurrentUser { }
  • 10.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. Path Variables in Web Security Expressions 10  Web Security Expressions で Path Variable を 使用できるようになった @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/assets/**", "/webjars/**").permitAll() .antMatchers("/users/{userId}").access("#userId == principal.id.toString()") .anyRequest().authenticated() .and() .httpBasic(); } @RequestMapping と同じで 中括弧で変数を指定 「#変数名」で使用できる
  • 11.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. Referring to Beans in Web Security Expressions 11  Web Security Expressions で Bean を 使用できるようになった @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/assets/**", "/webjars/**").permitAll() .antMatchers("/users/{userId}").access("@authz.check(#userId,principal)") .anyRequest().authenticated() .and() .httpBasic(); } 「@Bean名」で使用できる @Component public class Authz { public boolean check(Long userId, User user) { return userId.equals(user.getId()); } } 「authz」というBean名で登録される @PreAuthorize や@PostAuthorize 等でも Bean を使用できる
  • 12.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. MvcRequestMatcher 12  「/admin」のアクセス制限をした場合に、 「/admin/」からもアクセス制限できるようになった @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/assets/**", "/webjars/**").permitAll() .mvcMatchers("/admin").denyAll() .anyRequest().authenticated() .and() .httpBasic(); } antMatchers ではなく、 mvcMatchers を使用する @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/assets/**", "/webjars/**").permitAll() .antMatchers("/admin").denyAll() .anyRequest().authenticated() .and() .httpBasic(); } 下記のように antMatchers("/admin").denyAll() とした場合は、 「/admin/」でアクセスできる
  • 13.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. おわりに 13  とても簡単にセキュリティ設定ができるので、 強固なアプリケーションを作ってください!  他にもいろいろな機能が 4.1 で追加されています  http://docs.spring.io/spring- security/site/docs/current/reference/htmlsingle/#new
  • 14.
    Copyright ©2016 NSSolutions Corporation. All Rights Reserved. 14 NS Solutions、NS(ロゴ)、NSSOLは、新日鉄住金ソリューションズ株式会社の登録商標です。 Javaは、米国ORACLE Corp.の登録商標です。 その他本文記載の会社名及び製品名は、それぞれ各社の商標又は登録商標です。