java - Keycloak 虚拟配置
问题描述
我有以 Keycloak 作为身份验证提供者的 Spring Boot 项目。是否可以为特定的弹簧配置文件创建“虚拟身份验证”?我想要配置文件'dummy-auth',它将始终将 KeycloakPrincipal 设置为一些虚拟用户。也许某种过滤器可以更换?我有我的密钥斗篷配置:
@KeycloakConfiguration
public class KeycloakSecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
@Bean
public KeycloakSpringBootConfigResolver keycloakSpringBootConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.anyRequest()
.fullyAuthenticated();
}
}
并且真的不知道如何实现这个虚拟身份验证。也许更好的选择是某种嵌套的 keycloak 实例?
解决方案
几个建议;
1.拥有多个个人资料
我会为不同的目的推荐不同的配置文件;keycloak,本地,keycloak-local。
钥匙斗篷
当您想要与身份提供者集成并将从 Keycloak 检索到的 Authenticated Object 设置为您的 Spring 上下文时,请使用此配置文件。
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
@Profile( "keycloak" )
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
@Bean
public KeycloakSpringBootConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy( )
{
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Autowired
public void configureGlobal( AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Override
protected void configure( HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/hello")
.authenticated()
.anyRequest()
.permitAll();
}
}
当地的
还创建一个本地配置文件,您不想随身份提供者一起发布但仍想将经过身份验证的用户注入到您的上下文中
@Configuration
@EnableWebSecurity
@ComponentScan( basePackageClasses = KeycloakSecurityComponents.class )
@Profile( "local" )
public class LocalSecurityConfig extends WebSecurityConfigurerAdapter
{
@Override
protected void configure( HttpSecurity http ) throws Exception
{
http.authorizeRequests( )
.antMatchers( "/hello" )
.authenticated( )
.anyRequest( )
.permitAll( )
.and( )
.formLogin( );
}
@Autowired
public void configureGlobal( AuthenticationManagerBuilder auth )
throws Exception
{
auth
.inMemoryAuthentication( )
.withUser( "user" )
.password( passwordEncoder().encode( "password") )
.roles( "USER" );
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Keycloak-本地
或者更好的是,我们可以将真正的 Keycloak Authenticated 对象设置为特定配置文件中的上下文。如果您在上下文中需要更复杂的 Authentication 对象并且您附带 KeycloakAuthenticationToken,请使用此方法。否则本地配置文件也很好,因为这需要更多编码,但这也是工作示例:
创建一个过滤器,我们称之为LocalFilter。此过滤器将创建一个 KeycloakAuthenticationToken 并将其设置为 spring 上下文:
public class LocalFilter extends GenericFilterBean
{
@Override
public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain )
throws IOException, ServletException
{
SecurityContextHolder.getContext( ).setAuthentication( generateKeycloakToken( "stackoverflow.com", "ROLE_USER", "" ) );
filterChain.doFilter(servletRequest, servletResponse);
}
public static KeycloakAuthenticationToken generateKeycloakToken( String org, String roles, String permissions )
{
AccessToken accessToken = new AccessToken( );
if ( org != null && !org.isEmpty( ) )
{
accessToken.setOtherClaims( "org", org );
}
if ( permissions != null && !permissions.isEmpty( ) )
{
accessToken.setOtherClaims( "permissions", permissions );
}
RefreshableKeycloakSecurityContext rksc =
new RefreshableKeycloakSecurityContext( null, null, UUID.randomUUID( ).toString( ), accessToken, null, null,
null );
Set<String> rolesSet = new HashSet<>( );
String[] roleArr = roles.split( "," );
for ( String role : roleArr )
{
rolesSet.add( role.trim( ) );
}
KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<>( "name", rksc );
Collection<GrantedAuthority> authorities = generateGrantedAuthority( roles );
return new KeycloakAuthenticationToken( new SimpleKeycloakAccount( principal, rolesSet, rksc ), false,
authorities );
}
public static Collection<GrantedAuthority> generateGrantedAuthority( String roles )
{
Collection<GrantedAuthority> authorities = new ArrayList<>( );
for ( String role : roles.split( "," ) )
{
authorities.add( new SimpleGrantedAuthority( role.trim( ) ) );
}
return authorities;
}
}
并在您的 SecurityConfig 中配置过滤器:
@Configuration
@EnableWebSecurity
@ComponentScan( basePackageClasses = KeycloakSecurityComponents.class )
@Profile( "local-keycloak" )
public class LocalKeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
@Bean
public KeycloakSpringBootConfigResolver keycloakConfigResolver( )
{
return new KeycloakSpringBootConfigResolver( );
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy( )
{
return new RegisterSessionAuthenticationStrategy( new SessionRegistryImpl( ) );
}
@Autowired
public void configureGlobal( AuthenticationManagerBuilder auth ) throws Exception
{
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider( );
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper( new SimpleAuthorityMapper( ) );
auth.authenticationProvider( keycloakAuthenticationProvider );
}
@Override
protected void configure( HttpSecurity http ) throws Exception
{
super.configure( http );
http.addFilterBefore(new LocalFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests( )
.antMatchers( "/hello" )
.authenticated( )
.anyRequest( )
.permitAll( );
}
}
2. If Resource Server: Token 不与 Identity Provider 交互
如果您将客户端用作 Keycloak 的资源服务器,则有一种方法可以在不与身份提供者交互的情况下验证您的身份验证。按照步骤;
- 生成 JWT(如果您需要一些样本或在任何地方生成它,您可以为 Keycloak 创建一个虚拟客户端并复制它,记下您的算法和公钥)
- 如果您使用 Keycloak 生成 jwt,请从领域设置 -> 密钥 -> 复制公钥属于算法(默认为 RS256)复制您的公钥并将其保存到应用程序中的某个位置,例如:src/main/test/resources
- 而不是用and来
issuer-uri
配置你的服务。通过这样做,您的服务将不会请求您的身份提供者来验证承载。public-key
jws-algorithm
- 对于 spring security oauth2 库,这里是一个示例配置:
spring
security:
oauth2:
resourceserver:
jwt:
public-key-location: classpath:jwt_public_key.json
jws-algorithm: RS256 # this is default, you can skip setting it
- 现在将您的令牌作为Bearer标头发送。
推荐阅读
- angular - 使用在同一模块上声明的 Angular 组件
- javascript - 从 Javascript 创建跳转到页面
- javascript - 导入“dayjs/local/en”时出错?
- javascript - [Vue 警告]:观察者“childItems”的回调错误:“TypeError:无法读取未定义的属性‘标签’”
- android - 如何使用 Android Room 运行诸如“DELETE FROM table_name WHERE name LIKE '%abc%' AND name LIKE '%def%'”之类的 sql?
- realm - 重新路由领域网络以在本地进行笑话测试,调用领域功能时出错
- clojure - 将依赖项“clojure.tools.trace”导入 Clojure 中的 REPL 失败:找不到文件
- php - Symfony 5(包括 4)使用 Gedmo Doctrine Extension for SoftDelete
- mongodb - 使用 flask-mongoengine 连接到 MongoDB atlas 集群
- python-3.x - 我将如何诊断 python3 中的 ssl.WRONG_VERSION_NUMBER 错误