1. 程式人生 > >Spring cloud微服務實戰(二)——Zuul整合Swagger2及許可權校驗

Spring cloud微服務實戰(二)——Zuul整合Swagger2及許可權校驗

一、前言

##二、 整合Swagger2
Swagger2大家肯定都用過,為什麼我在這裡還要提到呢,因為各個微服務都會提供自己的API文件,我們總不能一個地址一個地址去查吧,能不能有個統一的入口呢。這就是這節要講的。

2.1 Zuul整合Swagger2

其他的都不說直接上程式碼

@Component
@Primary
public class GatewaySwaggerResourcesProvider implements SwaggerResourcesProvider {
    private final RouteLocator routeLocator;

    public GatewaySwaggerResourcesProvider(RouteLocator routeLocator) {
        this.routeLocator = routeLocator;
    }

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<Route> routes = routeLocator.getRoutes();
        for (Route route:routes) {
            resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", "v2/api-docs")));
        }
        return resources;
    }
    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}

SwaggerResourcesProvider 是資源提供者,我們重寫他,把各個微服務的資源路徑返回,即:resources.add(swaggerResource(route.getId(), route.getFullPath().replace("**", “v2/api-docs”)));
參看InMemorySwaggerResourcesProvider寫法,如下,預設是當前應用的/v2/api-docs。

@Autowired
  public InMemorySwaggerResourcesProvider(
      Environment environment,
      DocumentationCache documentationCache) {
    swagger1Url = environment.getProperty("springfox.documentation.swagger.v1.path", "/api-docs");
    swagger2Url = environment.getProperty("springfox.documentation.swagger.v2.path", "/v2/api-docs");
    swagger1Available = classByName("springfox.documentation.swagger1.web.Swagger1Controller").isPresent();
    swagger2Available = classByName("springfox.documentation.swagger2.web.Swagger2Controller").isPresent();
    this.documentationCache = documentationCache;
  }

  @Override
  public List<SwaggerResource> get() {
    List<SwaggerResource> resources = new ArrayList<SwaggerResource>();

    for (Map.Entry<String, Documentation> entry : documentationCache.all().entrySet()) {
      String swaggerGroup = entry.getKey();
      if (swagger1Available) {
        SwaggerResource swaggerResource = resource(swaggerGroup, swagger1Url);
        swaggerResource.setSwaggerVersion("1.2");
        resources.add(swaggerResource);
      }

      if (swagger2Available) {
        SwaggerResource swaggerResource = resource(swaggerGroup, swagger2Url);
        swaggerResource.setSwaggerVersion("2.0");
        resources.add(swaggerResource);
      }
    }
    Collections.sort(resources);
    return resources;
  }

最後記得配置Swagger

