Grails spring-security - Могу ли я перехватить до успешного выполнения действия, чтобы проверить требуемую смену пароля? - PullRequest
1 голос
/ 28 октября 2011

После создания новых пользователей в моей системе я отправляю им временный пароль по электронной почте и устанавливаю свойство changePasswordNextLogin = true.Когда они приходят в первый раз, я хотел бы перехватить поток при успешном входе в систему, проверить это значение и, если оно истинно, перенаправить их на действие смены пароля.Как только смена пароля будет завершена, в идеале я хотел бы отправить их по назначению.

Я просматривал настройки по умолчанию и не вижу - или, скорее всего, неправильно интерпретирую - какого-либо способа добиться этого.Кажется, что почти каждый раз, когда я пытаюсь найти какое-то решение в Grails, я обнаруживаю, что кто-то уже сделал более элегантный подход к тому же.Есть ли встроенная функциональность, которая позволила бы это?

Если нет, я был бы очень признателен за любые предложения о наилучшем подходе, чтобы сделать это так.

Ответы [ 2 ]

5 голосов
/ 06 ноября 2011

Существует некоторая поддержка для этого непосредственно с 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: '/'
}
1 голос
/ 18 августа 2014

Если вы используете Spring Secuirty 3.0 и новее, вы можете обратиться к документации плагина безопасности Spring 11.3 Блокировка учетной записи и принудительное изменение пароля .Помните, что вы должны установить grails.plugin.springsecurity.apf.storeLastUsername=true в Config.groovy.

...