2014-07-11 134 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

非常感謝您的時間! –