英文:
Configure Keycloak 21 with Spring Security 6
问题
I'm here to provide the translated content for you. Here's the translation of your provided text:
我正在尝试设置Spring Security与Keycloak 21一起工作,但不幸的是,互联网上的大多数教程都已过时。我已经配置了Keycloak中的客户端和领域,但Spring Security不清楚应该如何配置。我尝试了来自这个链接的代码:
我添加了以下Gradle依赖项:
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:3.1.0'
implementation 'org.springframework.boot:spring-boot-starter-security:3.1.0'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.1.0'
以及以下YAML配置:
spring:
security:
oauth2:
client:
provider:
keycloak:
issuer-uri: https://ip/realms/admin_console_realm
registration:
keycloak-login:
authorization-grant-type: authorization_code
client-name: My Keycloak instance
client-id: admin_console_client
client-secret: qwerty
provider: keycloak
scope: openid,profile,email,offline_access
resourceserver:
jwt:
issuer-uri: https://ip/realms/admin_console_realm
jwk-set-uri: https://ip/realms/admin_console_realm/protocol/openid-connect/certs
不清楚我需要在这里添加什么Spring Security配置:
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.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeHttpRequests()
.requestMatchers("/*").hasAuthority("ROLE_TECH_SUPPORT")
.anyRequest().authenticated()
.and()
.oauth2Login();
return httpSecurity.build();
}
}
我已经将角色添加到Keycloak客户端:
当我在浏览器中打开一个Rest API链接时,我被重定向到Keycloak的登录页面。成功验证后,我收到以下消息:
无法访问ip,您没有查看此页面的授权。
HTTP错误403
您知道如何解决这个问题吗?
英文:
I'm trying to setup Spring Security to work with Keycloak 21 but unfortunately most of the tutorials on Internet are outdated. I configured client and realms into Keycloak but Spring security is not clear what should be. I tried the code from this link:
I added these gradle dependencies:
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:3.1.0'
implementation 'org.springframework.boot:spring-boot-starter-security:3.1.0'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.1.0'
and this yml config:
spring:
security:
oauth2:
client:
provider:
keycloak:
issuer-uri: https://ip/realms/admin_console_realm
registration:
keycloak-login:
authorization-grant-type: authorization_code
client-name: My Keycloak instance
client-id: admin_console_client
client-secret: qwerty
provider: keycloak
scope: openid,profile,email,offline_access
resourceserver:
jwt:
issuer-uri: https://ip/realms/admin_console_realm
jwk-set-uri: https://ip/realms/admin_console_realm/protocol/openid-connect/certs
It's not clear what I need to add as a Spring security configuration here:
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.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeHttpRequests()
.requestMatchers("/*").hasAuthority("ROLE_TECH_SUPPORT")
.anyRequest().authenticated()
.and()
.oauth2Login();
return httpSecurity.build();
}
}
I added the role into Keycloak client:
When I open a Rest API link into the browser I'm redirected to Keycloak's login page. After successful authentication I get:
Access to ip was deniedYou don't have authorization to view this page.
HTTP ERROR 403
Do you know how I can fix this issue?
答案1
得分: 3
Here is the translated content:
如果您正在尝试公开受Keycloak服务器(身份验证服务器)保护的REST API,则您的应用程序是OAuth2资源服务器,而不是OAuth2客户端服务器,除非它们是公共的,否则您不能使用浏览器访问您的REST API。
对于具有REST API的资源服务器,您可以使用以下代码:
- application.yml
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://<KEYCLOAK_SERVER_IP>/realms/<YOUR_REALM_NAME>
jwk-set-uri: http://<KEYCLOAK_SERVER_IP>/realms/<YOUR_REALM_NAME>/protocol/openid-connect/certs
- 从Keycloak服务器获取JWT令牌(此CURL等同于用于从Keycloak获取访问令牌的Postman请求,您可以在此处找到更多信息 https://documenter.getpostman.com/view/7294517/SzmfZHnd)
curl --location 'http://<KEYCLOAK_SERVER_IP>/realms/test/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=<YOUR_USER_NAME>' \
--data-urlencode 'password=<YOUR_USER_PASSWORD>' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_id=<KEYCLOAK_CLIENT_ID>' \
--data-urlencode 'client_secret=<KEYCLOAK_CLIENT_SECRET>' \
--data-urlencode 'scope=openid';
- 使用 https://jwt.io/ 检查您的访问令牌
...
"realm_access": {
"roles": [
"default-roles-test",
"offline_access",
"MY_REALM_ROLE",
"uma_authorization"
]
},
"resource_access": {
"test-client": {
"roles": [
"MY_CLIENT_ROLE"
]
},
...
现在,我们需要告诉Spring Security从JWT令牌中查找角色信息的位置。
- WebSecurityConfig.java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeHttpRequests(registry -> registry
.requestMatchers("/my-api/**").hasRole("MY_REALM_ROLE")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2Configurer -> oauth2Configurer.jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(jwt -> {
Map<String, Collection<String>> realmAccess = jwt.getClaim("realm_access");
Collection<String> roles = realmAccess.get("roles");
var grantedAuthorities = roles.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
return new JwtAuthenticationToken(jwt, grantedAuthorities);
})))
;
return httpSecurity.build();
}
}
确保您在Keycloak中为用户进行适当的角色映射。
现在,要使用您的REST API,您可以使用Postman。在Postman中添加Bearer Token授权,并使用从Keycloak服务器生成的最新访问令牌。
英文:
if you are trying to expose rest APIs secured with Keycloak Server (Authentication Server) then your application is a OAuth2 resource server not a OAuth2 client server and also you can't use browser for accessing your rest APIs unless they are public.
For Resource Server with rest APIs you can use the below code
- application.yml
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://<KEYCLOAK_SERVER_IP>/realms/<YOUR_REALM_NAME>
jwk-set-uri: http://<KEYCLOAK_SERVER_IP>/realms/<YOUR_REALM_NAME>/protocol/openid-connect/certs
- Get JWT TOKEN from Keycloak Server (this curl is equivalent to postman request for keycloak to get access token, you can find more here https://documenter.getpostman.com/view/7294517/SzmfZHnd)
curl --location 'http://<KEYCLOAK_SERVER_IP>/realms/test/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=<YOUR_USER_NAME>' \
--data-urlencode 'password=<YOUR_USER_PASSWORD>' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'client_id=<KEYCLOAK_CLIENT_ID>' \
--data-urlencode 'client_secret=<KEYCLOAK_CLIENT_SECRET>' \
--data-urlencode 'scope=openid'
- Inspect your access token using https://jwt.io/
...
"realm_access": {
"roles": [
"default-roles-test",
"offline_access",
"MY_REALM_ROLE",
"uma_authorization"
]
},
"resource_access": {
"test-client": {
"roles": [
"MY_CLIENT_ROLE"
]
},
...
Now, we need to tell spring security from where it has look for Roles information in the JWT token.
- WebSecurityConfig.java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
// Note: Please change '/mp-api/**' to your desired rest controller path.
httpSecurity
.authorizeHttpRequests(registry -> registry
.requestMatchers("/my-api/**").hasRole("MY_REALM_ROLE")
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2Configurer -> oauth2Configurer.jwt(jwtConfigurer -> jwtConfigurer.jwtAuthenticationConverter(jwt -> {
Map<String, Collection<String>> realmAccess = jwt.getClaim("realm_access");
Collection<String> roles = realmAccess.get("roles");
var grantedAuthorities = roles.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toList());
return new JwtAuthenticationToken(jwt, grantedAuthorities);
})))
;
return httpSecurity.build();
}
}
Make sure you have proper Role Mappings for User in Keycloak.
Now, for using your rest API you can use Postman. In Postman add
Bearer Token Authorization and use the latest generated access token from keycloak server.
答案2
得分: 2
我们最近将应用程序迁移到使用Spring Boot 3.0.4和Keycloak 21.0.1。配置如下:
实施 'org.springframework.boot:spring-boot-starter-oauth2-client:3.0.4'
实施 'org.springframework.boot:spring-boot-starter-security:3.0.4'
实施 'org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.0.4'
YAML配置:
<!-- 语言:yml -->
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://<keycloak-base-url>/realms/<realms-name>
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://<keycloak-base-url>/realms/<realms-name>/protocol/openid-connect/certs
Spring安全配置:
<!-- 语言:java -->
@Configuration
public class WebSecurityConfig {
@Autowired
private CorsConfigurationSource corsConfigurationSource;
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.headers()
.frameOptions().disable();
httpSecurity
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt();
httpSecurity
.cors()
.configurationSource(corsConfigurationSource)
.and()
.csrf().disable();
return httpSecurity.build();
}
}
英文:
We recently migrated our application to use Spring Boot 3.0.4 and Keycloak 21.0.1 The configuration look like below,
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:3.0.4'
implementation 'org.springframework.boot:spring-boot-starter-security:3.0.4'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server:3.0.4'
YAML config:
<!-- language: yml -->
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://<keycloak-base-url>/realms/<realms-name>
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://<keycloak-base-url>/realms/<realms-name>/protocol/openid-connect/certs
Spring Security configuration is:
<!-- language: java -->
@Configuration
public class WebSecurityConfig {
@Autowired
private CorsConfigurationSource corsConfigurationSource;
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.headers()
.frameOptions().disable();
httpSecurity
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt();
httpSecurity
.cors()
.configurationSource(corsConfigurationSource)
.and()
.csrf().disable();
return httpSecurity.build();
}
}
答案3
得分: 1
以下是您提供的代码部分的中文翻译:
// 如果有人来到这里查找在Spring Security版本6.1和Spring Boot 3.1中与Keycloak配合使用的实现是什么样的。
// 如果您遇到关于JwtDecoder的错误,请关注这一行代码:.jwkSetUri(jwkSetUri)
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity(debug = true)
public class WebSecurityConfig {
public static final String ADMIN = "admin";
public static final String USER = "user";
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwkSetUri;
private final JwtAuthConverter jwtAuthConverter;
@Bean
public SecurityFilterChain securityFilterChain2(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorizeHttpRequests) ->
authorizeHttpRequests
.requestMatchers("/api/duenos/**").hasAnyRole(ADMIN, USER)
.requestMatchers("/api/objetos_extraviados/**").hasAnyRole(ADMIN, USER)
.anyRequest().authenticated()
)
.oauth2ResourceServer((oauth2ResourceServer) ->
oauth2ResourceServer
.jwt((jwt) ->
jwt
.jwtAuthenticationConverter(jwtAuthConverter)
.jwkSetUri(jwkSetUri)
)
)
.sessionManagement((sessionManagement) -> sessionManagement
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);
return http.build();
}
}
请注意,代码中的HTML实体编码(如")已被保留,以确保代码的正确性。
英文:
In case someone comes here looking for what an implementation in version 6.1 of Spring Security, Spring Boot 3.1 configured to work with keycloack would look like.
If you get an error about JwtDecoder, this line takes care of it: .jwkSetUri(jwkSetUri)
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity(debug = true)
public class WebSecurityConfig {
public static final String ADMIN = "admin";
public static final String USER = "user";
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwkSetUri;
private final JwtAuthConverter jwtAuthConverter;
@Bean
public SecurityFilterChain securityFilterChain2(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((authorizeHttpRequests) ->
authorizeHttpRequests
.requestMatchers("/api/duenos/**").hasAnyRole(ADMIN, USER)
.requestMatchers("/api/objetos_extraviados/**").hasAnyRole(ADMIN, USER)
.anyRequest().authenticated()
)
.oauth2ResourceServer((oauth2ResourceServer) ->
oauth2ResourceServer
.jwt((jwt) ->
jwt
.jwtAuthenticationConverter(jwtAuthConverter)
.jwkSetUri(jwkSetUri)
)
)
.sessionManagement((sessionManagement) -> sessionManagement
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
);
return http.build();
}
}
Las dependencias que usé:
spring-boot-starter-oauth2-resource-server
spring-security-oauth2-jose
spring-boot-starter-security
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论