Spring Cloud Zuul 網關使用與 OAuth2.0 認證受權服務

image

API 網關的出現的緣由是微服務架構的出現,不一樣的微服務通常會有不一樣的服務地址,而外部客戶端可能須要調用多個服務的接口才能完成一個業務需求,若是讓客戶端直接與各個微服務通訊,會有如下的問題:html

  • 客戶端會屢次請求不一樣的微服務,增長了客戶端的複雜性。
  • 存在跨域請求,在必定場景下處理相對複雜。
  • 認證複雜,每一個服務都須要獨立認證。
  • 難以重構,隨着項目的迭代,可能須要從新劃分微服務。例如,可能將多個服務合併成一個或者將一個服務拆分紅多個。若是客戶端直接與微服務通訊,那麼重構將會很難實施。
  • 某些微服務可能使用了防火牆 / 瀏覽器不友好的協議,直接訪問會有必定的困難。

網關是介於客戶端和服務器端之間的中間層,全部的外部請求都會先通過 API 網關這一層。也就是說,API 的實現方面更多的考慮業務邏輯,而安全、性能、監控能夠交由 API 網關來作 ,因此網關的性能,高可用,安全性都是相當重要的。git

備註Spring Cloud 微服務中搭建 OAuth2.0 認證受權服務github

經常使用網關有哪些 ?spring

Nginx、Kong、ZUUL、Spring Cloud Gateway(Spring Cloud 官方)、Linkerd 等api

Spring Cloud Zuul

Zuul 是 Netflix 開源的微服務網關組件,它能夠和 Eureka、Ribbon、Hystrix 等組件配合使用。Zuul 的核心是一系列的過濾器 (好比:動態路由)。Spring Cloud Zuul 對 Zuul 進行了整合 ,從而更方便的與 Spring Cloud 一塊兒使用。跨域

Zuul1瀏覽器

Zuul1 是基於 Servlet 框架構建,採用的是阻塞和多線程方式,即一個線程處理一次鏈接請求,這種方式在內部延遲嚴重、設備故障較多狀況下會引發存活的鏈接增多和線程增長的狀況發生。緩存

image

Zuul2安全

Zuul2 與 Zuul1 最大的區別是它運行在異步和無阻塞框架上,每一個 CPU 核一個線程,處理全部的請求和響應,請求和響應的生命週期是經過事件和回調來處理的,這種方式減小了線程數量,所以開銷較小。又因爲數據被存儲在同一個 CPU 裏,能夠複用 CPU 級別的緩存,前面說起的延遲和重試風暴問題也經過隊列存儲鏈接數和事件數方式減輕了不少(較線程切換來講輕量級不少,天然消耗較小)。這一變化必定會大大提高性能。服務器

 

 

image

 

注:zuul 2.0 版本 Spring Cloud 官方現階段不打算集成,官方仍是推薦使用 Spring Cloud Gateway

性能

能夠參考:糾錯帖:Zuul & Spring Cloud Gateway & Linkerd性能對比 ,簡單來講,Zuul 1.x 是一個基於阻塞 IO 的 API Gateway,另外 Spring Cloud Gateway 性能很好。

高可用

通常生產環境須要將多個 Zuul 節點註冊到 Eureka Server 上,就能夠實現 Zuul 的高可用。事實上,這種狀況下的高可用和其餘服務作高可用(例如:Eurka Server 集羣)的方案沒有什麼區別。當 Zuul 客戶端註冊到 Eureka Server 上時,Zuul 客戶端會自動從 Eureka Server 查詢 Zuul Server 列表,而後使用負載均衡組件(例如: Ribbon)請求 Zuul 集羣。另外的方式也可使用 Nginx 或者硬件 F5 的來實現。

安全性

Spring Cloud 的微服務化後,通常可使用 Spring Cloud Security 結合 OAuth2.0,生成的 Token 採用 JWT 來驗證票據,但 Spring Cloud Security 暫時還不支持 OpenID Connect 協議。Zuul 將本身註冊爲 Eureka 服務治理下,同時也從 Eureka 服務治理中得到全部其餘微服務的實例信息。經過搭建獨立的 OAuth2 認證受權服務,將微服務單獨剝離出來,這些認證與微服務本身的業務並無太大的關係,因此這些功能徹底能夠獨立成一個單獨的服務存在。獨立出來以後,並非給每一個微服務調用(業務服務通常在內網),而是經過 API網關進行統一調用,來對微服務接口作前置過濾,實現對分佈式系統中的其餘的微服務接口的攔截和安全校驗。

