我尝试了Spring Cloud Gateway / KeyCloak
我尝试了以下文章的内容。
尝试的事项
我只跳过了第七步并实现了其他部分,使用的是Kotlin语言。
Keycloak的配置
使用Docker启动Keycloak。
只需要一种选项来将以下命令的意思用中文表达出来:自动下载Docker镜像。
docker run -d --name keycloak -p 8888:8080 \
-e KEYCLOAK_USER=spring \
-e KEYCLOAK_PASSWORD=spring123 \
jboss/keycloak
创建客户
获取客户端秘钥
创建没有测试范围的Keycloak也是一样的。
下载Spring Boot
build.gradle.kts的配置
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "2.5.2"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.20"
kotlin("plugin.spring") version "1.5.20"
}
group = "phoneappli.people"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:2020.0.3")
}
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.springframework.cloud:spring-cloud-starter-gateway")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.security:spring-security-test")
implementation("org.springframework.security:spring-security-oauth2-resource-server")
implementation("org.springframework.security:spring-security-oauth2-jose")
implementation("org.springframework.security:spring-security-oauth2-client")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "1.8"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
应用程序的yml配置
server.port: 8090
spring:
security:
oauth2:
client:
provider:
keycloak:
token-uri: http://127.0.0.1:8888/auth/realms/master/protocol/openid-connect/token
authorization-uri: http://127.0.0.1:8888/auth/realms/master/protocol/openid-connect/auth
userinfo-uri: http://127.0.0.1:8888/auth/realms/master/protocol/openid-connect/userinfo
user-name-attribute: preferred_username
registration:
keycloak-with-test-scope:
provider: keycloak
client-id: spring-with-test-scope
client-secret: f7fab54d-b766-4fc3-b3a2-fbcaf826e816
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
application:
name: callme
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://127.0.0.1:8888/auth/realms/master
cloud:
gateway:
default-filters: TokenRelay
routes:
- id: callme-service
uri: http://127.0.0.1:5000 #callmeサービスのURL
predicates:
- Path=/callme/**
filters:
- RemoveRequestHeader=Cookie #callmeサービスへ転送する時にCookieを削除
main:
web-application-type: reactive
allow-bean-definition-overriding: true
logging:
level:
org.springframework.security: DEBUG
Spring Security的配置
import org.springframework.context.annotation.Configuration
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfig: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.authorizeHttpRequests {
authorize -> authorize.anyRequest().authenticated()
}.oauth2ResourceServer().jwt()
}
}
确认动作
使用Python Flask实现了一个只返回字符串的Callme服务。
在转发给callme服务的请求中,cookie已被删除,并且以下内容已附加到header中。
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJaSlZqWmlHUzgybmVETVlpVUZaRW1QQjBJM0ItOXJSTmhzQWJMWnhnbmtjIn0.eyJleHAiOjE2MjU3MjQ4NDgsImlhdCI6MTYyNTcyNDc4OCwiYXV0aF90aW1lIjoxNjI1NzIzODUxLCJqdGkiOiI5MTU3YWE4Zi0xZGQ1LTQxYTMtYmJkYi0wMTIxNTgwNmZlM2YiLCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjg4ODgvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbIm1hc3Rlci1yZWFsbSIsImFjY291bnQiXSwic3ViIjoiY2M1MWIxNTQtMGQ2Mi00YjRhLWI5YWYtMWZkN2FjMmFmNDdhIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoic3ByaW5nLXdpdGgtdGVzdC1zY29wZSIsInNlc3Npb25fc3RhdGUiOiJjMGQxMWNmMi0wODllLTQzZWItYmYzMi1kNDVkYzM1N2EzNzQiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImNyZWF0ZS1yZWFsbSIsImRlZmF1bHQtcm9sZXMtbWFzdGVyIiwiU0NPUEVfVEVTVCIsIm9mZmxpbmVfYWNjZXNzIiwiYWRtaW4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7Im1hc3Rlci1yZWFsbSI6eyJyb2xlcyI6WyJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsInZpZXctcmVhbG0iLCJtYW5hZ2UtaWRlbnRpdHktcHJvdmlkZXJzIiwiaW1wZXJzb25hdGlvbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJlbWFpbCBURVNUIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInByZWZlcnJlZF91c2VybmFtZSI6InNwcmluZyJ9.CRKt9rGPsv-et1bWlLcVdgj46PSGRKSMmZmxzBusHxORjJK2OeyzSYRqFNlGWW_hZDtTp3zB4DU3VYnFSDo_zxAaBJnjA4efr3SnKhUKjdSa6Oiv95PVkU_xzStKKOeqC7VUB8WZpXWgh4GfcC7VFMnUhWJyjCUsE3kfUZA3z7WxuAhrU_9nz3elDIgtQt6Rj9CePk_a4HDfMrjhWLqYi1qjlnyWsMatHav44Iz0ygTpOQyd4k0awd-f7FEp916zfAxLOKFIo7tqsS8DEf46II_GBThTkTtmCNlOJoBHHTqL9VHaN1kWHUbm6BxTfoaqooLaIxTc7BIbkJPVp8Hhag
这是一个JWT,解析后包含有角色等信息。