当前位置: 首页 > 知识库问答 >
问题:

如何为特定的索赔结构配置JwtAuthentiationConverter?

孟永望
2023-03-14

我有一个JWT,其中的角色可以在特定的声明下找到。此声明位于嵌套结构中。我如何告诉JwtAuthenticationConverter在特定路径下查找角色?

作为授权服务器,我使用keydrope。可以为角色添加映射器。但我现在想排除这种可能性,因为目标是找到特定声明下的角色。

这是我解码的JWT。角色“user role”应位于声明“resource\u access”下-

  "resource_access": {
    "admin": {
      "roles": [
        "admin-role"
      ]
    },
    "user": {
      "roles": [
        "user-role"
      ]
    },
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },

这是我对JwtAuthentiationConverter的配置:

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
    @Override
    public void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(jwtAuthenticationConverter());
    }

    private static JwtAuthenticationConverter jwtAuthenticationConverter()
    {
        var jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("resource_access.user.roles");
        jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
        var jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        return jwtAuthenticationConverter;
    }
}

我希望有人能帮助我。谢谢:)

共有1个答案

池赞
2023-03-14

谢谢你的帮助。解决方案是实现一个自定义转换器。

以下是我的解决方案:

我的自定义转换器:

@AllArgsConstructor
public class KeycloakJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken>
{
    @NotEmpty
    private List<String> clientIds;

    @Override
    public AbstractAuthenticationToken convert(Jwt source)
    {
        return new JwtAuthenticationToken(source, Stream.concat(new JwtGrantedAuthoritiesConverter().convert(source)
                .stream(), extractResourceRoles(source).stream())
                .collect(toSet()));
    }

    private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt)
    {
        var resourceAccess = new HashMap<>(jwt.getClaim("resource_access"));
        var resourceRoles = new ArrayList<>();

        clientIds.stream().forEach(id ->
        {
            if (resourceAccess.containsKey(id))
            {
                var resource = (Map<String, List<String>>) resourceAccess.get(id);
                resource.get("roles").forEach(role -> resourceRoles.add(id + "_" + role));
            }
        });
        return resourceRoles.isEmpty() ? emptySet() : resourceRoles.stream().map(r -> new SimpleGrantedAuthority("ROLE_" + r)).collect(toSet());
    }
}

我的安全配置:

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
    @Value("${spring.security.jwt.role.locations}")
    private List<String> rolesLocation;

    @Override
    public void configure(HttpSecurity http) throws Exception
    {
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt()
                .jwtAuthenticationConverter(new KeycloakJwtAuthenticationConverter(rolesLocation));
    }
}
 类似资料:
  • 问题内容: 原谅我,我来自ac#背景! 我在Go中有以下结构。我们通过从文件中读取配置来填充此结构,效果很好。但是我试图找出一种方法来告诉结构中的某个特定属性(通过配置文件传递时是否为null)。如图所示,完全没有设置。 我为此奋斗了大约3个小时。我可以针对类型字符串等执行此操作,但无法找到针对所有类型的通用方法? 问题答案: 在执行过程中,值的默认值为其零值。您可能要使所有类型的指针成为指针(例

  • 3.2.1 配置结构 当默认的工程结构不适用的时候,你可能需要配置它。根据 Gradle 文档说明,可以通过如下方式重新配置Java工程的 sourceSets: sourceSets { main { java { srcDir 'src/java' } resources { srcDir

  • 我在MySQL中有一些结构相同的遗留表,如: 有没有一种方法可以配置JOOQ codegen,使其只生成一个由所有这些表共享的表/记录类?

  • 问题内容: 最近,我开始着手研究使用MySQL用PHP编写的遗留电子商务应用程序中的ElasticSearch(ES)实施。我对所有这些东西都是新手,阅读文档很好,但是我确实需要有经验的人为我提供建议。 从ES文档中,我可以设置一个新集群,并且我还发现河已被弃用,应该将其替换,因此我将它们替换为Logstash和JDBC MySQL连接器。 此时,我有: elasticsearch Logstas

  • 当默认的项目结构不适用时,可以自定义配置。查看 Gradle 文档中 Java plugin 部分以了解如何在纯 Java 项目中进行配置。 Android plugin 使用了类似的语法,但因为 Android 有自己的 sourceSets,所以需要配置到 android 块中。下面的例子使用了旧的项目结构(Eclipse),并把 androidTest 的 sourceSet 映射到 tes

  • 问题内容: 我试图找出一种在Hive中从平面源中选择数据并将其输出到一个名为struct的数组中的方法。这是我正在寻找的示例… 样本数据: 所需的输出: 我尝试了collect_list和collect_set,但是它们仅允许原始数据类型。关于如何在Hive中进行此操作有任何想法吗? 问题答案: 我会使用这个jar,它是的更好的实现(并需要复杂的数据类型)。 查询 : 输出 :