leftovers...

about grails groovy

Grails Spring Security Coreプラグイン2.0の話を少し。

Grails Spring Security Coreプラグインの新バージョン2.0がまもなくRCとれてリリースになりそうです。
合宿から延長戦で、Grails 2.3.xを検証している流れでドキュメントからかいつまんでまとめてみました。
#昔自分が作った某プラグインがベースなのでドキュメントに名前載ってるから責任を感じてます。ウソです。

プラグインのページ
http://grails.org/plugin/spring-security-core
ドキュメント。
http://grails-plugins.github.io/grails-spring-security-core/docs/manual/


現状中身的には、Spring Security 3.2.0.RC1が使用されています。きっとRCが外れたら、プラグインもRCが外れるのだと期待しています。

では、ドキュメントの「What's New in Version 2.0」の中を、中途半端に動作確認しながら追ったので、そのまとめを!


悲観的ロックダウン
訳したらなんかかっこいいのかかっこわるいのかなネーミングになってしまった!→「悲観的ロックダウン」
失恋ソングか何かでは無いのは確かで。。
Rock!じゃないですよ!Lockですよ!

英語だと"Pessimistic Lockdown"


基礎セキュリティを高めるためにデフォルトでアクセス禁止。ちゃんとコントローラとかアクションに@Secured(['ROLE_USER'])書こうぜ
めんどかったら、rejectIfNoRule設定で変更できます。

grails.plugin.springsecurity.rejectIfNoRule = false

もう1個追加された設定が、fii.rejectPublicInvocationsで(確認してないから何とも)、
この機能は、マップされてないURLでIllegalArgumentExceptionがトリガーされてエラーページに飛ばされるとか。ちょっとかっこわるい実装だけど、設定ミスとかがわかりやすいから便利だとか(ドキュメント談)。外したいときは。

grails.plugin.springsecurity.fii.rejectPublicInvocations = false

デフォルトの悲観的ロックダウンに準拠するなら、アクセス制限の設定をしっかりしないとダメですね。jsとかcssとかも、一応s2-quickstartすると以下の内容がConfig.groovyに設定されます。が、しかし!以前のバージョンから更新した場合はstaticRulesに以下から必要な物を追加しないとgdgdになります。

grails.plugin.springsecurity.controllerAnnotations.staticRules = [
	'/':                              ['permitAll'],
	'/index':                         ['permitAll'],
	'/index.gsp':                     ['permitAll'],
	'/**/js/**':                      ['permitAll'],
	'/**/css/**':                     ['permitAll'],
	'/**/images/**':                  ['permitAll'],
	'/**/favicon.ico':                ['permitAll']
]


細かなのをザックリと

  • GETでログアウトするときに405がでるよ。 grails.plugin.springsecurity.logout.postOnly = false 入れましょう。
  • Configで、grails.plugins.springsecurityだったのが"s"がとれて、grails.plugin.springsecurityに変わったよ。古い定義入れるとコンソールで注意される。
  • パッケージも変わったよ grails.plugin.springsecurity
  • パスワード用ハッシュアルゴリズムのデフォルトがbcryptになった。PBKDF2もサポートされたよ。もちろん今までと同様のMDアルゴリズムも対応してるよ。grails.plugin.springsecurity.password.algorithmで設定が変更できます。
  • セッション固定攻撃制御 (Session Fixation Prevention)はデフォルトでONです!セッションをあれしてハイジャックするあれです。

しないと思うけどOFFにするには

grails.plugin.springsecurity.useSessionFixationPrevention = false 
  • Hibernate依存からの開放!もうMongo用のコード用意しなくてもオッケー。s2-quickstartで生成されるドメインのコードでHQLが使用されていた部分がwhereクエリへ変更された。


@Secured アノテーション
(重要)クロージャで定義されたアクションでは使えなくなったよ。つうか、Grails 2.0からはアクションをメソッドで書くのもう慣れたよねー。
アノテーションの追加機能として、RESTとかからのアクセスに使うために、HTTPメソッドが定義できるようになったとか。

