我曾尝试使用Keyclove作为IdP保护我的Spring云网关,但当我通过网关发送请求时,响应总是将我重定向到登录页面。
Keyclope领域有三个客户端:
Angular via browser生成的请求如下:
OPTIONS /trainings/exercises HTTP/1.1
Host: localhost:8762
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Origin: http://localhost:4201
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Sec-Fetch-Dest: empty
Referer: http://localhost:4201/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37
Accept-Encoding: gzip, deflate, br
Accept-Language: es,es-ES;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:4201
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Credentials: true
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1 ; mode=block
Referrer-Policy: no-referrer
content-length: 0
GET /trainings/exercises HTTP/1.1
Host: localhost:8762
Connection: keep-alive
Accept: application/json, text/plain, */*
Authorization: bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ4bGpIN2tlaGJWeWZNcVBPWUgyZTZJbmRQQjZfQm15amtzOEk5dnJtWU8wIn0.eyJleHAiOjE1OTAzNDI1MzMsImlhdCI6MTU5MDM0MjIzMywiYXV0aF90aW1lIjoxNTkwMzQyMTc0LCJqdGkiOiJlZmVhZDI1ZS1jNTI3LTQxMzEtODQyMy1kMWExNGM4NmZiYTgiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODIvYXV0aC9yZWFsbXMvYmFza2VpdG9yIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImVkMDRhYWU4LWQ5MTEtNGQ5MC1iMDIyLWU3ZDRkZWExNTRiYyIsInR5cCI6IkJlYXJlciIsImF6cCI6InRlYW1zLXBvcnRhbCIsIm5vbmNlIjoiZjYwOTE0MjUtYzYzMy00MWI3LTkwNGUtZGQ1YWY0MDY2Y2RhIiwic2Vzc2lvbl9zdGF0ZSI6IjJkZTQwNzg3LTZkZGItNGI1ZC05OTVhLTc5MTU0ZGQwMWNmOSIsImFjciI6IjAiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo0MjAxIiwiaHR0cDovL2xvY2FsaG9zdDo0MjAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiY29hY2giXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsIm5hbWUiOiJ0ZXN0MSB0ZXN0MSIsInByZWZlcnJlZF91c2VybmFtZSI6InRlc3QxIiwiZ2l2ZW5fbmFtZSI6InRlc3QxIiwiZmFtaWx5X25hbWUiOiJ0ZXN0MSIsImVtYWlsIjoidGVzdDFAaW52ZW50LmNvbSJ9.jll1KSMZiubWrewXZ_DgtmxeRsHZ38VtDMAXfzMqo87M0C9OQ9ieG6VgveE5M2zJJDuUYv2ixiiOEgZeQ2MOYcZ93YX38viT8KahqE1RggSS2Iiq_O2xLx_BA-GvYtM4D5dkQvfXJ5NQ6id53QRPPKA7T_4lyAafxlmMrtslXOeC6_iGnbWlRxYAeGURoAkAoy8fZhHDbz8MRJ3ayyNpWbgkymQE8ZRw-d8N41n0eapId3UYlEUGRxPtHcbDGZIdPoVgewrIJSFr-Q7oLSlqaTvqbSjFn_zxiVIYjV-c7SVBxeOV5aMebKzCzmiRGYBm-4sFZpa6YJrlbRLnGIFquQ
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37
Origin: http://localhost:4201
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:4201/
Accept-Encoding: gzip, deflate, br
Accept-Language: es,es-ES;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
HTTP/1.1 302 Found
Location: /oauth2/authorization/keycloak
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1 ; mode=block
Referrer-Policy: no-referrer
content-length: 0
该令牌是使用clientId=Team portal的KeyCloves登录页面生成的,之后在发送到网关的下一个请求中,将输出令牌作为承载令牌注入。
网关属性
spring:
application:
name: gateway-service
cloud:
gateway:
routes:
- id: training-service
uri: http://localhost:8200
predicates:
- Path=/trainings/**
filters:
- StripPrefix=1
- TokenRelay=
- RemoveRequestHeader=Cookie
security:
oauth2:
client:
provider:
keycloak:
issuer-uri: http://localhost:8082/auth/realms/baskeitor
user-name-attribute: preferred_username
registration:
keycloak:
client-id: gateway
client-secret: 87444049-832b-41d0-995f-1ae84db61684
培训服务属性
spring.application.name=training-service
keycloak.auth-server-url=http://localhost:8082/auth/
keycloak.realm=baskeitor
keycloak.resource=training-service
keycloak.public-client=true
keycloak.bearer-only=true
keycloak.principal-attribute=preferred_username
角环境
keycloakConfig: {
url: 'http://localhost:8082/auth',
realm: 'baskeitor',
clientId: 'teams-portal'
}
?为什么令牌无效,并且它正在将我重定向到/oauth2/authorization/keydrope??我应该如何更改配置才能正常工作?
编辑1我已使用此CORS配置更新网关:
kotlin prettyprint-override">@EnableWebFlux
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
class CorsConfig : WebFluxConfigurer {
override fun addCorsMappings(corsRegistry: CorsRegistry) {
corsRegistry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.maxAge(3600)
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
fun corsFilter(): CorsWebFilter {
val config = CorsConfiguration()
config.allowCredentials = true
config.addAllowedOrigin("*")
config.addAllowedHeader("*")
config.addAllowedMethod("*")
val source = UrlBasedCorsConfigurationSource()
source.registerCorsConfiguration("/**", config)
return CorsWebFilter(source)
}
}
但浏览器显示此错误:
Access to XMLHttpRequest at 'http://localhost:8082/auth/realms/baskeitor/protocol/openid-connect/auth?response_type=code&client_id=gateway&scope=openid%20address%20email%20microprofile-jwt%20offline_access%20phone%20profile%20roles%20web-origins&state=wDesvgfbtxm29q1MfeFoBYtxyXf-12Nnm47kXR7uzjU%3D&redirect_uri=http://localhost:8762/login/oauth2/code/keycloak&nonce=GvepIeC1HXq-xdq6ZBP333zrumwhXTB_KVei74gdndY' (redirected from 'http://localhost:8762/trainings/exercises') from origin 'http://localhost:4201' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
使用此配置,请求仍会重定向到登录页面:
OPTIONS /trainings/exercises HTTP/1.1
Host: localhost:8762
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Origin: http://localhost:4201
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Sec-Fetch-Dest: empty
Referer: http://localhost:4201/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37
Accept-Encoding: gzip, deflate, br
Accept-Language: es,es-ES;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:4201
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Credentials: true
content-length: 0
GET /trainings/exercises HTTP/1.1
Host: localhost:8762
Connection: keep-alive
Accept: application/json, text/plain, */*
Authorization: bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ4bGpIN2tlaGJWeWZNcVBPWUgyZTZJbmRQQjZfQm15amtzOEk5dnJtWU8wIn0.eyJleHAiOjE1OTA0MjMxNDYsImlhdCI6MTU5MDQyMjg0NiwiYXV0aF90aW1lIjoxNTkwNDIwNTMzLCJqdGkiOiIwMjk0NDA0MC00NTJjLTRkNWUtOGQxYS1kOWYwZTMxNDAyMzQiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODIvYXV0aC9yZWFsbXMvYmFza2VpdG9yIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImVkMDRhYWU4LWQ5MTEtNGQ5MC1iMDIyLWU3ZDRkZWExNTRiYyIsInR5cCI6IkJlYXJlciIsImF6cCI6InRlYW1zLXBvcnRhbCIsIm5vbmNlIjoiYTI4NjJkYTgtY2NiOS00ZDQzLTkxOGEtMGExMmIzYjQ2ZDY0Iiwic2Vzc2lvbl9zdGF0ZSI6IjczMTAxMzNjLTc3MGMtNDdiZS1iZmU5LWZjZDZkODRlZDVlYiIsImFjciI6IjAiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo0MjAxIiwiaHR0cDovL2xvY2FsaG9zdDo0MjAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiY29hY2giXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsIm5hbWUiOiJ0ZXN0MSB0ZXN0MSIsInByZWZlcnJlZF91c2VybmFtZSI6InRlc3QxIiwiZ2l2ZW5fbmFtZSI6InRlc3QxIiwiZmFtaWx5X25hbWUiOiJ0ZXN0MSIsImVtYWlsIjoidGVzdDFAaW52ZW50LmNvbSJ9.LwTs7-FM0Dh2ATx1KwRz5lGfAJjhluvHoTAuiUPd4WXjd1YNgfSQ5R0B_aY05MSLQupiVQNBwrEDmoJT2qup8jyoIUBn4aHRmtS1b3b0ppni60vprHTuEZKpBERfsoGE7mnfyxFv-xL_yUVNOrx4TzM3rnFTIPVchXAQuNkVrnp9UudrdWw4Qar1XhMPZ1J8Df8uPqDr5yBdHXu8u1IPptD3PnfcTfhesx1ugn09JmSFWtQzat7ucmdYjN1buhW8_NCK_kGSblM-k0GheAVO2Fjc6nvigsogW1gmmTRZNB1xX1DSZPNjQ4lNzNAR-JEtP0XEMvGHhuQDJbZ3yvFT6A
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37
Origin: http://localhost:4201
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:4201/
Accept-Encoding: gzip, deflate, br
Accept-Language: es,es-ES;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
HTTP/1.1 302 Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:4201
Access-Control-Allow-Credentials: true
Location: /oauth2/authorization/keycloak
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1 ; mode=block
Referrer-Policy: no-referrer
content-length: 0
OPTIONS /oauth2/authorization/keycloak HTTP/1.1
Host: localhost:8762
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Origin: http://localhost:4201
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Sec-Fetch-Dest: empty
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37
Accept-Encoding: gzip, deflate, br
Accept-Language: es,es-ES;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:4201
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Credentials: true
content-length: 0
GET /oauth2/authorization/keycloak HTTP/1.1
Host: localhost:8762
Connection: keep-alive
Accept: application/json, text/plain, */*
Authorization: bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ4bGpIN2tlaGJWeWZNcVBPWUgyZTZJbmRQQjZfQm15amtzOEk5dnJtWU8wIn0.eyJleHAiOjE1OTA0MjMxNDYsImlhdCI6MTU5MDQyMjg0NiwiYXV0aF90aW1lIjoxNTkwNDIwNTMzLCJqdGkiOiIwMjk0NDA0MC00NTJjLTRkNWUtOGQxYS1kOWYwZTMxNDAyMzQiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODIvYXV0aC9yZWFsbXMvYmFza2VpdG9yIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImVkMDRhYWU4LWQ5MTEtNGQ5MC1iMDIyLWU3ZDRkZWExNTRiYyIsInR5cCI6IkJlYXJlciIsImF6cCI6InRlYW1zLXBvcnRhbCIsIm5vbmNlIjoiYTI4NjJkYTgtY2NiOS00ZDQzLTkxOGEtMGExMmIzYjQ2ZDY0Iiwic2Vzc2lvbl9zdGF0ZSI6IjczMTAxMzNjLTc3MGMtNDdiZS1iZmU5LWZjZDZkODRlZDVlYiIsImFjciI6IjAiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo0MjAxIiwiaHR0cDovL2xvY2FsaG9zdDo0MjAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiY29hY2giXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsIm5hbWUiOiJ0ZXN0MSB0ZXN0MSIsInByZWZlcnJlZF91c2VybmFtZSI6InRlc3QxIiwiZ2l2ZW5fbmFtZSI6InRlc3QxIiwiZmFtaWx5X25hbWUiOiJ0ZXN0MSIsImVtYWlsIjoidGVzdDFAaW52ZW50LmNvbSJ9.LwTs7-FM0Dh2ATx1KwRz5lGfAJjhluvHoTAuiUPd4WXjd1YNgfSQ5R0B_aY05MSLQupiVQNBwrEDmoJT2qup8jyoIUBn4aHRmtS1b3b0ppni60vprHTuEZKpBERfsoGE7mnfyxFv-xL_yUVNOrx4TzM3rnFTIPVchXAQuNkVrnp9UudrdWw4Qar1XhMPZ1J8Df8uPqDr5yBdHXu8u1IPptD3PnfcTfhesx1ugn09JmSFWtQzat7ucmdYjN1buhW8_NCK_kGSblM-k0GheAVO2Fjc6nvigsogW1gmmTRZNB1xX1DSZPNjQ4lNzNAR-JEtP0XEMvGHhuQDJbZ3yvFT6A
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37
Origin: http://localhost:4201
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Accept-Encoding: gzip, deflate, br
Accept-Language: es,es-ES;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
HTTP/1.1 302 Found
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: http://localhost:4201
Access-Control-Allow-Credentials: true
Location: http://localhost:8082/auth/realms/baskeitor/protocol/openid-connect/auth?response_type=code&client_id=gateway&scope=openid%20address%20email%20microprofile-jwt%20offline_access%20phone%20profile%20roles%20web-origins&state=wDesvgfbtxm29q1MfeFoBYtxyXf-12Nnm47kXR7uzjU%3D&redirect_uri=http://localhost:8762/login/oauth2/code/keycloak&nonce=GvepIeC1HXq-xdq6ZBP333zrumwhXTB_KVei74gdndY
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1 ; mode=block
Referrer-Policy: no-referrer
Set-Cookie: SESSION=d6617ced-7cda-414e-8f7b-2c1f2adb5694; Path=/; HttpOnly; SameSite=Lax
content-length: 0
我认为你把事情搞混了。使用当前配置,您需要服务或访问网关后面的Angular应用程序。您需要在网关中html" target="_blank">添加另一条路由,将请求转发到Angular应用程序,并通过网关访问Angular应用程序。在你的情况下http://localhost:8762/angularapp.您将被重定向到IdP以登录,并重定向回Angular应用程序,您将能够访问api。您还需要删除angular应用程序中的OIDC身份验证流/隐式,因为您已经通过身份验证,因此不再需要它。当您访问API时,网关和IdP之间将有一个令牌交换,您将得到一个JWT响应,您可以在API中使用它。
注意:您的KeyClope客户端(网关)应设置为机密。
如果你不想在网关后面为你的angular应用程序提供服务。您需要删除网关中的oauth2客户端,将请求连同访问令牌一起转发到api中,并让spring处理jwt进行授权。这里有一个教程