2014-07-11 84 views
0

我试图自定义弹簧安全UI插件。我想达到什么:grails-弹簧安全UI奇怪的行为

1)管理从春季安全用户界面创建与电子邮件的新用户

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

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

4)用户提交页面的帐户被激活与他指定

为此,我决定自定义UserController中由弹簧SECU提供的密码后默认情况下RITY UI:

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)表观s上3)我提交的页面(这里savePassword()应该被调用,但由于某种原因,它没有被调用)和应用程序显示我默认页面用于创建一个新的用户从弹簧安全UI插件与验证erros它说,用户(所有的一个接一个)字段不能为空

4)当我尝试调试(在savePassword()方法开始时断点)没有反应 - 似乎控制器只是不赶上要求savePassword()

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

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

+0

你的'initpassword.gsp'位于哪里?请从项目根目录获取完整路径。并且你调用这个视图的控制器代码 – wwarlock

+0

initpassword.gsp在%PROJECT%/ grails-app/views/user下面,它用在UserController的def verifyRegistration()方法中(post above) –

+0

我看着我的代码,我已经开发出类似的案例:1)将'initpassword.gsp'重命名为'_initpassword.gsp'; 2)将render(view:“initpassword”,model:[token:token])重写为'render(controller:“user”,template:“initpassword”,model:[token:token])''。请尝试,这必须工作。 – wwarlock

回答

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> 
+0

非常感谢您的时间! –