Grails - 拦截在LoginController的authfail中输入的用户名

时间:2014-07-28 11:41:39

标签: authentication grails login spring-security

我试图强制用户在首次登录时更改密码(正如此处Grails spring-security - Can I intercept before success action to check required password change?所述)。

但是,UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY(也已弃用)和springSecurityService.authentication.name都不会提供输入的用户名。我得到的只是__grails.anonymous.user__无法用来设置用户的新密码。

您是否有人知道如何确定输入的用户名?

非常感谢。

2 个答案:

答案 0 :(得分:3)

您可以使用session.getAttribute(SpringSecurityUtils.SPRING_SECURITY_LAST_USERNAME_KEY) 我还必须在config.groovy

中启用此属性
grails.plugin.springsecurity.apf.storeLastUsername=true

答案 1 :(得分:0)

我没弄明白如何将登录表单中输入的用户名传递给changePassword.gsp。尽管如此,我还是构建了一个尚未完善的解决方案,但至少是有效的。

我的自定义登录控制器中的authfail关闭保持在Grails spring-security - Can I intercept before success action to check required password change?

但是,我删除了changePassword关闭,因为我在changePassword.gsp中添加了一个文本字段,以便用户输入其用户名。这也是我认为这个解决方案并不完美的原因,因为通常我也不想重新输入我的用户名。

由于我对grails不熟悉,你们中的一些人可能会对如何更加优雅地实现此功能有一两个提示。我真的很感激它:)

关注LoginControllerchangePassword.gsp

的源摘录

LoginController.groovy

/**
 * Callback after a failed login. Redirects to the auth page with a warning message.
 */
def authfail() {

    String msg = ''
    def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
    if (exception) {
        if (exception instanceof AccountExpiredException) {
            msg = g.message(code: "springSecurity.errors.login.expired")
        }
        else if (exception instanceof CredentialsExpiredException) {
            msg = g.message(code: "springSecurity.errors.login.passwordExpired")
            if (!springSecurityService.isAjax(request)) {
                flash.message = msg
                render view: 'changePassword'
                return
            }
        }
        // omitting other cases
    }

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

def updatePassword() {
    String username = params.username

    if (!username) {
        flash.message = 'Sorry, an error has occurred'
        redirect controller: 'login', action:'auth'
        return
    }

    String password = params.password_old
    String newPassword = params.password_new
    String newPassword2 = params.password_new_rep

    if (!password || !newPassword || !newPassword2 || newPassword != newPassword2) {
        flash.message = 'Please enter your current password and a new password'
        render view: 'changePassword', model: [username: username]
        return
    }

    User user = userService.getUserByUsername(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 (user.username.equals(newPassword)) {
        flash.message = 'New password must not equal your username'
        render view: 'changePassword', model: [username: username]
        return
    }

    // success if we reach here!
    user.password = newPassword
    user.passwordExpired = false
    userService.updateUser(user)

    springSecurityService.reauthenticate(username, newPassword)

    flash.message = 'Password changed successfully' + (springSecurityService.loggedIn ? '' : ', you can now login')
    redirect uri: '/'
}

changePassword.gsp

<html>
    <head>
        <meta name="layout" content="general" />
        <title>Change password</title>
    </head>
    <body>
        <content tag="heading">Change password</content>
        <content tag="content">
            <g:if test="${flash.message }">
                ${flash.message }
            </g:if>
            <g:form name="changePassword" autocomplete="off">
            <table>
                <tr>
                    <td>Username</td>
                    <td><g:field type="text" name="username" required="" /></td>
                </tr>
                <tr>
                    <td>Old password</td>
                    <td><g:field type="password" name="password_old" required=""/></td>
                </tr>
                <tr>
                    <td>New password</td>
                    <td><g:field type="password" name="password_new" required=""/></td>
                </tr>
                <tr>
                    <td>New password (repeat)</td>
                    <td><g:field type="password" name="password_new_rep" required=""/></td>
                </tr>
                <tr>
                    <td></td>
                    <td>
                        <g:actionSubmit name="submit" value="Change password" action="updatePassword"/>
                    </td>
                </tr>

            </table>
            </g:form>
        </content>
    <script>
$(document).ready(function() {
    $('#username').focus();
});
    </script>
    </body>
</html>