我有一个非常简单的 Spring Boot 应用程序,其资源位于 /repositories
和 /persons
.
这是我的 build.gradle
文件。
plugins {
id 'org.springframework.boot' version '2.4.0'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
// use java 11 until keycloak is fixed
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom "org.keycloak.bom:keycloak-adapter-bom:12.0.1"
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.keycloak:keycloak-spring-boot-starter'
implementation 'org.flywaydb:flyway-core'
runtime 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
...
...
这是我的 SecurityConfig.java
文件。@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
var keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/persons*")
.hasRole("user")
.anyRequest()
.permitAll();
}
@Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
这是我的 application.yaml
文件。spring:
datasource:
url: jdbc:postgresql://localhost:5432/postgres
username: john
password: john
keycloak:
auth-server-url: http://localhost:8081/auth/
realm: myrealm
resource: myclient
credentials:
secret: 45d43bd6-5ab9-476c-83c8-67bd203a78ee
这一切都在我的本地机器上,Keycloak 和 Postgres 是通过 docker compose 启动的。
version: "3.1"
volumes:
postgres_data:
driver: local
services:
db:
image: "postgres:13.1"
ports:
- "5432:5432"
environment:
POSTGRES_DB: postgres
POSTGRES_USER: john
POSTGRES_PASSWORD: john
postgres:
image: "postgres:13.1"
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
keycloak:
image: quay.io/keycloak/keycloak:12.0.1
environment:
DB_VENDOR: POSTGRES
DB_ADDR: postgres
DB_DATABASE: keycloak
DB_USER: keycloak
DB_SCHEMA: public
DB_PASSWORD: password
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: Pa55w0rd
ports:
- 8081:8080
depends_on:
- postgres
我有用户 zemirco
和 one
在 Keycloak 中,他们都有 user
角色。一切都很好,路线 /persons
受到保护,而 /repositories
对所有人开放。这是我的问题!我想保护个人资源,例如
/person/1
.我无法让它工作:(我已经尝试了好几天了,但没有运气。这是我的 key 斗篷设置。这是我的政策。
这里是资源。
这是许可。
在 Keycloak 的评估过程中,这一切都有效。但是它不能直接在我的 Spring Boot 应用程序中工作。我仍然可以访问
/person/1
如 zemirco
虽然用户 one
应该只有访问权限。我现在有点失落。你有什么想法?
非常感谢!
编辑 2021 年 1 月 10 日
感谢大家的回答,但我仍然认为它是可行的,而无需在我这边(应用程序方面)付出很多额外的努力。我特别关注政策执行者 https://www.keycloak.org/docs/latest/authorization_services/#_enforcer_overview .
A PEP is responsible for enforcing access decisions from the Keycloak server where these decisions are taken by evaluating the policies associated with a protected resource. It acts as a filter or interceptor in your application in order to check whether or not a particular request to a protected resource can be fulfilled based on the permissions granted by these decisions.
这听起来与我正在尝试做的完全一样。不幸的是我不能让它工作。我只是认为我的配置是错误的或者可能不完整。我会为这个问题增加悬赏。
最佳答案
它终于起作用了:) 我很高兴!
这是我所做的。
首先我使用了keycloak.json
来自我的 Keycloak 客户端安装的文件。一开始我尝试将所有配置放入我的 application.yaml
. keycloak.json
文件必须位于 src/main/webapp/WEB-INF/keycloak.json
.当您使用 JSON 文件而不是 YAML 文件时,您可以从 SecurityConfig
中删除以下内容.
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
它实际上很不错。您可以简单地将 Keycloak 中的内容复制并粘贴到文件中,您就可以确保一切正常。我看到的另一个问题是 keycloak.json
中的配置被称为 policy-enforcer
与 policy-enforcer-config
相比在 application.yaml
.这很烦人,因为我一开始没有意识到这一点。这是配置。{
"realm": "myrealm",
"auth-server-url": "http://localhost:8081/auth/",
"ssl-required": "external",
"resource": "myclient",
"verify-token-audience": true,
"credentials": {
"secret": "45d43bd6-5ab9-476c-83c8-67bd203a78ee"
},
"confidential-port": 0,
"policy-enforcer": {}
}
"policy-enforcer": {}
是最重要的部分。这里我们启用默认设置,并简单地说 Keycloak 应该授权对我们资源的所有请求。然后一切似乎都奏效了。我只能通过正确的用户访问 protected 资源。但是,在我注销并再次尝试访问该资源后,我仍然能够做到。在这里我了解到我的 Ant 匹配器是错误的。这是正确的配置。
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/persons/**") // changed from .antMatchers("/persons*")
.hasRole("user")
.anyRequest()
.permitAll()
.and()
// this is just to have a convenient GET /logout method. DO NOT USE IN PRODUCTION
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
现在一切正常,我来自 Keycloak 的资源/策略/权限会自动应用到我的 Spring Boot 应用程序中。
关于java - 通过 Keycloak 保护 Spring Boot 中的单个资源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65628832/