SIer だけど技術やりたいブログ

SpringSecurityでEL式を拡張してカスタムルールを作るときのメモ

Java SpringBoot SpringSecurity

SpringSecurityでカスタムルールを作る

SpringSecurityで提供されているEL式(hasRole()とか)で足りなくなった場合に、独自のEL式を作成する方法のメモ。

前の記事で作成してたプロジェクトからちょっとカスタマイズして作成。
SpringSecurityでFORM認証 - SIerだけど技術やりたいブログ

カスタムルール用のBeanを作る

コンテナからBeanとして認識されるように作る。

@Component
public class WebSecurity {
  private static int counter;

  /**
   * 2回アクセスがあるごとに一回アクセスを許可するカスタムルール
   */
  public boolean checkMyRule(Authentication auth, HttpServletRequest request) {
    if (auth == null) {
      return false;
    }
    Object principal = auth.getPrincipal();
      if (principal == null) {
        return false;
      } else {
        counter++;
        return (counter % 2 == 0) ? true : false;
      }
  }
}

カスタムルールを使う

重要なのはaccess部分だけ。
@webSecurity.checkMyRule…はSPEL式のBean参照。
引数のauthenticationとrequestはEL式の暗黙オブジェクト?なので、名前までしっかり合わせないといけない。

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.authorizeRequests()
      // カスタムルールを参照する
      .antMatchers("/admin/**").access("@webSecurity.checkMyRule(authentication,request)")
        .anyRequest().authenticated().and()
      .formLogin()
        .loginPage("/login")
        .defaultSuccessUrl("/home")
        .failureUrl("/login?error")
        .permitAll().and()
      .logout()
        .logoutUrl("/logout")
        .logoutSuccessUrl("/login?logout")
        .permitAll();
  }

宿題

EL式の引数に取れるオブジェクトには、他に何が使えるのかを詳しく調べる。
WebSecurityExpressionRootで定義されてるEL式(パラメータ名は下記リンク)と HttpServletRequest(パラメータ名はrequest)で定義されてるものはアクセス可能っぽい。

http://docs.spring.io/spring-security/site/docs/4.1.0.RC1/reference/htmlsingle/#el-common-built-in

参考

リファレンスにすべて載ってた。
http://docs.spring.io/spring-security/site/docs/4.1.0.RC1/reference/htmlsingle/#el-access-web-beans