在我的 Spring Boot 应用程序中,我想使用 keycloak 进行身份验证和授权,所以我根本不会使用 spring security,我会将所有内容留给 keycloak。
我使用了以下一系列视频来实现,如果有人可能熟悉的话: https://www.youtube.com/playlist?list=PLHXvj3cRjbzs8TaT-RX1qJYYK2MjRro-P
现在一切正常,但我有一个问题。在 SecurityConfig 中,我使用映射到 PolicyEnforcerConfig 的 JSON 文件来在授权和身份验证期间使用 Keycloak 配置。 但是,JSON 文件已将信息硬编码到其中。我怎样才能做到这一点,这样我就不必在那里显式定义客户端和领域信息,而是从 application.properties 访问它或以某种方式从类映射它,因为据我所知,目前我不能在 JSON 文件中使用占位符。
我愿意在 SecurityConfig 中进行更改,主要是确保 keycloak 之后执行所有操作。
这是我现在的 SecurityConfig 类:
import org.keycloak.adapters.authorization.integration.jakarta.ServletPolicyEnforcerFilter;
import org.keycloak.adapters.authorization.spi.ConfigurationResolver;
import org.keycloak.adapters.authorization.spi.HttpRequest;
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
import org.keycloak.util.JsonSerialization;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.server.resource.web.authentication.BearerTokenAuthenticationFilter;
import org.springframework.security.web.SecurityFilterChain;
import java.io.IOException;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(AbstractHttpConfigurer::disable);
httpSecurity.addFilterAfter(createPolicyEnforcerFilter(), BearerTokenAuthenticationFilter.class);
httpSecurity.sessionManagement(t -> t.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return httpSecurity.build();
}
private ServletPolicyEnforcerFilter createPolicyEnforcerFilter() {
return new ServletPolicyEnforcerFilter(new ConfigurationResolver() {
@Override
public PolicyEnforcerConfig resolve(HttpRequest httpRequest) {
try {
return JsonSerialization.readValue(getClass().getResourceAsStream("/policy-enforcer.json"),
PolicyEnforcerConfig.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
}
}
这是policy-enforcer.json:
{
"realm": "realm-name",
"auth-server-url": "server-url",
"resource": "client-name",
"credentials": {
"secret": "client-secret"
},
"http-method-as-scope": true,
"paths": [
{
"path": "/path-1",
"enforcement-mode": "DISABLED"
},
{
"path": "/path-2",
"enforcement-mode": "DISABLED"
}
]
}
通过此实现,一切正常,但我认为对客户端数据进行硬编码不是最好的。
在
application.properties
中设置以下内容。
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8081/realms/medium
在 SecurityConfig 上,如下所示。
@Bean
public SecurityFilterChain configurePaths(HttpSecurity http,
@Value("${security.authentication.unsecure.paths}") List<String> springSecurityAllowedPaths)
throws Exception {
AntPathRequestMatcher[] allowedPaths = springSecurityAllowedPaths.stream().map(AntPathRequestMatcher::new)
.toArray(AntPathRequestMatcher[]::new);
http.sessionManagement(
sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests.requestMatchers(allowedPaths)
.permitAll().anyRequest().authenticated());
http.oauth2ResourceServer(
oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())));
return http.build();
}