Spring boot 验证后未执行Spring安全oauth2Login OAuth2UserService

Spring boot 验证后未执行Spring安全oauth2Login OAuth2UserService,spring-boot,spring-security,keycloak,spring-security-oauth2,spring-boot-admin,Spring Boot,Spring Security,Keycloak,Spring Security Oauth2,Spring Boot Admin,我有一个由KeyClope保护的Spring Boot管理应用程序,我定义了一个具有领域角色执行器的用户。 问题是,经过身份验证后,Spring安全性无法访问领域角色。我可以看到授予的权限:授予的权限:角色\用户、范围\执行器\访问、范围\配置文件' 查看文档,我发现了以下部分:这是我的配置: @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override p

我有一个由KeyClope保护的Spring Boot管理应用程序,我定义了一个具有领域角色<代码>执行器的用户。 问题是,经过身份验证后,Spring安全性无法访问领域角色。我可以看到授予的权限:
授予的权限:角色\用户、范围\执行器\访问、范围\配置文件'

查看文档,我发现了以下部分:这是我的配置:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure( HttpSecurity http ) throws Exception {
        http.csrf().disable().cors().disable();
        http.authorizeRequests()
                .antMatchers( "/error","/instances", "/**/*.css", "/**/img/**", "/**/third-party/**", "/*.js" )
                .permitAll()
                .anyRequest().hasRole( "ACTUATOR" )
                .and()
                .oauth2Login( oauth2 -> oauth2.userInfoEndpoint(
                        userInfo -> userInfo.oidcUserService( this.oidcUserService() ) ) );
    }

    // I just copy-paste the doc's code to play with it...
    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {

        final OidcUserService delegate = new OidcUserService();

        return ( userRequest ) -> {
            OidcUser oidcUser = delegate.loadUser( userRequest );

            //TODO find a way to extract realm roles 
            OAuth2AccessToken accessToken = userRequest.getAccessToken();

            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

            oidcUser = new DefaultOidcUser( mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo() );

            return oidcUser;
        };
    }
这是我的配置:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure( HttpSecurity http ) throws Exception {
        http.csrf().disable().cors().disable();
        http.authorizeRequests()
                .antMatchers( "/error","/instances", "/**/*.css", "/**/img/**", "/**/third-party/**", "/*.js" )
                .permitAll()
                .anyRequest().hasRole( "ACTUATOR" )
                .and()
                .oauth2Login( oauth2 -> oauth2.userInfoEndpoint(
                        userInfo -> userInfo.oidcUserService( this.oidcUserService() ) ) );
    }

    // I just copy-paste the doc's code to play with it...
    private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {

        final OidcUserService delegate = new OidcUserService();

        return ( userRequest ) -> {
            OidcUser oidcUser = delegate.loadUser( userRequest );

            //TODO find a way to extract realm roles 
            OAuth2AccessToken accessToken = userRequest.getAccessToken();

            Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

            oidcUser = new DefaultOidcUser( mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo() );

            return oidcUser;
        };
    }
@配置
公共类SecurityConfig扩展了WebSecurity配置适配器{
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http.csrf().disable().cors().disable();
http.authorizeRequests()
.antMatchers(“/error”、“/instances”、“/**.css”、“/**/img/**”、“/**/third-party/**”、“/**.js”)
.permitAll()
.anyRequest().hasRole(“执行器”)
.及()
.oauth2Login(oauth2->oauth2.userInfoEndpoint(
userInfo->userInfo.oidcUserService(this.oidcUserService());
}
//我只是复制粘贴文档的代码来玩它。。。
专用OAuth2UserService oidcUserService(){
最终OidcUserService委托=新OIDCUSERVICE();
返回(用户请求)->{
OidcUser OidcUser=delegate.loadUser(userRequest);
//TODO找到提取领域角色的方法
OAuth2AccessToken accessToken=userRequest.getAccessToken();
Set mappedAuthorities=new HashSet();
oidcUser=新的DefaultOidcUser(mappedAuthorities,oidcUser.getIdToken(),oidcUser.getUserInfo());
回归方程;
};
}
我希望使用方法
oidcUserService()
从令牌中提取Keyclope领域角色,但该方法根本没有执行。我的意思是在成功地从Keyclope进行身份验证并重定向到应用程序后,
OIDCUSERVICE()
方法未执行。它似乎只在应用程序启动时执行,这很奇怪

问题是在这个场景中我如何检索领域角色

编辑

我在这里添加了一个示例项目:


安全配置在
application.yml
SecurityConfig
class

中,我不知道为什么不调用此oidcUserService。您可以使用它,并将JWT映射到您需要的任何角色

这有点棘手,所以这里有两个例子:

  • (最新但有点太宽泛,请看“自定义索赔”部分)
  • (过时)

注意:我不知道您是否应该在解析JWT签名之前亲自检查它,或者Spring OAuth是否会这样做。这是值得检查的。

我不知道为什么没有调用此oidcUserService。您可以使用它,并将JWT映射到您需要的任何角色

这有点棘手,所以这里有两个例子:

  • (最新但有点太宽泛,请看“自定义索赔”部分)
  • (过时)

注意:我不知道在解析JWT签名之前是否应该自己检查它,或者Spring OAuth是否会这样做。这是值得检查的。

我发现了为什么要使用
oidcUserService()
方法在身份验证后未被调用。原因是令牌的类型,我从Spring安全文档中复制了代码,但没有注意这些信息

在文档中它是关于
OidcUserRequest
的,而在我的例子中它是
OAuth2UserRequest
,因此它是
OAUTH2
OIDC
之间的冲突。将方法更改为:

private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
   // code extracting authorities from JWT here

}
专用OAuth2UserService OAuth2UserService(){
//这里是从JWT提取权限的代码
}

解决了我的问题。我现在可以从访问令牌获取KeyClope域角色。

我找到了身份验证后未调用
oidcUserService()
方法的原因。原因是令牌的类型,我从Spring安全文档中复制了代码,但没有注意这些信息

在文档中它是关于
OidcUserRequest
的,而在我的例子中它是
OAuth2UserRequest
,因此它是
OAUTH2
OIDC
之间的冲突。将方法更改为:

private OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService() {
   // code extracting authorities from JWT here

}
专用OAuth2UserService OAuth2UserService(){
//这里是从JWT提取权限的代码
}

解决了我的问题。我现在可以从访问令牌中获取keydove领域角色。

谢谢你的建议,但我希望避免使用keydove适配器。我使用Spring security 5,它提供了完全的Oauth2支持。唯一的问题是我们必须自定义很多东西。@akuma8你能在Github上放置一个示例项目吗?没有查看您正在谈论的所有定制很难理解为什么它不起作用…感谢这个项目,这很有帮助。我更新了我的答案。解析JWT适用于资源服务器,但我的情况并非如此。我有一些项目使用这种方法,因为
授权中存在承载令牌ode>header。另外,正如您所看到的,
jwt()
方法遵循
oauth2ResourceServer()
元素,在我的例子中,我使用
oauth2Login()
。很抱歉,我仍然不明白。您的授权服务器是KeyClope。我了解spring boot admin应用程序包含您要保护的资源。如果您的应用程序只是Oauth2提供商,那么它提供了什么访问权限?另外,如果不解析JWT声明和(除其他外)将它们映射到角色?您计划如何在不解析JWT(或让spring oauth lib为您完成)的情况下获得正确的角色?谢谢您的建议,但我希望避免使用KeyClope适配器。我使用spring security 5,它提供了完全的Oauth2支持。唯一的问题是我们必须