Grailsスプリングセキュリティ - 成功アクションの前にインターセプトして、必要なパスワード変更を確認できますか?

私のシステムで新しいユーザーを作成する際には、電子メールで一時パスワードを送信し、changePasswordNextLogin = trueのプロパティを設定しています。彼らが初めてログインに来たとき、私は成功したログイン時にこのフローを傍受し、この値をチェックし、それが真であればパスワード変更アクションにリダイレクトしたいと思います。パスワードの変更が完了したら、理想的には、それらを意図した目的地に送信したいと考えています。

私はデフォルトの設定を注ぎ込んできており、それを実現する方法は見当たりませんし、正しく解釈しない可能性もあります。私がGrailsでいくつかの解決策をまとめようとするたびに、誰かが同じことをやるためにもっと優雅なアプローチをしていることがわかりました。これを可能にする機能が組み込まれていますか?

もしそうでなければ、私は本当にそうするための最善のアプローチに関する提案を感謝するでしょう。

1
あなたのおかげで申し訳ありません。投稿のタイトルに "Grails spring-security"を付けるのは説明的だと思っていましたが、プラグインなしでS2を使うという考えは考えていませんでした。私はもっ​​と具体的にすべきだったと思う。
追加された 著者 Dave Shuck,
あなたは春のセキュリティコアプラグインを使用していますか?または他のプラグインか独自のフィルターですか?スプリングセキュリティプラグインを使用している場合は、@ darrendがフレームワークが提供するpasswordExpiredプロパティを使用するための基礎を提供します。
追加された 著者 omarello,
@omarello質問文はs2は言及していませんでしたが、そのようにタグ付けされていたので、安全な前提だと思いました:)
追加された 著者 darrend,

2 答え

Spring Securityとgrailsプラグインでこれを直接サポートしていますが、あなた自身もいくつかの作業をしなければなりません:)

grails-spring-securityプラグインをインストールしたとき(S2Quickstartスクリプトを実行したとき)に作成されたドメインクラスには、 'passwordExpired'という名前のプロパティがあります。新しいユーザードメインインスタンスを作成するときは、これをtrueに設定します。

そのユーザが初めてログインすると、Spring Securityコアライブラリはログインコントローラのauthfailクロージャでキャッチした例外をスローし、パスワードの変更フォーム(自分で指定する必要がある)にリダイレクトします。

以下は、私のアプリケーションの例ですが、このクロージャーのスケルトン版はすでにログインコントローラーに含まれているはずです:

/**
 * Callback after a failed login.
 */
def authfail = {

    def msg = ''

    def username = 
       session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY]

    def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]

    if (exception) {
        if (exception instanceof CredentialsExpiredException) {
            msg = g.message(code: "springSecurity.errors.login.passwordExpired")
            if (!springSecurityService.isAjax(request))
                redirect (action:'changePassword')//<-- see below
        }
       //other failure checks omitted
    }

    if (springSecurityService.isAjax(request)) {
        render([error: msg] as JSON)
    }
    else {
        flash.message = msg
        redirect controller: 'login', action:'auth', params: params
    }
}

/**
 * render the change pwd form
 */
def changePassword = {
    [username: session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY] ?: springSecurityService.authentication.name]
}

あなたの 'changePasssword'ビューから、フォームを別のコントローラクロージャに送り返します(私は私の 'updatePassword'と呼んでいます)。あなたがパスワードに必要な制約をチェックし、更新されたパスワードをドメインオブジェクトに保存するかどうかを指定します。

def updatePassword = {
    String username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY] ?: springSecurityService.authentication.name
    if (!username) {
        flash.message = 'Sorry, an error has occurred'
        redirect controller: 'login', action:'auth'
        return
    }
    String password = params.password
    String newPassword = params.password_new
    String newPassword2 = params.password_new_2
    if (!password || !newPassword || !newPassword2 || newPassword != newPassword2) {
        flash.message = 'Please enter your current password and a new password'
        render view: 'changePassword', model: [username: username]
        return
    }
    SecUser user = SecUser.findByUsername(username)
    if (!passwordEncoder.isPasswordValid(user.password, password, null /*salt*/)) {
        flash.message = 'Current password is incorrect'
        render view: 'changePassword', model: [username: username]
        return
    }
    if (passwordEncoder.isPasswordValid(user.password, newPassword, null /*salt*/)) {
        flash.message = 'Please choose a different password from your current one'
        render view: 'changePassword', model: [username: username]
        return
    }
    if (!newPassword.matches(PASSWORD_REGEX)) {
        flash.message = 'Password does not meet minimum requirements'
        render view: 'changePassword', model: [username: username]
        return            
    }

   //success if we reach here!
    user.password = springSecurityService.encodePassword(newPassword)
    user.passwordExpired = false
    user.save() 

    flash.message = 'Password changed successfully' + (springSecurityService.loggedIn ? '' : ', you can now login')
    redirect uri: '/'
}
5
追加された
これはまさに私が探していたものと思われます。私は本当にあなたに説明する時間を割いていただき、ありがとうございます。理にかなっている!
追加された 著者 Dave Shuck,

Spring Secuirty 3.0以降を使用している場合は、Spring Security Pluginのドキュメント 11.3アカウントロックと強制パスワード変更。 あなたは、 Config.groovyの grails.plugin.springsecurity.apf.storeLastUsername = true

1
追加された