我想根据请求 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 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-多租户