输入数据:
- 尤里卡(localhost: 8761) 使用keycloak (localhost:8765)启动云网关服务
- 开发者资源服务(localhost:8082)
- kecloak (localhost: 8080)
Keycloak:
- 创建领域 创建客户端
- 创建了2个不同角色的用户:developer和manager
- 为路径
/developer/**
创建了1个资源(这是我的开发人员服务端点的前缀) - 为role=developer创建基于角色的策略(required!)
- 根据上面的策略创建资源权限
:在浏览器中发出请求
http://localhost:8765/developer/developers
以manager
登录!!
:拒绝访问
实际:200 with response =开发者列表
问题:我错过什么了吗?这个角色是否已经在隐形衣里面过滤了?已经看过一些视频和帖子,其中一些是基于前端keycloak-js
库和过滤,后端@RolesAllowed
。我只是好奇,如果有可能阻止请求只是使用keycloak管理控制台?
网关yaml:
server:
port: 8765
logging:
level:
root: info
eureka:
client:
serviceUrl:
defaultZone: http://eurekauser:eureka!@localhost:8761/eureka
instance:
hostname: localhost
prefer-ip-address: false
spring:
application:
name: GATEWAY
cloud:
gateway:
discovery.locator.enabled: true
routes:
- id: developer
uri: lb://DEVELOPER
predicates:
- Path=/developer/**
filters:
TokenRelay=
security:
oauth2:
client:
registration:
keycloak:
provider: keycloak
client-id: test_client
client-secret: lBIz3la07j3a5uEEFdQgoapFa4s1seeD
authorization-grant-type: authorization_code
redirect-uri: "http://localhost:${server.port}/login/oauth2/code/{registrationId}"
scope:
- openid
provider:
keycloak:
issuer-uri: http://localhost:8080/realms/TestRealm
authorization-uri: http://localhost:8080/realms/TestRealm/protocol/openid-connect/auth
token-uri: http://localhost:8080/realms/TestRealm/protocol/openid-connect/token
user-info-uri: http://localhost:8080/realms/TestRealm/protocol/openid-connect/userinfo
jwk-set-uri: http://localhost:8080/realms/TestRealm/protocol/openid-connect/certs
jackson:
date-format: yyyy-MM-dd HH:mm:ss
开发服务:YAML:
server:
port: 8082
error:
include-message: always
servlet:
context-path: /developer
spring:
application:
name: DEVELOPER
security:
oauth2:
resource-server:
jwt:
jwk-set-uri: http://localhost:8080/realms/TestRealm/protocol/openid-connect/certs
eureka:
client:
serviceUrl:
defaultZone: http://eurekauser:eureka!@localhost:8761/eureka
instance:
prefer-ip-address: false
hostname: localhost
端点:
@RestController
@RequestMapping("/developers")
class DevelopController {
private val developers = mapOf(
Pair(1L, "developer#1"),
Pair(2L, "developer#2"),
Pair(3L, "developer#3"),
Pair(4L, "developer#4"),
Pair(5L, "developer#5")
)
@GetMapping
fun findAll(authentication: Authentication) = developers.entries
@GetMapping("/{developerId}")
fun findById(@PathVariable developerId: Long): String = developers[developerId] ?: let {
throw RuntimeException("Not found by id=$developerId")
}
}
基于角色的访问控制不会在访问令牌发射上实现:访问令牌是为特定客户端的给定用户发射的,可用于授权对许多资源的许多请求。
Spring- Boot资源服务器中基于角色的访问控制的详细信息,在对"使用Keycloak Spring Adapter with Spring Boot 3"的接受回答中
Keycloak中有一个授权服务,您可以使用它来集中访问控制,但是:
- 作为Spring的Keycloak适配器没有移植到Spring -security 6,它需要你编写自己的客户端服务和身份验证过滤器
- 此服务在请求到达资源服务器之前不被调用,它由资源服务器调用,以委托决定是否使用给定的访问令牌为请求授予对资源的访问权限
- 与在资源服务器上评估JWT中包含的角色(在启动时只需要向Keycloak发出一次请求)相比,这是相当低效的:使用授权服务,对每个向资源服务器发出的请求都向Keycloak发出请求(就像使用自省而不是JWT解码时一样)
- 它是非常Keycloak的:没有标准围绕它和访问控制规则必须定义在Keycloak =>如果Keycloak停止支持它,或者如果你必须切换到另一个OIDC授权服务器,你就完蛋了
- 它不容易测试(您可以很容易地在资源服务器上编写带有模拟身份的Spring访问控制规则的单元测试)
- 在我看来,与
@Controller
方法 上使用SpEL的方法安全性相比,当所有规则都放在同一位置时,更难准确地找出适用于特定资源的访问控制规则。