Spring应用程序基本身份验证通过keycloak
Posted
技术标签:
【中文标题】Spring应用程序基本身份验证通过keycloak【英文标题】:Spring app basic auth over keycloack 【发布时间】:2019-01-14 11:46:00 【问题描述】:我需要将身份验证添加到我的 Spring Boot (MVC) 应用程序中。身份验证提供者是通过 OpenID 的 keycloak。隐式和授权代码授权都被禁用,所以我被资源所有者凭据授权所困扰。我想要实现的是未授权用户的基本身份验证提示。以这种方式检索的凭据应该用于从 keycloak 获取令牌和用户信息,以供 Spring Security 进一步使用。应在每个请求上检查令牌。
我发现的大多数示例都使用org.keycloak:keycloak-spring-boot-starter
的重定向功能。虽然我找到了enable-basic-auth
here,但它对我不起作用。我知道我必须使用 keycloak.bearer-only=true
来关闭重定向,但它可以正常工作,而不是重定向它为未经授权的用户返回 401。
我的安全配置:
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver()
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()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().permitAll();
我的 keycloak 属性(我不使用占位符,只是为了安全起见):
keycloak.auth-server-url=https://$keycloak.host/auth/
keycloak.realm=master
keycloak.resource=$client.name
keycloak.enable-basic-auth=true
keycloak.credentials.secret=$client.secret
很抱歉提出一般性问题。我主要使用 jdbcAuthentication,这是我第一次使用身份管理软件。
【问题讨论】:
请注意,在您引用的那个文档中,它说“如果启用此选项,则还必须提供秘密。”这需要在客户端适配器的配置和领域中进行配置。见github.com/keycloak/keycloak/blob/master/examples/basic-auth/…这是来自官方keycloak基本认证示例 @RyanDawson 感谢您的回复!是的,我已打开所有这些选项:keycloak.credentials.secret=66666a66-66a6-6a66-666a-6a6a66aa666
和 Direct Access Grants Enabled
已打开。
您看到的失败行为是什么?我不清楚你所说的“不工作”是什么意思
@RyanDawson 我已经能够通过删除spring-boot-starter-security
和SecurityConfig.java
来实现使用curl 的基本身份验证,但是在浏览器中而不是获得基本身份验证提示时,我得到了重定向。使用 spring-boot-starter-security
和 SecurityConfig
基本身份验证即使使用 curl (HTTP/1.1 302
Location: http://localhost:8080/sso/login
) 也不起作用。 localhost:8080 是我的申请地址。
更新:需要自定义 authenticationEntryPoint 和 keycloak.bearer-only=true
。 401
响应的标头错误。应该是WWW-Authenticate: Basic realm="Restricted Content"
我稍后会发布代码
【参考方案1】:
这是一种通过具有资源所有者密码凭据流的 keycloak openid 向您的应用程序添加基本身份验证的方法。
首先你需要把它添加到 pom.xml:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>4.2.0.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
...
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
...
</dependencies>
添加 keycloak 服务器属性:
keycloak.auth-server-url=https://$keycloak.host/auth/
keycloak.realm=master
keycloak.resource=$client.name
keycloak.credentials.secret=$client.secret
keycloak.enable-basic-auth=true
keycloak.bearer-only=true
enable-basic-auth
实际上负责启用资源所有者密码凭证流。因此,每次您使用基本授权BasicAuthRequestAuthenticator
发送请求时,都会从 keycloak 请求令牌。需要bearer-only
才能关闭访问代码流。每次您在没有基本授权(和外部授权会话)的情况下向安全资源发出请求时,您都会被重定向到 keycloak 服务器——我们不希望这样。使用bearer-only
,您将获得 401。
最后一步是添加安全配置:
@Configuration
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
@EnableWebSecurity
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
@Bean
public KeycloakAuthenticationProvider authenticationProvider()
KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
provider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
return provider;
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver()
return new KeycloakSpringBootConfigResolver();
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy()
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
@Override
protected void configure(HttpSecurity http) throws Exception
super.configure(http);
http
.csrf().disable()
.exceptionHandling().authenticationEntryPoint((request, response, authException) ->
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Restricted Content\"");
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
)
.and()
.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.anyRequest().permitAll();
这里最有趣的部分是:
.exceptionHandling().authenticationEntryPoint((request, response, authException) ->
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"Restricted Content\"");
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
)
标准 keycloak AuthenticationEntryPoint
实现将 WWW-Authenticate
标头设置为 String.format("Bearer realm=\"%s\"", realm)
以防授权失败。我需要将其设置为Basic realm="Restricted Content"
才能弹出基本身份验证提示。如果你想避免使用这个提示(你想添加你自己的登录表单) - 删除这部分。
【讨论】:
以上是关于Spring应用程序基本身份验证通过keycloak的主要内容,如果未能解决你的问题,请参考以下文章
使用 spring restTemplate 对 REST API 进行基本身份验证
Spring OAuth2 禁用 TokenEndpoint 的 HTTP 基本身份验证
如何通过我的基本身份验证配置允许“/api/**”进入我在 Spring Security 中的 oauth 配置