You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Grails 3.3.5+Spring-security-rest登录响应中添加用户信息

如何在Spring Security REST登录响应中添加额外用户信息?

刚好我之前也处理过类似需求,按照你提到的Spring Security REST文档指引,咱们分三步就能实现:

1. 自定义UserDetailsService,封装额外用户信息

首先需要创建一个自定义的UserDetailsService实现类,用来从你的数据源(比如数据库)获取用户的额外信息(比如姓名、ID等),并把这些信息存入自定义的GrailsUser对象中:

import grails.plugin.springsecurity.userdetails.GrailsUser
import grails.plugin.springsecurity.userdetails.GrailsUserDetailsService
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException

class CustomUserDetailsService implements GrailsUserDetailsService {

    @Override
    UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException {
        // 替换为你实际查询用户的逻辑,比如从User域类根据邮箱查询
        def user = User.findByEmail(username)
        if (!user) {
            throw new UsernameNotFoundException("用户不存在:$username")
        }

        // 处理用户角色,转换为Spring Security需要的Authority对象
        def authorities = user.authorities.collect { 
            new org.springframework.security.core.authority.SimpleGrantedAuthority(it.authority) 
        }

        // 自定义GrailsUser实例,将额外信息(比如realName、id)封装进去
        return new GrailsUser(user.email, user.password, user.enabled, !user.accountExpired,
                !user.passwordExpired, !user.accountLocked, authorities, user.id) {
            final String realName = user.realName
            // 可根据需求添加更多字段,比如phoneNumber等
        }
    }

    @Override
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return loadUserByUsername(username, true)
    }
}

2. 自定义AccessTokenJsonRenderer,渲染额外信息

接下来创建一个自定义的AccessTokenJsonRenderer,用来从认证令牌的principal中取出额外信息,并添加到登录响应的JSON里:

import grails.plugin.springsecurity.rest.token.rendering.AccessTokenJsonRenderer
import grails.plugin.springsecurity.rest.token.rendering.DefaultAccessTokenJsonRenderer
import org.springframework.security.core.Authentication
import grails.converters.JSON

class CustomAccessTokenJsonRenderer implements AccessTokenJsonRenderer {

    private final DefaultAccessTokenJsonRenderer defaultRenderer = new DefaultAccessTokenJsonRenderer()

    @Override
    String generateJson(Authentication authentication) {
        // 先获取默认的响应JSON数据
        def defaultJson = defaultRenderer.generateJson(authentication)
        def parsedJson = JSON.parse(defaultJson)

        // 从principal中提取自定义的额外信息
        def principal = authentication.principal
        if (principal instanceof GrailsUser) {
            // 添加你需要的字段到响应中
            parsedJson.realName = principal.realName
            parsedJson.userId = principal.id
            // 可继续添加其他字段,比如phoneNumber等
        }

        // 返回修改后的JSON字符串
        return parsedJson as JSON
    }
}

3. 注册自定义Bean,替换默认实现

最后在grails-app/conf/spring/resources.groovy中注册这两个自定义Bean,让Spring Security使用我们的实现:

beans = {
    // 替换默认的userDetailsService
    userDetailsService(CustomUserDetailsService)
    // 替换默认的accessTokenJsonRenderer
    accessTokenJsonRenderer(CustomAccessTokenJsonRenderer)
}

完成以上配置后,再次调用/api/login接口,你就能得到包含额外信息的响应了,示例如下:

{ 
  "username": "name.surname@acme.com", 
  "roles": [ "ROLE_USER" ], 
  "access_token": "qgsbpk05jfrbf33xx08m8r4govkg53d1",
  "realName": "Name Surname",
  "userId": 123
}

内容的提问来源于stack exchange,提问作者NiBE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:22:21