@Secured(value=["hasRole('ROLE_ADMIN')"], httpMethod='POST')
def someMethod() {
   …
}

あと、アノテーションに、アクセスチェックで実行される、boolean値を返すクロージャをかけるようになった。ctxとしてApplicationContextが呼べたり、requestもとれたり。

@Secured(closure = {
   assert request
   assert ctx
   authentication.name == 'admin1'
})
def someMethod() {
   …
}


@Authorities アノテーション
@Authoritiesを使ってサックリとROLEをまとめて扱えるように。
詳しくはBurtのブログを見れば良いと思う。 http://burtbeckwith.com/blog/?p=1398
かいつまんで説明すると。
プロジェクトルートにロールの定義をした、roles.propertiesを置く。
中身はこんなやつ。

admins=ROLE_ADMIN, ROLE_SUPERADMIN
switchUser=ROLE_SWITCH_USER
editors=ROLE_EDITOR, ROLE_ADMIN

そしてコントローラに。

@Authorities('admins')
class SecureController {
 
   @Authorities('editors')
   def someAction() {
      ...
   }
}

あとは、コンパイル時にASTであれのあれしてくれるという代物です。動作的には、以下と同じになると。あらDRY!

@Secured(['ROLE_ADMIN', 'ROLE_SUPERADMIN'])
class SecureController {
 
   @Secured(['ROLE_EDITOR', 'ROLE_ADMIN'])
   def someAction() {
      ...
   }
}


SecurityContextHolderストラテジー
SecurityContextHolderをThreadLocal(デフォルト)に置くかInheritableThreadLocalにするか、設定できるようになりましたー。
Configで設定できるよー。grails.plugin.springsecurity.sch.strategyNameを"MODE_THREADLOCAL"(デフォルト)でThreadLocalになって、"MODE_INHERITABLETHREADLOCAL"にするとInheritableThreadLocalに。他にSecurityContextHolderStrategyを実装したクラス名も設定できます。

デバッグフィルター
org.springframework.security.config.debug.DebugFilterベースのデバッグフィルタが使えます。

Log4j設定にこれを追加して。

info 'grails.plugin.springsecurity.web.filter.DebugFilter'

環境設定(environmentsブロック)にgrails.plugin.springsecurity.debug.useFilterを追加。

environments {
   development {
      grails.logging.jul.usebridge = true
      grails.plugin.springsecurity.debug.useFilter = true
   }
   production {
      grails.logging.jul.usebridge = false
   }
}


セッションへのユーザ名保存
Spring Security 3.0 以前は、セッションに"SPRING_SECURITY_LAST_USERNAME"が保存されていましたが、これが無くなりました。プラグインではgrails.plugin.springsecurity.apf.storeLastUsernameを設定すれば(デフォルトはfalse)使用できます。
あとユーザ名は保存時にエスケープされないから、取り出して表示するときはXSSきをつけましょう!


AuthenticationDetailsSourceの話。
以前はauthenticationDetails.authClassを設定することでauthenticationDetailsSourceから生成されるUserDetailsクラスを変更出来たのですが、Spring Security 3.2ではWebAuthenticationDetailsSourceが常にWebAuthenticationDetailsを返すため、できなくなりました。
ただし、AuthenticationDetailsSourceを実装したクラスを作成することで、UserDetailsクラスをカスタマイズできます。

package com.mycompany;
import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.AuthenticationDetailsSource;

public class MyAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, MyWebAuthenticationDetails> {

   public MyWebAuthenticationDetails buildDetails(HttpServletRequest context) {
      // build a MyWebAuthenticationDetails
   }
}

resources.groovyでauthenticationDetailsSourceビーンをレジストしてね。

import com.mycompany.MyAuthenticationDetailsSource
beans = {
   authenticationDetailsSource(MyAuthenticationDetailsSource) {
      // any required properties
   }
}


あれです!詳しくはドキュメント読みましょう!いろいろと発見がありますよ!
http://grails-plugins.github.io/grails-spring-security-core/docs/manual/guide/newInV2.html




明日のJGGUG行けなくてゴメンナサイ。