@Configuration
@EnableSwagger2
public class Swagger2Config {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("說明文件")
                .description("介面說明文件")
                .termsOfServiceUrl("")
                .contact(new Contact("楊秀峰","
[email protected]
","[email protected]")) .version("1.0") .build(); } }

三、Zuul許可權控制

Spring cloud微服務實戰(一)的Zuul只是做為一個路由,並沒有做許可權限制,具體的許可權控制要到各個微服務自己實現,這樣一來不免要有很多重複的工作。那麼就把許可權控制放在閘道器的進行。
注意: 我這裡是基於到URL的細粒度的許可權控制
Zuul到這裡就充當了資源伺服器的角色。
配置資源伺服器:

@Configuration
@EnableResourceServer
public class SecurityConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private OAuth2WebSecurityExpressionHandler expressionHandler;

    private static final String[] AUTH_WHITELIST = {
          
    };

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/v2/api-docs","/uaa/**").permitAll();

        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
                .authorizeRequests();
        for (String au:AUTH_WHITELIST
             ) {
            http.authorizeRequests().antMatchers(au).permitAll();
        }
        http.authorizeRequests().anyRequest().authenticated();
        registry.anyRequest()
                .access("@permissionService.hasPermission(request,authentication)");
    }
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.expressionHandler(expressionHandler);
    }
    @Bean
    public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) {
        OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();
        expressionHandler.setApplicationContext(applicationContext);
        return expressionHandler;
    }
}

注意如下這段

registry.anyRequest()
                .access("@permissionService.hasPermission(request,authentication)");

我們自定義表示式決策。最終在WebExpressionVoter的vote方法的ExpressionUtils.evaluateAsBoolean會呼叫到hasPermission(request,authentication);

PermissionService的程式碼如下:

@Service("permissionService")
@Slf4j
public class PermissionServiceImpl implements PermissionService {

    /**
     * 可以做URLs匹配,規則如下
     *
     * ?匹配一個字元
     * *匹配0個或多個字元
     * **匹配0個或多個目錄
     * 用例如下
     * <p>https://www.cnblogs.com/zhangxiaoguang/p/5855113.html</p>
     */

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        String requestUrl = request.getRequestURI();
        log.info("requestUrl:{}",requestUrl);
        List<SimpleGrantedAuthority> grantedAuthorityList = (List<SimpleGrantedAuthority>) authentication.getAuthorities();
        boolean hasPermission = false;

        if (principal != null){
            if (CollectionUtils.isEmpty(grantedAuthorityList)){
                return hasPermission;
            }
            for (SimpleGrantedAuthority authority:grantedAuthorityList
                 ) {
                if (antPathMatcher.match(authority.getAuthority(),requestUrl)){
                    hasPermission = true;
                    break;
                }
            }
        }

        return hasPermission;
    }
}

我這裡只做了簡單的URL校驗,完善的應該是判斷URL、Request Method是否一致等等,大家有更多的發揮空間。
最後記得在application.yml裡配置

security:
  basic:
    enabled: false
  oauth2:
    resource:
      user-info-uri:  http://localhost:9060/user
      prefer-token-info: false

更好的做法應該直接從redis獲取使用者資訊,減少一次HTTP請求;後面再完善吧,今兒有點賴了。

結束

相關推薦

Spring cloud微服務實()——Zuul整合Swagger2許可權

一、前言 ##二、 整合Swagger2 Swagger2大家肯定都用過,為什麼我在這裡還要提到呢,因為各個微服務都會提供自己的API文件,我們總不能一個地址一個地址去查吧,能不能有個統一的入口呢。這就是這節要講的。 2.1 Zuul整合Swagger2 其他

Spring + Cloud微服務實》讀書筆記()————Spring Boot

1.Spring Boot簡介 1.1簡化配置 通過設計大量的自動化配置等方式來簡化Spring原有樣板化的配置,使得開發者可以快速構建應用。 1.2簡化依賴管理 Spring Boot 通過一系列Starter POMs的定義,讓我們整合各項功

Spring cloud微服務實——高可用註冊中心()

上一篇我們介紹服務註冊中心、服務提供者、服務消費者的建立以及呼叫。本次課程介紹的是服務中心高可用設定,以及Eureka的自我保護模式。 高可用的服務註冊中心 在服務註冊中心其實也就是一個服務,它同樣可以向其他服務中心註冊,Eureka Servere的高

PK1648-Spring Cloud微服務實視頻

集成 後端 aid 前後端分離 隨筆 使用 log eight container PK1648-Spring Cloud微服務實戰視頻 對接真實數據 從0開發前後端分離企業級上線項目 新年伊始,學習要趁早,點滴記錄,學習就是進步! 隨筆背景:在很多時候,很多入門不久的

Spring Cloud微服務實教程|Spring Cloud教程

Spring CloudSpring Cloud微服務實戰教程網盤地址:https://pan.baidu.com/s/1nN_tpaUuIhWIHTTtk1k9lg 密碼:9obv備用地址(騰訊微雲):https://share.weiyun.com/5Sc3eEK 密碼:q6cmrk 微服務架構已是當下最

Spring Cloud微服務實》讀書筆記之客戶端負載均衡:Spring Cloud Ribbon - 4

摘要 客戶端負載均衡元件部署在客戶端,由客戶端維護要訪問的服務端清單(清單來源於服務註冊中心)。在Spring Cloud 中預設使用Ribbon作為客戶端負載均衡。 關鍵詞:客戶端負載均衡,Ribbon 一、什麼是客戶端負載均衡 負載均衡是對系統高可用、緩解網路壓力、處理能力擴容的重要手段之一。通常

Spring Cloud 微服務實詳細筆記

本文是看某課網關於 SpringCloud 微服務實戰的視訊總結的筆記,其中涉及了 Eureka Server 和 Eureka Client 的配置 Eureka Server 高可用性 服務間通訊的兩種方式:RestTemplate 和 Feign RabbitMQ 的安裝和使用

Spring cloud微服務實(三)——基於OAUTH2.0統一認證授權的微服務基礎架構升級

前言 從2018年年初寫的一篇主題為 Spring cloud微服務實戰——基於OAUTH2.0統一認證授權的微服務基礎架構的文章後就很少更新了。自從小寶貝誕生和公司業務的繁忙,年初計劃每週更新一篇博文的計劃已經落空了。年底了,終於清閒了些。 升級 Spring cloud微

Spring Cloud 微服務實 第六章 宣告式服務呼叫:Spring Cloud Feign

