资源服务器多个jwt.issuer-uri

问题描述 投票:0回答:1

我想根据请求 URL 设置

jwt.issuer-uri

假设我有一个请求

http://hostname/realm1/request
那么我想将
jwt.issuer-uri
设置为
http://keycloak-host/auth/realms/realm1

如果第二个请求来自

https://hostname/realm2/request
,则
jwt.issuer-uri
将是
http://keycloak-host/auth/realms/realm2

我所做的是创建一个

SecurityFilterChain
,就像

@Bean
@Order(100)
public SecurityFilterChain myJwtSecFilterChain (HttpSecurity http) throws Exception {

    http.authorizeHttpRequests(auth -> {
        auth.requestMatchers("/api/**").authenticated();
    });

    http.oauth2ResourceServer(oauth -> {
        oauth.jwt(jwt -> {
            jwt.decoder(new MyJwtDecoder());
        });
    });

    return http.build();
}

然后是解码器:

public class MyJwtDecoder implements JwtDecoder {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyJwtDecoder.class);

    public MyJwtDecoder() {
    }

    @Override
    public Jwt decode(String token) throws JwtException {
        LOGGER.debug("*********** MyJwtDecoder - decode token {}", token);
        return getJwt(token);
    }

    private Jwt getJwt(String token) {

        Jwt result = null;
        List<String> realmList = List.of("realm1", "realm2");
        for (String realm : realmList) {
            JwtDecoder jdLocal = JwtDecoders.fromIssuerLocation("http://keycloak-host/auth/realms/" + realm);
            try {
                result = jdLocal.decode(token);
                LOGGER.info("TOKEN VALIDATED !!!!!");
                break;
            } catch (JwtValidationException vex) {
                LOGGER.info("Jwt validation exception - Stop Validation - Exception type {} - Message: {}", vex.getClass().getSimpleName(), vex.getMessage());
                throw vex;
            } catch (Exception ex) {
                // Continue with validation
                LOGGER.info("Jwt validation exception - Continue with other realms validation - Exception type {} - Message: {}", ex.getClass().getSimpleName(), ex.getMessage());
            }
        }
        return result;
    }
}

如何修改解码器以使用请求 URL,而不是循环进入领域?

另一个选项可能是在

BearerTokenAuthenticationFilter
之前创建一个过滤器,但在这种情况下我如何绑定解码器?

请不要用已弃用的适配器给我答案。

spring-boot spring-security keycloak
1个回答
0
投票

您可以配置 Spring OAuth2 资源服务器,以根据令牌中包含的“Issuer Claim”自动找出令牌颁发者。

这里是实现动态发行人解析的代码

JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = JwtIssuerAuthenticationManagerResolver
    .fromTrustedIssuers("http://keycloak-host/auth/realms/realm1", "http://keycloak-host/auth/realms/realm2");

http
    .authorizeHttpRequests(authorize -> authorize
        .anyRequest().authenticated()
    )
    .oauth2ResourceServer(oauth2 -> oauth2
        .authenticationManagerResolver(authenticationManagerResolver)
    );

如果您需要更深入的配置选项,Spring Security 文档有很好的解释:https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/multitenancy.html#oauth2resourceserver-多租户

© www.soinside.com 2019 - 2024. All rights reserved.