在 Grails 的 Spring Security 插件中使用电子邮件和用户名作为登录名

Posted

技术标签:

【中文标题】在 Grails 的 Spring Security 插件中使用电子邮件和用户名作为登录名【英文标题】:using email and username both as login in spring security plugin in Grails 【发布时间】:2013-10-05 05:06:20 【问题描述】:

我在我的 Grails 应用程序中使用 Spring Security 插件,我希望注册用户使用注册过程中提供的用户名或电子邮件地址登录应用程序。(就像 fb)

我已经查看了网络并关注 Grails 文档 ::: http://grails-plugins.github.io/grails-spring-security-core/docs/manual/guide/single.html#4.1%20Person%20Class

但找不到任何解决方案。

任何帮助将不胜感激。

提前致谢

【问题讨论】:

【参考方案1】:

我认为最近没有任何关于此的内容。在更高版本的 spring security / grails 3.2.8 中。这是我的:

这是在服务中创建的服务。用户电子邮件位于 User 之外的一个单独的类中,因此 attributes.email 检查否则你可以只做 User.findByUsernameOrEmail(username,username)

所以我将 UserEmailUserService 作为服务:

package com.app.users

import grails.plugin.springsecurity.userdetails.GormUserDetailsService
import grails.transaction.Transactional
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException

class UserEmailUserService extends GormUserDetailsService

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

    @Transactional
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        //enable login with either username or password
        User user = User.find 
            username == username || attributes.email == username
        
        if (!user) throw new UsernameNotFoundException('User not found', username)
        UserDetails userDetails = new org.springframework.security.core.userdetails.User(user.username, user.getPassword(),
                user.enabled, !user.accountExpired, !user.passwordExpired, !user.accountLocked, getAuthorities(user.roles))
        Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities())
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return userDetails
    

    public static List<GrantedAuthority> getAuthorities(Set<Role> roles) 
       List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>()
       roles?.each  role ->
          authorities.add(new SimpleGrantedAuthority(role.authority))
       
       return authorities
   

然后在conf/spring/resources.groovy:

import com.app.users.UserEmailUserService

// Place your Spring DSL code here
beans = 
      userDetailsService(UserEmailUserService)
            grailsApplication = ref('grailsApplication')
        

请注意我调用了user.roles 这是我在用户类中进行的自定义调用。因为我有团体角色等:

Set<Role> getRoles() 
    UserRole.findAllByUser(this)*.role

【讨论】:

【参考方案2】:

从spring-security的角度来看,你应该做的是实现你自己的org.springframework.security.core.userdetails.UserDetailsS​​ervice

public class MyUserServiceImpl implements UserDetailsService

    @Autowired
    private AdminUserDao dao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException 

    ... Here comes your logic to get your the user based on email or userid ...

    

在您的 spring 配置中,您必须引用您的 UserDetails 类:

<authentication-manager>
    <authentication-provider user-service-ref="myUserServiceImpl" />
</authentication-manager>

【讨论】:

以上是关于在 Grails 的 Spring Security 插件中使用电子邮件和用户名作为登录名的主要内容,如果未能解决你的问题,请参考以下文章

Spring 3.0 - 无法找到 XML 模式命名空间的 Spring NamespaceHandler [http://www.springframework.org/schema/securit

Spring 3.0 - 无法找到 XML 模式命名空间的 Spring NamespaceHandler [http://www.springframework.org/schema/securit

Grails 3 Spring Security 覆盖登录表单

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

Grails,从 Acegi 升级到 Spring 安全插件

在 grails 中使用 spring-security 插件时出错