    本章介紹的是Spring Cloud Feign ,它是基於Netfix Feign 實現 ,整合了Spring Cloud Ribbon 與 Spring Cloud Hystrix, 除了提供這兩者的強大功能之外,還提供了一種宣告式的web服務客戶端定義方式。

Spring Cloud微服務實》讀書筆記之基礎知識1

摘要 微服務是一種系統架構的設計風格,它主旨在於將一個原本獨立的系統,拆分成多個獨立執行的小型服務。不同服務之間通過Restful介面進行通訊協作。 關鍵詞:Spring Cloud,微服務 一、什麼是微服務 微服務是一種系統架構的設計風格,它主旨在於將一個原本

Spring Cloud微服務實---1.9.微服務架構容錯處理

在微服務架中,所有功能均通過微服務來提供,如果其中某個關鍵微服務出現問題,如響應時間過長,那麼所有呼叫這個微服務的微服務都會變慢,由於呼叫者微服務變慢,進一步會使其他更廣泛的微服務變慢,最終整個系統可能會因為一個微服務出現問題,而使整個微服務架構出現故障。為了防止這種現象的發生,我們可以使用

Spring Cloud微服務實》讀書筆記之服務治理:Spring Cloud Eureka

摘要 服務治理是微服務架構最為核心和基礎的模組,用於實現各個微服務例項的自動化註冊與發現。Spring Cloud Eureka 是對Netflix Eureka的二次封裝,負責服務的治理。 關鍵詞:服務治理 一、服務治理介紹 服務治理是微服務架構最為核心和基礎

Spring Cloud微服務實》讀書筆記之客戶端負載均衡:Spring Cloud Ribbon

摘要 客戶端負載均衡元件部署在客戶端,由客戶端維護要訪問的服務端清單(清單來源於服務註冊中心)。在Spring Cloud 中預設使用Ribbon作為客戶端負載均衡。 關鍵詞:客戶端負載均衡,Ribbon 一、什麼是客戶端負載均衡 負載均衡是對系統高可用、緩解網

Spring Cloud微服務實視訊課程

第1章微服務架構概述1小時46分鐘2節1-1公開課[免費觀看]01:27:431-21.1 微服務架構概述[免費觀看]18:40第2章開始使用Spring Cloud實戰微服務13分鐘1節2-1開始使用Spring Cloud實戰微服務[免費觀看]13:46第3章服務提供者與

Spring Cloud 微服務實-王浩彬-專題視訊課程

Spring Cloud 微服務實戰—17435人已學習 課程介紹        1、瞭解Spring Cloud核心模組構成概要,實操通過模版空程式碼搭建自有框架,瞭解Spring Cloud核心模組拉通細節; 2、實操搭建服務腳手架,構建服務增刪改查基礎模組,考慮利用模

Spring Cloud 微服務實——Java開發人員必須掌握的技術

Spring Cloud簡介 Spring Cloud是一個基於Spring Boot實現的雲應用開發工具,它為基於JVM的雲應用開發中的配置管理、服務發現、斷路器、智慧路由、微代理、控制匯流排、全域性鎖、決策競選、分散式會話和叢集狀態管理等操作提供了一種簡單的開發方式

eureka詳解(spring cloud 微服務實的理解)

概述 這篇文章主要講的是eureka的架構和詳細配置。 eureka的架構 eureka的基礎架構可以分成三個部分: 1.服務註冊中心:提供服務的發現和註冊的功能。 2.服務提供者:提供服務的應用

第三章:Spring Cloud Eureka(Spring cloud微服務實)下

本章主要內容:1.原始碼分析2.配置詳解原始碼分析    我們從Eureka的客戶端看它如何完成通訊行為的。    我們將一個普通的Spring Boot應用註冊到Eureka Server 或者是 從Eureka Server 中獲取服務列表時,主要做了兩個事情:    在

Spring Cloud微服務實》——服務治理 Spring Cloud Eureka

一、簡介    Spring cloud Eureka是spring Cloud Netflix微服務套件中的一部分,它基於Netflix Eureka做了二次封裝,主要負責完成微服務架構中的服務治理功能。Spring  Cloud通過為Eureka增加了Spring Boo

Spring-cloud微服務實【三】:eureka註冊中心(中)

  回憶一下,在上一篇文章中,我們建立了兩個springboot專案,並且在consumer專案中通過restTemplate進行HTTP通訊,成功訪問到了producer提供的介面,思考一下這樣的實現方式有什麼問題?   1.consumer必須知道producer的IP,才能呼叫對方的HTTP介面,並且在