【发布时间】: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