grails - grails-Spring Security UI奇怪的行为

标签 grails grails-plugin grails-controller

我正在尝试自定义spring security ui插件。我要实现的目标:

1)管理员使用来自Spring Security ui的电子邮件创建一个新用户

2)应用程序生成链接并将其发送到用户的电子邮件

3)用户点击链接,然后看到页面,他可以在其中指定密码并保存

4)用户提交页面帐户后,使用他指定的密码激活

为此,我决定默认情况下自定义Spring安全性UI提供的UserController:

class UserController extends grails.plugin.springsecurity.ui.UserController {

    def mailService

    def save() {
        def user = lookupUserClass().newInstance(params)
        if (!user.save(flush: true)) {
            render view: 'create', model: [user: user, authorityList: sortedRoles()]
            return
        }

        //generate secured link
        def registrationCode = new RegistrationCode(username: user.username).save(flush: true)
        String url = generateLink('verifyRegistration', [t: registrationCode.token])
        def conf = SpringSecurityUtils.securityConfig

        //here we should send an invitation mail
        mailService.sendMail {
            async true
            to user.email
            from conf.ui.register.emailFrom
            subject conf.ui.register.emailSubject
            html url
        }

        addRoles(user)
        flash.message = "${message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), user.id])}"
        redirect action: 'edit', id: user.id
    }



    def verifyRegistration() {
        def conf = SpringSecurityUtils.securityConfig
        String defaultTargetUrl = conf.successHandler.defaultTargetUrl
        String token = params.t
        println token

        def registrationCode = token ? RegistrationCode.findByToken(token) : null
        if (!registrationCode) {
            println registrationCode
            flash.error = message(code: 'spring.security.ui.register.badCode')
            redirect uri: defaultTargetUrl
            return
        }

        render(view: "initpassword", model: [token: token])
    }

    def savePassword() {
        String token = params.token
        def conf = SpringSecurityUtils.securityConfig
        String defaultTargetUrl = conf.successHandler.defaultTargetUrl
        def registrationCode = token ? RegistrationCode.findByToken(token) : null

        //TODO check if passwords are equal

        if (!registrationCode) {
            flash.error = message(code: 'spring.security.ui.register.badCode')
            redirect uri: defaultTargetUrl
            return
        }

        def user

        RegistrationCode.withTransaction { status ->
            String usernameFieldName = SpringSecurityUtils.securityConfig.userLookup.usernamePropertyName
            user = lookupUserClass().findWhere((usernameFieldName): registrationCode.username)
            if (!user) {
                return
            }
            user.accountLocked = false

            String salt = saltSource instanceof NullSaltSource ? null : params.username
            user.password = springSecurityUiService.encodePassword(params.password1, salt)
            user.save(flush: true)
            def UserRole = lookupUserRoleClass()
            def Role = lookupRoleClass()
            for (roleName in conf.ui.register.defaultRoleNames) {
                UserRole.create user, Role.findByAuthority(roleName)
            }
            registrationCode.delete()
        }

        if (!user) {
            flash.error = message(code: 'spring.security.ui.register.badCode')
            redirect uri: defaultTargetUrl
            return
        }

    }
}

initpassword.gsp非常简单,看起来像这样:
<g:form action="savePassword" absolute="true" method="POST">
    <g:passwordField name="password1"/>
    <g:passwordField name="password2"/>
    <g:hiddenField value="${token}" name="token"/>
    <g:actionSubmit value="Save"/>
</g:form>

到目前为止,一切看起来都很好(至少对我来说,请让我知道您是否发现了错误),但是当我尝试对其进行测试时,会发生非常奇怪的事情:

1)我单击通过电子邮件发送的链接(调用verifyRegistration()方法)

2)应用程序显示了我可以在其中键入密码的页面(显示了initpassword页面)

3)我提交页面(这里应该调用savePassword(),但由于某种原因未调用它),应用程序向我显示了默认页面,该页面用于通过带有验证错误的spring security ui插件创建一个新用户,其中它表示用户的字段(全部一一)不能为空

4)当我尝试调试(在savePassword()方法开头使用断点)时,什么都没发生-好像 Controller 只是没有捕获到savePassword()的请求

但是,当我尝试仅从浏览器(键入localhost / myApp / user / savePassword) Controller 打开savePassword()方法时,会捕获该请求,并在该断点上进行调试。

我花了将近4个小时来处理这个问题。不知道实际发生了什么。 Grails有一些魔力。
有人可以帮我弄这个吗?谢谢!!!

最佳答案

在您的initpassword.gsp中,只需将action="savePassword"属性添加到g:actionSubmit标签即可。您甚至可以从g:form标记中删除此属性。那就是Grails能够采取多种行动的形式。我不确定,但是在干净的HTML中它也可以工作。

<html>
<head>
    <title></title>
</head>

<body>
<g:form controller="user" absolute="true" method="POST">
    <g:passwordField name="password1"/>
    <g:passwordField name="password2"/>
    <g:hiddenField value="${token}" name="token"/>
    <g:actionSubmit value="Save" action="savePassword"/>
</g:form>
</body>
</html>

关于grails - grails-Spring Security UI奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24700839/

相关文章:

grails - 为Grails安装Nimble

grails - “GORM support for Hadoop HBase plugin”不支持grails 2.1.0

grails - 使用用户名作为电子邮件,Spring Security UI 插件

grails - 如何访问 Controller 中的 config.groovy 值?

grails - Grails 3-带过滤参数的前进

grails - 如何在 grails 中编写 accessDeniedHandler

grails - 在 Controller 中引用 hasMany 属性

grails - 在grails 2.3上安装grails插件的正确方法是什么?

grails - Play的模板引擎可以在Grails上使用吗?

grails - MongoDB 和 mysqlDB 在 grails 中一起使用导致我的项目出现问题