【问题标题】:Spring OAuth2.0: Getting User Roles based on ClientId (Authorization Code Grant Type)Spring OAuth2.0:根据ClientId(授权码授予类型)获取用户角色
【发布时间】:2019-10-13 18:07:54
【问题描述】:

我为 AuthServer 设置了 spring boot OAuth,它可以使用 spring-security-jwt 为一些资源服务器提供身份验证服务。 我的问题是在进行身份验证时我需要加载用户的角色,但特定于 clientId。 例如:如果 user1 有角色 ROLE_A、ROLE_B 用于 client1 和 ROLE_C、ROLE_D 用于 client2,那么当用户使用 client1 或 client2 登录时,他能够看到所有四个角色,即。 ROLE_A, ROLE_B, ROLE_C, ROLE_D 因为我正在根据用户名获取角色。 如果我需要基于客户端的角色,那么我需要 clientId。 供参考, 我正在使用授权代码流进行身份验证。 我见过类似的问题,但这是基于密码授予,但我正在尝试授权代码流,该解决方案对我不起作用。 密码授予问题link

下面是我需要 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
        ....
    }
}

MyUserDetailsS​​ervice.java

@Override
    public UserDetails loadUserByUsername(String username) {
        String clientId = ? // how to get it 
        ....
    }
}

【问题讨论】:

    标签: spring-boot jwt spring-security-oauth2


    【解决方案1】:

    您可能需要在 Spring-security 中查看 OAuth2Authentication。当您的客户端通过 oauth2 身份验证时,您的“身份验证”实际上是最终实现身份验证的 OAuth2Authentication 实例。

    如果你看到 OAuth2Authentication 的实现,如下所示;

        public Object getPrincipal() {
           return this.userAuthentication == null ? this.storedRequest.getClientId() : this.userAuthentication
                .getPrincipal();
        }
    

    因此,如果请求包含“clientId”,那么只要您的请求不包含用户身份验证,您就应该能够通过调用 getPrincipal() 并将类型转换为 String 来获取 clientId。

    对于您的第二种情况,用户名实际上被视为 clientId。您需要调用内存中、RDBMS 或任何存储了 clientId 并返回 ClientDetails 的实现。通过查看 Spring security 的 ClientDetailsUserDetailsS​​ervice 类,您将能够有所了解。

    【讨论】:

    • 正如我所提到的,授权是授权代码,即我在此流程中同时处理用户身份验证和客户端身份验证。在我的情况下,MyAuthenticationProvider.java 将只处理用户身份验证,而不是客户端身份验证,因此它不包含 OAuth2Authentication。
    • @AbidAli 在用户签名后经过身份验证,现在他可以使用客户端应用程序执行操作,您可以创建 RBAC 来检查角色(即,如果那样,您必须使用身份验证服务器为您的应用程序分配一个角色存在于原则上,即当前用户)您也必须为 Auth Server 提供这样的角色,就像 OAuth 服务一样,将会有更多只执行 RBAC 任务的服务
    【解决方案2】:

    由于我的问题没有得到任何合适的解决方案,我发布了我在挖掘源代码和研究后使用的解决方案。
    MyJwtAccessTokenConverter.java(扩展 JwtAccessTokenConverter 并实施增强方法)

    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() 获取 clientId,从 authentication.getUserAuthentication() 获取 userDetails/user_name。
    在生成访问令牌步骤和刷新令牌步骤时,除了 JwtAccessTokenConverter 之外,还需要 AuthenticationProvider 和 UserDetailsS​​ervice 进行身份验证。

    【讨论】:

      【解决方案3】:

      从请求中获取授权标头,然后从 base64 解析以获取客户端 ID。

      类似这样的:

              HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
      .getRequestAttributes())
      .getRequest();
      String authHeader = request
      .getHeader("Authorization");
      

      【讨论】:

        猜你喜欢
        • 2019-01-09
        • 2017-01-14
        • 2019-04-13
        • 2018-09-20
        • 2020-04-28
        • 1970-01-01
        • 2018-05-26
        • 2019-05-16
        • 2019-05-21
        相关资源
        最近更新 更多