我正在尝试自定义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/