Keycloak + Spring Cloud Gateway + Angular 9。

问题描述 投票:0回答:1

我试着用Keycloak作为IdP来保障我的Spring云网关的安全,但是当我通过网关发送请求时,响应总是将我重定向到登录页面。

Keycloak领域有三个客户端。

  • teams-portal (前端[公开])
  • 网关(后台[机密])
  • 培训服务(后端[仅有])

用Angular通过浏览器生成的请求就是这个。

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

使用Keycloaks登录页面生成token,clientId=teams-portal,之后输出的token作为Bearer Token注入下一个发送到网关的请求中。

网关属性

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'
  }

为什么令牌无效,并将我重定向到 oauth2authorizationkeycloak?我应该如何改变配置,以使其正常工作?

EDIT 1我有更新网关与此CORS配置。

@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 spring-security spring-cloud keycloak
1个回答
0
投票

我想你把事情搞混了。以你目前的配置,你需要在网关后面服务或访问Angular应用.你需要在你的网关中添加另一条路由,它将请求转发到你的Angular应用并通过网关访问Angular应用。在你的情况下,它是 http:/localhost:8762angularapp。. 你将被重定向到你的IdP登录,并重定向回你的Angular应用,你将能够访问你的api。你还需要删除你的Angular应用中隐含的OIDC认证流,因为你已经通过了认证,所以你不再需要它。当你访问你的API时,你的网关和IdP之间会有一个令牌交换,你会得到一个JWT响应,你可以在你的API中使用。

注意:您的密钥衣客户端(网关)应该设置为 保密.

如果你不想在网关后为你的Angular应用服务,你需要在网关中删除oauth2客户端,只需将请求和你的访问令牌一起转发到你的api中,让spring处理jwt授权。教程

© www.soinside.com 2019 - 2024. All rights reserved.