【问题标题】:grails - spring security UI strange behaviourgrails - Spring Security UI 奇怪的行为
【发布时间】:2014-07-11 15:03:43
【问题描述】:

我正在尝试自定义 spring security ui 插件。我想要达到的目标:

1) admin 使用来自 spring security ui 的电子邮件创建一个新用户

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

3) 用户点击链接后会看到可以指定密码并保存的页面

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

为此,我决定自定义 Spring Security 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) 应用显示此页面,我可以在其中输入密码(显示初始密码页面)

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

4) 当我尝试调试时(在 savePassword() 方法的开头使用断点)没有任何反应 - 控制器似乎只是不捕获对 savePassword() 的请求

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

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

【问题讨论】:

  • 您的initpassword.gsp 在哪里?请从项目根目录中获取完整路径。以及调用此视图的控制器代码
  • initpassword.gsp 位于 %PROJECT%/grails-app/views/user 下,用于 UserController 中的 def verifyRegistration() 方法(上面的帖子)
  • 我查看了我的代码,并通过以下方式开发了类似的案例:1)将initpassword.gsp重命名为_initpassword.gsp; 2) 将render(view: "initpassword", model: [token: token]) 重写为render(controller: "user", template: "initpassword", model: [token: token])。请试一试,这一定行得通。
  • 不,很遗憾这个版本也不行
  • 是的,当然。请通过bitbucket.org/mie777/securitybug/src查看它

标签: grails grails-plugin grails-controller


【解决方案1】:

在您的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>

【讨论】:

  • 非常感谢您的宝贵时间!
猜你喜欢
  • 2014-12-11
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-20
  • 2017-10-26
  • 2012-09-12
  • 1970-01-01
相关资源
最近更新 更多