建立 Zuul 網關服務

Maven

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
@SpringBootApplication
//@EnableOAuth2Sso
@EnableZuulProxy
public class MicrosrvZuulGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(MicrosrvZuulGatewayApplication.class, args);
    }
}

application.yml

spring:
  application:
    name: microsrv-zuul-gateway

server:
  port: 5555

eureka:
  instance:
    preferIpAddress: true
  client:
    serviceUrl:
      defaultZone: http://10.255.131.162:8000/eureka/,http://10.255.131.163:8000/eureka/,http://10.255.131.164:8000/eureka/

zuul:
  host:
    connect-timeout-millis: 20000
    socket-timeout-millis: 20000
  ignoredServices: '*'
  prefix: /api # 設置一個公共的前綴
  routes:
    auth-service:
      path: /auth/**
      sensitiveHeaders:
      serviceId:  idsrv-server
    order-service:
      path: /order/**
      sensitiveHeaders:
      serviceId:  order-service
  add-proxy-headers: true

 

由於使用 Eureka 來服務發現,因此請求URL格式形如 /service-id/** 會被自動轉發到在 Eureka Server 上註冊的 service id 爲「service-id」的微服務應用上。例如上面咱們定義了兩個路由規則,好比將「order-service」的請求轉發到相應 service-id 註冊的服務上,也能夠經過修改 zuul.prefix=/api 配置來配置全局的前綴地址。默認 Eureka Server會暴露全部註冊在它上面的微服務。你可使用 zuul.ignored-services 屬性來禁止這種行爲,且只有顯式配置的服務纔會被暴露。

Zuul  整合 OAuth2.0 認證受權

Zuul 整合 OAuth2.0 有兩種思路,一種是受權服務器採用 JwtToken 統一在網關層使用公鑰驗證票據,判斷權限等操做;另外一種是讓資源端處理,網關只作路由轉發。

資源端配置

maven

<!-- oauth2 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.0.5.RELEASE</version>
        </dependency>

Spring Boot

@SpringBootApplication
@EnableResourceServer
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@RestController
public class AccountController {

    @GetMapping("/principal")
    @PreAuthorize("hasAnyAuthority('user')")
    public Principal user(Principal principal) {
        return principal;
    }

    @GetMapping("/query")
    @PreAuthorize("hasAnyAuthority('all')")
    public String all () {
        return "具備 all 權限";
    }
}

application.yml

logging:
  level:
    org.springframework: DEBUG

server:
  port: 5000

security:
  oauth2:
    resource:
#      prefer-token-info: true
#      user-info-uri: http://localhost:8080/api/v1/users/principal
#      token-info-uri: http://localhost:8080/oauth/check_token
      jwt:
       # key-uri: http://localhost:8080/oauth/token_key
        key-value: |
          -----BEGIN PUBLIC KEY-----
          MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm4irSNcR7CSSfXconxL4
          g4M4j34wTWdTv93ocMn4VmdB7rCBU/BlxXtBUf/cgLIgQhQrAPszSZSmxiEXCOkG
          Pr4aQBQuPgmNIR95Dhbzw/ZN0BnecAt3ZfkkDBHv8kH3kR/jYGTdwrxKeDgXGljN
          sTRhbjuASxPG/Z6gU1yRPCsgc2r8NYnztWGcDWqaobqjG3/yzFmusoAboyV7asIp
          o4yk378LmonDNwxnOOTb2Peg5PeelwfOwJPbftK1VOOt18zA0cchw6dHUzq9NlB8
          clps/VdBap9BxU3/0YoFXRIc18nyzrWo2BcY2KQqX//AJC3OAfrfDmo+BGK8E0mp
          8wIDAQAB
          -----END PUBLIC KEY-----

最後能夠在 Zuul 上啓用  @EnableOAuth2Sso 註解做爲 OAuth2.0 的一個客戶端(非必須),這樣當用戶訪問到網關沒有受權的話,會跳轉到受權服務器登陸受權。

security:
  oauth2:
    client:
      access-token-uri:http://localhost:8080/oauth/token
      user-authorization-uri: http://localhost:8080/oauth/authorize
      client-id: client_test
      client-secret: secret_test
    resource:
      user-info-uri: http://localhost:8080/api/v1/users/principal
      prefer-token-info: false

REFER:

https://docs.spring.io/spring-security-oauth2-boot/docs/current-SNAPSHOT/reference/htmlsingle/

相關文章
相關標籤/搜索