Spring Authorization Server中如何为OAuth2Authorizations添加自定义属性?
解决方案
一、确认OAuth2Authorization的attributes字段适用性
完全适合你的场景。OAuth2Authorization的attributes就是为存储自定义扩展信息设计的,JdbcOAuth2AuthorizationService会自动将该Map序列化为JSON格式,存入数据库oauth2_authorization表的attributes字段中,无需额外修改表结构。
二、获取HttpServletRequest中的User-Agent与IP
在Spring Security上下文里,可通过RequestContextHolder直接获取当前请求实例,再提取所需信息:
- User-Agent:直接通过
request.getHeader("User-Agent")获取 - 请求IP:需考虑反向代理场景(如Nginx),优先读取
X-Forwarded-For等头,兜底用request.getRemoteAddr()
工具方法示例:
private String getClientIp(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } // 多IP场景取第一个有效IP if (ip != null && ip.contains(",")) { ip = ip.split(",")[0].trim(); } return ip; }
三、将自定义信息注入OAuth2Authorization
推荐两种实现方式,按需选择:
方式1:自定义OAuth2AuthorizationGenerator
直接拦截OAuth2Authorization的生成过程,添加自定义属性:
@Component public class CustomOAuth2AuthorizationGenerator implements OAuth2AuthorizationGenerator { private final OAuth2AuthorizationGenerator delegate; public CustomOAuth2AuthorizationGenerator(OAuth2AuthorizationGenerator delegate) { this.delegate = delegate; } @Override public OAuth2Authorization generate(OAuth2AuthorizationContext context) { OAuth2Authorization authorization = this.delegate.generate(context); // 获取当前请求实例 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String userAgent = request.getHeader("User-Agent"); String clientIp = getClientIp(request); // 基于原实例构建新的OAuth2Authorization,添加自定义属性 return OAuth2Authorization.from(authorization) .attribute("user_agent", userAgent) .attribute("client_ip", clientIp) .build(); } private String getClientIp(HttpServletRequest request) { // 实现上述IP获取逻辑 } }
然后在授权服务器配置中替换默认生成器:
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig implements AuthorizationServerConfigurer { private final CustomOAuth2AuthorizationGenerator customAuthorizationGenerator; public AuthorizationServerConfig(CustomOAuth2AuthorizationGenerator customAuthorizationGenerator) { this.customAuthorizationGenerator = customAuthorizationGenerator; } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authorizationGenerator(customAuthorizationGenerator); // 其他配置:数据源、客户端详情、令牌存储等 } }
方式2:通过AuthenticationListener注入授权请求
在授权请求认证成功时,将信息存入AuthorizationRequest的属性中,后续生成OAuth2Authorization会自动继承这些属性:
@Component public class CustomAuthorizationRequestListener implements AuthenticationListener<OAuth2AuthorizationRequestAuthenticationToken> { @Override public void onAuthenticationSuccess(OAuth2AuthorizationRequestAuthenticationToken authentication) { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String userAgent = request.getHeader("User-Agent"); String clientIp = getClientIp(request); // 将属性添加到授权请求中 authentication.getAuthorizationRequest().getAttributes().put("user_agent", userAgent); authentication.getAuthorizationRequest().getAttributes().put("client_ip", clientIp); } private String getClientIp(HttpServletRequest request) { // 实现上述IP获取逻辑 } }
四、验证效果
授权流程完成后,查看数据库oauth2_authorization表的attributes字段,会看到包含user_agent和client_ip的JSON数据,说明自定义信息已成功持久化。
内容的提问来源于stack exchange,提问作者wmkoch
相关产品推荐
相关产品推荐

