Grails Acegi插件丢失密码

Grails Acegi插件丢失密码,grails,spring-security,Grails,Spring Security,我正在寻找一个使用Acegi Grails插件的密码检索过程的实现…Google让我失望了…我想这目前不是Acegi插件的一部分。我已将forgotPassword操作添加到LoginController: def forgotPassword = { if (params.username) { User user = User.findByUsername(params.username) if (user) { def

我正在寻找一个使用Acegi Grails插件的密码检索过程的实现…Google让我失望了…

我想这目前不是Acegi插件的一部分。我已将forgotPassword操作添加到LoginController:

    def forgotPassword = {
    if (params.username) {
        User user = User.findByUsername(params.username)
        if (user) {
            def password = randomService.generateRandomString(8)
            user.passwd = authenticateService.encodePassword(password)
            if (!user.save(flush:true)) {
                user.errors.each {
                    log.error "err $it"
                }
                flash.message = message(code: "LoginController.msg.forgot.error")
            } else {
                sendMail {
                    to user.username
                    subject message(code:"LoginController.mail.forgot.subject" )
                    body(view:"forgotPasswordEmail", model: [person:user, password:password])
                }
                flash.message = message(code:"LoginController.msg.forgot", args:[user.username] )
            }
        } else {
            flash.message = message(code:"LoginController.msg.forgot.unknown", args:[params.username])
        }
    }
}

上面的代码使用了Grails邮件插件。

谷歌让你失望了,因为没有。如果不使用暴力破解和彩虹表,就不可能反转散列密码,如果是,那就意味着您的系统不安全


常见的模式是通过电子邮件向忘记密码的用户发送一次性使用令牌,然后用户可以使用该令牌将密码重置为他们想要的任何密码。这不是内置到框架中的,但是手动操作并不难(我建议使用grails mail插件)。

Acegi插件不支持这种开箱即用的方式,但是如果添加插件,就很容易推出自己的插件

以下是步骤:

创建密码重置表单,要求用户输入其电子邮件地址和新密码

处理密码重置表单的控制器操作应验证数据和 使用电子邮件确认插件向用户发送电子邮件,其中包含一个链接,供用户单击以确认其密码更改。您可以通过在插件添加的EmailConfirmationService服务上调用以下方法来完成此操作

def sendConfirmation(String emailAddress, String theSubject, Map model = null, 
String userToken = null)
其中:

emailAddress = address of user changing password
theSubject = subject of e-mail sent
model = any data passed to GSP that creates e-mail body
userToken = hashed user's password
当用户单击电子邮件中的链接时(有关如何自定义此电子邮件的信息,请参阅插件文档),将调用服务的
onConfirmation
关闭

应该在
Bootstrap.groovy
中指定此闭包,如下所示:

def emailConfirmationService

def init = { servletContext -> 

  emailConfirmationService.onConfirmation = { email, hashedPassword ->

    User user = User.findByEmail(email)
    user.passwd = hashedPassword
    if (!user.save()) {
        // Handle this error, somehow....
    }

    // Then return a map which will redirect the user to the login screen  (for example)
    [controller:'userProfile', action:'login'] 
  } 
}

请注意,用户的电子邮件和哈希密码被传递到此闭包中,使您能够重置和保存用户的密码。

这是一个很好的开始实现。它的一个潜在问题是,即使其他人请求,它也会自动重置密码,因此恶意用户可能会不断点击“重置密码”并更改用户的密码,而实际上他们并不希望更改密码(尽管他们仍然会收到电子邮件)。我们做了类似的事情,但却有一个表,其中保存了一次使用令牌,这些令牌的生存时间很短,可以通过电子邮件重置密码。如果未使用令牌,则密码不变。表中每个用户最多只有一个令牌。完全同意。另一个选择是一种安全问题,例如“你母亲的婚前姓是什么?”。只有问题回答正确,密码才会重置。也许这是有意义的,在一个独立的插件中,根据acegi插件,将那些帐户处理函数“恢复密码”、“恢复登录名”、“删除帐户”考虑在内。