带有 Keycloak 的 Springboot 总是 return 403
Springboot with Keycloak always return 403
我已经按照本教程使用 Keycloak 创建了一个 Springboot 应用程序 Baeldung
当我尝试输入 /api/foos 时,它总是 returns 403 而没有任何错误消息。
// SecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
class SecurityConfig(
private val unauthorizedHandler: JwtAuthenticationEntryPoint
) : WebSecurityConfigurerAdapter() {
@Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http
.cors()
.and()
.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/user/info", "/api/foos/**", "/api/foos")
.hasAnyRole("free_user")
.antMatchers(HttpMethod.POST, "/api/foos")
.hasAnyRole("free_user")
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
}
}
// Controller
@RestController
@RequestMapping(value = ["/api/foos"])
class SecurityTestController() {
@GetMapping(value = ["/{id}"])
fun findOne(@PathVariable id: Long?): String {
return "fineOne with id $id"
}
@GetMapping
fun findAll(): Message {
return Message("findAll")
}
}
// application.properties
# Resource server config
rest.security.issuer-uri=http://localhost:8081/auth/realms/dev
spring.security.oauth2.resourceserver.jwt.issuer-uri=${rest.security.issuer-uri}
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${rest.security.issuer-uri}/protocol/openid-connect/certs
// build.gradle (app)
plugins {
id("org.springframework.boot")
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter- oauth2-resource-server")
implementation("org.springframework.boot:spring-boot-starter-security")
testImplementation("org.springframework.security:spring-security-test")
}
这是我在 Keycloak 上的用户
邮递员结果:
我已经尝试过的
- 禁用 csrf - 不工作
- 评论 SecurityConfig class - 在没有安全的情况下工作
看起来“free_user”是客户端角色。
两种解决方案:
要么删除当前的“free_user”客户端角色,在全局角色选项卡中创建一个“free_user”领域角色,然后将其分配给您的用户。
或者,将 属性 keycloak.use-resource-role-mappings=true
添加到您的 Spring 引导配置,以允许 spring 安全映射您当前的客户端角色。
我在这里找到了答案LINK
我们需要在 Spring 安全和 Keycloak 角色之间创建自定义映射。
public class KeycloakRealmRoleConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
@Override
public Collection<GrantedAuthority> convert(Jwt jwt) {
final Map<String, Object> realmAccess = (Map<String, Object>) jwt.getClaims().get("realm_access");
return ((List<String>)realmAccess.get("roles")).stream()
.map(roleName -> "ROLE_" + roleName) // prefix to map to a Spring Security "role"
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
}
我已经按照本教程使用 Keycloak 创建了一个 Springboot 应用程序 Baeldung 当我尝试输入 /api/foos 时,它总是 returns 403 而没有任何错误消息。
// SecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
class SecurityConfig(
private val unauthorizedHandler: JwtAuthenticationEntryPoint
) : WebSecurityConfigurerAdapter() {
@Throws(Exception::class)
override fun configure(http: HttpSecurity) {
http
.cors()
.and()
.csrf()
.disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/user/info", "/api/foos/**", "/api/foos")
.hasAnyRole("free_user")
.antMatchers(HttpMethod.POST, "/api/foos")
.hasAnyRole("free_user")
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
}
}
// Controller
@RestController
@RequestMapping(value = ["/api/foos"])
class SecurityTestController() {
@GetMapping(value = ["/{id}"])
fun findOne(@PathVariable id: Long?): String {
return "fineOne with id $id"
}
@GetMapping
fun findAll(): Message {
return Message("findAll")
}
}
// application.properties
# Resource server config
rest.security.issuer-uri=http://localhost:8081/auth/realms/dev
spring.security.oauth2.resourceserver.jwt.issuer-uri=${rest.security.issuer-uri}
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=${rest.security.issuer-uri}/protocol/openid-connect/certs
// build.gradle (app)
plugins {
id("org.springframework.boot")
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter- oauth2-resource-server")
implementation("org.springframework.boot:spring-boot-starter-security")
testImplementation("org.springframework.security:spring-security-test")
}
这是我在 Keycloak 上的用户
邮递员结果:
我已经尝试过的
- 禁用 csrf - 不工作
- 评论 SecurityConfig class - 在没有安全的情况下工作
看起来“free_user”是客户端角色。
两种解决方案:
要么删除当前的“free_user”客户端角色,在全局角色选项卡中创建一个“free_user”领域角色,然后将其分配给您的用户。
或者,将 属性 keycloak.use-resource-role-mappings=true
添加到您的 Spring 引导配置,以允许 spring 安全映射您当前的客户端角色。
我在这里找到了答案LINK
我们需要在 Spring 安全和 Keycloak 角色之间创建自定义映射。
public class KeycloakRealmRoleConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
@Override
public Collection<GrantedAuthority> convert(Jwt jwt) {
final Map<String, Object> realmAccess = (Map<String, Object>) jwt.getClaims().get("realm_access");
return ((List<String>)realmAccess.get("roles")).stream()
.map(roleName -> "ROLE_" + roleName) // prefix to map to a Spring Security "role"
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
}