在 grails 中与开放 id 的 Spring 安全集成

Posted

技术标签:

【中文标题】在 grails 中与开放 id 的 Spring 安全集成【英文标题】:Spring security integration with open id in grails 【发布时间】:2012-02-14 02:50:19 【问题描述】:

我正在使用 springsecurity 核心和 springsecurity openid 插件为我的 grails 应用程序集成 spring security 和 openId。我已经集成了它,它运行良好,但我需要访问已登录人员的电子邮件。我怎么能得到它,我能访问的只是一个用于识别人的令牌。

【问题讨论】:

【参考方案1】:

感谢伊恩·罗伯茨。 他给了我这个回复,正好解决了我的问题。 他的回复是:

碰巧我在我的一个应用程序中实现了这一点 昨天:-) 不幸的是它不是一个开源应用程序所以我不能只是 指出我的代码,但我可以解释我做了什么。

spring-security-openid 插件支持“属性交换” OpenID 的机制,尽管支持的文档不多(如果在 全部)。它的工作情况取决于远端的提供商,但这 至少使用 Google 和 Yahoo 对我有用。

为了向提供商请求电子邮件地址,您需要添加 以下为 Config.groovy:

grails.plugins.springsecurity.openid.registration.requiredAttributes.email =“http://axschema.org/contact/email”

现在要将其连接到您的用户注册过程中,您需要一封电子邮件 S2 用户域类中的字段,您需要编辑生成的 OpenIdController.groovy 在几个地方。

将电子邮件属性添加到 OpenIdRegisterCommand

在 createAccount 操作中有一行 "if(!createNewAccount(...))" 传递用户名、密码和 openid 作为参数。将其与方法定义一起更改为 传递整个命令对象,而不仅仅是这两个字段。

在 createNewAccount 中从命令中向前传递电子邮件值 对象到用户域对象构造函数。

最后为您的电子邮件添加一个输入字段 grails-app/views/openId/createAccount.gsp.

您可以对其他属性(例如全名)执行相同操作。

grails.plugins.springsecurity.openid.registration.requiredAttributes.fullname = "http://axschema.org/namePerson"

将它连接在一起的重要一点是最后一个 requiredAttributes 后面的点(本例中为全名)必须匹配 OpenIdRegisterCommand 上的属性名称。

问候 查鲁耆那教

【讨论】:

我已验证此方法有效,并且有更多信息。上述步骤不仅会获取电子邮件,还会在创建时将其与新用户相关联。如果您只想在身份验证过程中从会话中访问电子邮件(即:从 OpenIdController createAccount 函数中),您可以使用 session[OIAFH.LAST_OPENID_ATTRIBUTES] 字符串对象来实现。【参考方案2】:

我从未使用过 springsecurity openid 插件,但是在使用 springsecurity 核心时,您可以通过实现自定义 UserDetails 来公开有关当前用户的其他信息。在我的应用程序中,我添加了这个实现,以便我可以显示登录用户的name 属性。您需要稍作更改,以便显示电子邮件地址

/**
 * Custom implementation of UserDetails that exposes the user's name
 * http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/11%20Custom%20UserDetailsService.html
 */
class CustomUserDetails extends GrailsUser 

    // additional property
    final String name

    CustomUserDetails(String username,
                      String password,
                      boolean enabled,
                      boolean accountNonExpired,
                      boolean credentialsNonExpired,
                      boolean accountNonLocked,
                      Collection<GrantedAuthority> authorities,
                      long id,
                      String displayName) 

        super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities, id)
        this.name = displayName
    

然后您需要创建UserDetailsService 的自定义实现,它返回上述类的实例

class UserDetailsService implements GrailsUserDetailsService 

    /**
     * Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least one role, so
     * we give a user with no granted roles this one which gets past that restriction but
     * doesn't grant anything.
     */
    static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]

    UserDetails loadUserByUsername(String username, boolean loadRoles) 
        return loadUserByUsername(username)
    

    UserDetails loadUserByUsername(String username) 
        User.withTransaction  status ->

            User user = User.findByUsername(username)
            if (!user) 
                throw new UsernameNotFoundException('User not found', username)
            

            def authorities = user.authorities.collect new GrantedAuthorityImpl(it.authority)
            return new CustomUserDetails(
                    user.username,
                    user.password,
                    user.enabled,
                    !user.accountExpired,
                    !user.passwordExpired,
                    !user.accountLocked,
                    authorities ?: NO_ROLES,
                    user.id,
                    user.name)
        
    

您需要将此类的一个实例注册为名为@9​​87654326@ 的Spring bean。我通过将以下内容添加到 Resources.groovy

来做到这一点
userDetailsService(UserDetailsService)

【讨论】:

以上是关于在 grails 中与开放 id 的 Spring 安全集成的主要内容,如果未能解决你的问题,请参考以下文章

Grails 2.1.1 和 Spring Security Core 插件

Auth0 + Grails 3 + Spring Security

如何在 Spring Security 中指定 Open ID Realm?

Grails 3 Spring Security 覆盖登录表单

在 Spring Security 登录期间设置 Grails/Spring Locale - 如何?

Grails sitemesh 是不是有任何解决方法不支持带有开放 HTML 正文标记的 if 语句