Spring OAuth2.0:根据ClientId获取用户角色(授权码授权类型)
Spring OAuth2.0: Getting User Roles based on ClientId (Authorization Code Grant Type)
我为 AuthServer 安装了 spring 启动 OAuth,它负责使用 spring-security-jwt 为一些资源服务器提供身份验证服务。
我的问题是在进行身份验证时我需要加载用户的角色但特定于 clientId。
例如:如果 user1 对 client1 具有 ROLE_A、ROLE_B 并且对 client2 具有 ROLE_C、ROLE_D,则当用户使用 client1 或 client2 登录时,他能够看到所有四个角色即。 ROLE_A、ROLE_B、ROLE_C、ROLE_D 因为我正在根据用户名获取角色。
如果我需要基于客户端的角色,那么我需要 clientId。
供参考,
我正在使用授权代码流进行身份验证。
我见过类似的问题,但这是基于密码授予,但我正在尝试授权代码流,但该解决方案对我不起作用。
密码授予问题
下面是我需要 clientId
的代码
MyAuthenticationProvider.java
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
String userName = ((String) authentication.getPrincipal()).toLowerCase();
String password = (String) authentication.getCredentials();
String clientId = ? // how to get it
....
}
}
MyUserDetailsService.java
@Override
public UserDetails loadUserByUsername(String username) {
String clientId = ? // how to get it
....
}
}
您可能需要在 Spring-security 中查看 OAuth2Authentication。当您的客户端通过 oauth2 进行身份验证时,您的 "authentication" 实际上是最终实现身份验证的 OAuth2Authentication 实例。
如果您看到 OAuth2Authentication 的实现,它是按如下方式完成的;
public Object getPrincipal() {
return this.userAuthentication == null ? this.storedRequest.getClientId() : this.userAuthentication
.getPrincipal();
}
因此,如果请求包含“clientId”,那么只要您的请求不包含用户身份验证,您就应该能够通过调用 getPrincipal() 并将类型转换为 String 来获取 clientId。
对于你的第二种情况,username 实际上被认为是 clientId。您需要调用 in-memory、RDBMS 或任何存储了 clientId 和 returns ClientDetails 的实现。通过查看 Spring 安全性的 ClientDetailsUserDetailsService class.
,您将能够有所了解
由于我的问题没有得到任何合适的解决方案,所以我发布了我在挖掘源代码和研究后使用的解决方案。
MyJwtAccessTokenConverter.java(扩展JwtAccessTokenConverter并实现enhance方法)
public class OAuthServerJwtAccessTokenConverter extends JwtAccessTokenConverter {
....
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String clientId = authentication.getOAuth2Request().getClientId();
// principal can be string or UserDetails based on whether we are generating access token or refreshing access token
Object principal = authentication.getUserAuthentication().getPrincipal();
....
}
....
}
信息:
在增强方法中,我们将从 authentication.getOAuth2Request() 和 userDetails/user_name 从 authentication.getUserAuthentication().
与 JwtAccessTokenConverter 一起,AuthenticationProvider 和 UserDetailsService 分别需要在生成访问令牌步骤和刷新令牌步骤中进行身份验证。
从请求中获取授权 header 然后从 base64 解析以获取 client-id.
像这样:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes())
.getRequest();
String authHeader = request
.getHeader("Authorization");
我为 AuthServer 安装了 spring 启动 OAuth,它负责使用 spring-security-jwt 为一些资源服务器提供身份验证服务。
我的问题是在进行身份验证时我需要加载用户的角色但特定于 clientId。
例如:如果 user1 对 client1 具有 ROLE_A、ROLE_B 并且对 client2 具有 ROLE_C、ROLE_D,则当用户使用 client1 或 client2 登录时,他能够看到所有四个角色即。 ROLE_A、ROLE_B、ROLE_C、ROLE_D 因为我正在根据用户名获取角色。
如果我需要基于客户端的角色,那么我需要 clientId。
供参考,
我正在使用授权代码流进行身份验证。
我见过类似的问题,但这是基于密码授予,但我正在尝试授权代码流,但该解决方案对我不起作用。
密码授予问题
下面是我需要 clientId
的代码
MyAuthenticationProvider.java
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
String userName = ((String) authentication.getPrincipal()).toLowerCase();
String password = (String) authentication.getCredentials();
String clientId = ? // how to get it
....
}
}
MyUserDetailsService.java
@Override
public UserDetails loadUserByUsername(String username) {
String clientId = ? // how to get it
....
}
}
您可能需要在 Spring-security 中查看 OAuth2Authentication。当您的客户端通过 oauth2 进行身份验证时,您的 "authentication" 实际上是最终实现身份验证的 OAuth2Authentication 实例。
如果您看到 OAuth2Authentication 的实现,它是按如下方式完成的;
public Object getPrincipal() {
return this.userAuthentication == null ? this.storedRequest.getClientId() : this.userAuthentication
.getPrincipal();
}
因此,如果请求包含“clientId”,那么只要您的请求不包含用户身份验证,您就应该能够通过调用 getPrincipal() 并将类型转换为 String 来获取 clientId。
对于你的第二种情况,username 实际上被认为是 clientId。您需要调用 in-memory、RDBMS 或任何存储了 clientId 和 returns ClientDetails 的实现。通过查看 Spring 安全性的 ClientDetailsUserDetailsService class.
,您将能够有所了解由于我的问题没有得到任何合适的解决方案,所以我发布了我在挖掘源代码和研究后使用的解决方案。
MyJwtAccessTokenConverter.java(扩展JwtAccessTokenConverter并实现enhance方法)
public class OAuthServerJwtAccessTokenConverter extends JwtAccessTokenConverter {
....
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
String clientId = authentication.getOAuth2Request().getClientId();
// principal can be string or UserDetails based on whether we are generating access token or refreshing access token
Object principal = authentication.getUserAuthentication().getPrincipal();
....
}
....
}
信息:
在增强方法中,我们将从 authentication.getOAuth2Request() 和 userDetails/user_name 从 authentication.getUserAuthentication().
与 JwtAccessTokenConverter 一起,AuthenticationProvider 和 UserDetailsService 分别需要在生成访问令牌步骤和刷新令牌步骤中进行身份验证。
从请求中获取授权 header 然后从 base64 解析以获取 client-id.
像这样:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes())
.getRequest();
String authHeader = request
.getHeader("Authorization");