Grails Spring 安全用户界面

Posted

技术标签:

【中文标题】Grails Spring 安全用户界面【英文标题】:Grails spring Security UI 【发布时间】:2011-12-18 19:11:14 【问题描述】:

我是 Grails 的新手,我正在尝试构建一个简单的帮助台应用程序。我希望能够注册一个新用户,登录,发布请求/事件,将其保存到数据库中,并且从管理员方面我希望能够查看表中的所有请求/事件,并更改用户的权限。 对于安全部分(和安全管理),我正在考虑使用 Spring security 和 Spring security UI 插件。 现在我已经创建了应用程序,安装了 spring security 和它的 UI 扩展,添加了真实姓名、电子邮件和公司属性。当我运行应用程序时,我设法成功注册,当我通过电子邮件确认注册时,我会自动登录,但是当我尝试使用其他浏览器登录时,我收到以下错误:

“抱歉,我们无法找到具有该用户名和密码的用户”

但是数据库里有一个。

另外,我想拥有一个事件域类,我将在其中保存所有事件/请求数据。 User 和 Incident 域类之间的关系将是一对多的。我是像其他任何关系一样实现它,还是因为 User 是由 Spring Security 实现的,所以我必须做一些特别的事情? 我愿意接受任何建议。

【问题讨论】:

【参考方案1】:

最新的 spring-security-core 和 spring-security-ui 0.1.2 不兼容。特别是,spring-security-core 将密码编码移动到 User 类中的 beforeInsert/beforeUpdate 事件处理程序中。 RegisterController.register spring-security-ui 中的控制器还不知道这一点,并尝试再次对其进行编码,从而产生双重编码的密码。要解决此问题,请覆盖 RegisterController 并将 register 操作更改为:

def register =  RegisterCommand command ->

    if (command.hasErrors()) 
        render view: 'index', model: [command: command]
        return
    

    def user = lookupUserClass().newInstance(email: command.email, username: command.username,
                                             password: command.password, accountLocked: true, enabled: true)
    if (!user.validate() || !user.save()) 
        // TODO
    

    def registrationCode = new RegistrationCode(username: user.username).save()
    String url = generateLink('verifyRegistration', [t: registrationCode.token])

    def conf = SpringSecurityUtils.securityConfig
    def body = conf.ui.register.emailBody
    if (body.contains('$')) 
        body = evaluate(body, [user: user, url: url])
    
    mailService.sendMail 
        to command.email
        from conf.ui.register.emailFrom
        subject conf.ui.register.emailSubject
        html body.toString()
    

    render view: 'index', model: [emailSent: true]

http://jira.grails.org/browse/GPSPRINGSECURITYUI-27 正在跟踪此问题。

关于您的第二个问题,您可以像对待任何其他域对象一样对待您的 User 类。

【讨论】:

可以通过在 Config.groovy 中添加 grails.plugins.springsecurity.ui.encodePassword = false 行来防止双重编码【参考方案2】:

当您使用 s2-quickstart 脚本将 Spring Security 添加到您的 grails 项目时,会自动创建用户和角色的域类。这些是普通的域类,因此您可以将任何您想要的(例如事件列表)添加到用户类。

要在运行时获取当前登录的用户域对象,请使用

springSecurityService.currentUser

【讨论】:

【参考方案3】:

此问题已在“org.grails.plugins:spring-security-ui:1.0-RC3”中修复。 spring-security-ui 默认不对密码进行编码。

以下是 grails spring Security UI 文档中的描述及其对问题的解决方案。搜索标题为“密码哈希”的部分

http://grails-plugins.github.io/grails-spring-security-ui/v1/guide/customization.html

“在最新版本的 Spring Security Core 插件中,“User”域类是gene该选项默认由s2-quickstart脚本用代码自动散列密码进行虚假验证。这使得代码更简单(例如在控制器中您在哪里创建用户或更新用户密码)但较旧的生成类没有此生成的代码。这对于像这样的插件来说是一个问题,因为无法可靠地确定域类是否对密码进行哈希处理,或者您是否使用较旧的显式调用springSecurityService.encodePassword()的方法。

将执行密码散列的较新域类与调用 springSecurityService.encodePassword() 的控制器混合的不幸后果是密码被双重散列,并且用户无法登录。所以为了解决这个问题,你可以设置一个配置选项来告诉这个插件的控制器是否散列:grails.plugin.springsecurity.ui.encodePassword。

此选项默认为 false,因此如果您有一个不处理散列的旧域类,只需启用此插件的散列:

grails.plugin.springsecurity.ui.encodePassword = true"

【讨论】:

以上是关于Grails Spring 安全用户界面的主要内容,如果未能解决你的问题,请参考以下文章

Grails Spring 安全性

基于 SAML 响应在 Grails 中分配 Spring 安全角色

Grails - Spring Security 帐户创建

Grails 3 Spring 安全插件

Grails Spring Security 插件 - 修改登录用户的权限

grails spring 安全角色和组