最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

教你Spring Cloud保證各個微服務之間調用安全性

 更新時間:2021年08月20日 10:08:37   作者:碼農架構  
在微服務的架構下,系統會根據業(yè)務拆分為多個服務,各自負責單一的職責,在這樣的架構下,我們需要確保各api的安全性,今天通過本文給大家分享Spring Cloud中如何保證各個微服務之間調用的安全性,需要的朋友參考下吧

導讀:在微服務的架構下,系統會根據業(yè)務拆分為多個服務,各自負責單一的職責,在這樣的架構下,我們需要確保各api的安全性,也就是說服務不是開放的,而是需要授權才可訪問的,避免接口被不合法的請求所訪問。

但是在在微服務集群中服務之間暴力的接口,或者對于第三方開放的接口如果不做及安全和認證,后果可想而知。

閱讀下文之前思考幾個問題:

  • 如何在restTemplate遠程調用請求增加添加統一認證?
  • 服務認證如何規(guī)范加密和解密?
  • 遠程調用統一什么協議比較合適?

如下圖,三個服務注冊到同一個注冊中心集群,服務A、B、C之間如果不做任何限制,服務之間的接口基本是互通的。

圖片

但是如果A、B、C之間要做服務認證該如何設計?如果外部定制集成服務D接入怎么保證服務的安全性?

怎么加認證?

假設服務A是組織架構服務,服務B是規(guī)則引擎服務,服務C是公式引擎服務,如果B、C請求A服務調用用戶信息除了開放接口規(guī)定參數。我們如何加入權限認證信息。

目前市面上主要兩種方案處理

  • 請求體Body中加入參數校驗 => SDK集成場景較多
  • 請求頭Header中加入認證信息 token

請求頭Header中加入認證信息 token,如下圖結構所示。

圖片

確定服務認證統一在request header 加X-SERVICE-NAME,在服務服務中我們不可能每個服務都會主動去管理基礎認證信息,仔細閱讀RestTemplate源碼不難發(fā)現,RestTemplate實現接口InterceptingHttpAccessor,因此我們可以再定義自己的攔截器來統一處理。

圖片

攔截@FeignClient 標識攔截

feign遠程調用請求增加頭部信息處理,重新定義 RequestInterceptor

public class FeignApiInterceptor implements RequestInterceptor {
 
    /**
     * 統一處理feign的遠程調用攔截
     */
    @Override
    public void apply(RequestTemplate requestTemplate) {
        // 遠程調用請求增加頭部信息處理(簡寫代碼如下)
		requestTemplate.header("X-SERVICE-NAME", "...");
    }
}

攔截RestTemplate遠程調用請求

RestTemplate 提供高度封裝的接口,可以讓我們非常方便地進行 Rest API 調用。常見的方法如下:

image.jpg

RestTemplate遠程調用請求增加頭部信息處理,統一處理處理restTemplate的請求攔截。

/**
 * restTemplate遠程調用請求增加頭部信息處理
 */
@Slf4j
public class RestApiHeaderInterceptor implements ClientHttpRequestInterceptor {
 
    /**
     * 處理restTemplate的請求攔截
     */
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        long startTime = System.currentTimeMillis();
        try {
            HttpHeaders headers = request.getHeaders();
            
            // 遠程調用請求增加頭部信息處理(簡寫代碼如下)
			requestTemplate.header("X-SERVICE-NAME", "...");
            
            ClientHttpResponse response = execution.execute(request, body);
            
            // 加入鏈路深度Deep
            // ....
            return response;
        } finally {
            // do something
        }
    }
}

服務注冊客戶端配置

@Configuration
@EnableFeignClients(basePackages = NamingConstant.BASE_PACKAGE)
public class DiscoveryClientConfig {
    
    //......
    
    /**
     * feign請求攔截器
     */
    @Bean
    public RequestInterceptor feignInterceptor() {
        return new FeignApiInterceptor();
    }
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(HttpClient httpClient,
                                     Environment environment) {
        RestTemplate restTemplate = new RestTemplate();
        restTemplateBuilder.configure(restTemplate);
        restTemplate.setRequestFactory(buildFactory(httpClient, environment));
        // 加入自定義攔截器
        restTemplate.getInterceptors().add(new RestApiHeaderInterceptor());
        return restTemplate;
    }
    
}

拓展補充:

在處理RestTemplate的請求攔截的時候我們也可以追加鏈路追蹤日志,具體對于鏈路日志的拓展可查閱《微服務分布式架構中,如何實現日志鏈路跟蹤?》

簡寫代碼

@Slf4j
public class RestApiHeaderInterceptor implements ClientHttpRequestInterceptor {
 
    /**
     * 處理restTemplate的請求攔截
     */
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        long startTime = System.currentTimeMillis();
        try {
            // 遠程調用請求增加頭部信息處理
            ClientHttpResponse response = execution.execute(request, body);
            // 獲取傳遞線程變量
            Collection<String> values = response.getHeaders()
                    .get(TraceUtil.TRACE_RPCCOUNT);
            if (!CollectionUtils.isEmpty(values)) {
                int value = Integer.valueOf(values.iterator().next());
                // 鏈路深度追加
                TraceUtil.getRpcCounter().addAndGet(value + 1);
            }
            return response;
        } finally {
            // 是否開啟鏈路追蹤
            if (TraceUtil.isTraceLoggerOn()) {
                // 輸出鏈路日志(接口耗時)
                TraceUtil.log(StringHelper.join("dt:", System.currentTimeMillis() - startTime,
                        ", TRACE-RPC-", request.getMethod(),
                        ", URI:", request.getURI()));
            }
        }
    }
}

怎么接收認證信息?

讀過Spring-Web源碼應該知道OncePerRequestFilter過濾器基類,旨在保證在任何 servlet 容器上每個請求分派一次執(zhí)行。 它提供了一個帶有 HttpServletRequest 和 HttpServletResponse 參數的doFilterInternal方法,詳細用法可閱讀源碼。

另一種也出現在它自己的線程中的調度類型是ERROR 。 如果子類希望靜態(tài)聲明是否應該在錯誤調度期間調用一次,它們可以覆蓋shouldNotFilterErrorDispatch() 。

getAlreadyFilteredAttributeName方法確定如何識別請求已被過濾。 默認實現基于具體過濾器實例的配置名稱。

定義基礎過濾器

public abstract class BaseWebFilter extends OncePerRequestFilter {
 
    /**
     * 返回類名,避免filter不被執(zhí)行
     */
    @Override
    protected String getFilterName() {
        return null;
    }
}

過濾器定義虛擬類, 繼承自接口的過濾器。如果聲明為springbean,他自動加載到請求過濾鏈(因為繼承了GenericFilterBean接口,spring默認把繼承此類的過濾器bean加到web過濾鏈)中,通過注解@order定義其優(yōu)先級如果不申明為springbean,又要加入到過濾鏈中,可以通過FilterRegistrationBean定義,并指定優(yōu)先級

封裝攔截 ApiValidationFilter

@Override
public BaseWebFilter getFilterInstance() {
    return new BaseWebFilter() {
        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
            // 攔截校驗
            if (validateToken(request)) {
                // 校驗通過執(zhí)行下一個lan'j
                chain.doFilter(request, response);
            } else {
                // 封裝統一認證失敗返回信息
                response.setStatus(401);
                response.setCharacterEncoding(
                    Charset.defaultCharset().displayName());
                response.setContentType(
                    MimeTypeUtils.APPLICATION_JSON.toString());
                response.getWriter().println(JsonUtil.toJsonString(Response
                                                                   .err("status.401")));
            }
        }
    };
}

針對與validateToken方法這里就不做展開,對于加密方式大同小異,根據自己項目情況來定。

private boolean validateToken(HttpServletRequest request) {
		if (!needValidate(request)) {
			return true;
		}
		String security = resolveToken(request);
		if (security == null) {
			log.info("驗證信息缺失,請求地址:{}", request.getRequestURI());
			return false;
		}
		try {
            // 解析security加密規(guī)則
			return true;
		} catch (Exception e) {
			log.info("驗證信息無效:{},請求地址:{}", security, request.getRequestURI());
			return false;
		}
	}

總結

回顧整個方案設計與實現,大致可分為以下幾個步驟

參數加入位置:請求頭Header還是請求體Body確定加入范圍:@FeignClient客戶端、構建RestTemplate以及集成服務遠程接口調用確定攔截位置:Web線程攔截器,用于統一處理線程變量,該過濾器執(zhí)行順序早于springsecurity的過濾器確定加密/解密方式:加密字符串和解密​​​​​​

到此這篇關于教你Spring Cloud保證各個微服務之間調用安全性的文章就介紹到這了,更多相關Spring Cloud微服務調用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JAVA如何獲取客戶端IP地址和MAC地址

    JAVA如何獲取客戶端IP地址和MAC地址

    本篇文章主要介紹了JAVA如何獲取客戶端IP地址和MAC地址非常具有實用價值,這里整理了詳細的代碼,需要的朋友可以參考下
    2017-08-08
  • Springboot控制反轉與Bean對象的方法

    Springboot控制反轉與Bean對象的方法

    文章介紹了Spring Boot中的控制反轉(IoC)概念,描述了IoC容器如何管理Bean的生命周期和依賴關系,它詳細講解了Bean的注冊過程,包括通過@ComponentScan和@Bean注解的方式,并討論了Bean的依賴注入方法,如構造器注入、Setter注入和字段注入,感興趣的朋友一起看看吧
    2025-03-03
  • 一文帶你了解Spring中@Enable開頭注解的使用

    一文帶你了解Spring中@Enable開頭注解的使用

    前面的文章給大家介紹?Spring?的重試機制的時候有提到過?Spring?有很多?@Enable?開頭的注解,平時在使用的時候也沒有注意過為什么會有這些注解,今天就給大家介紹一下
    2022-09-09
  • Springboot接收前端的Json但是為null問題

    Springboot接收前端的Json但是為null問題

    這篇文章主要介紹了Springboot接收前端的Json但是為null問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教<BR>
    2024-05-05
  • java在linux系統下開機啟動無法使用sudo命令的原因及解決辦法

    java在linux系統下開機啟動無法使用sudo命令的原因及解決辦法

    每次開機自動啟動的java進程,頁面上的關機按鈕都無法實現關機功能,但是此時如果以chb賬號通過ssh登錄該服務器,手動殺掉tomcat進程,然后再重新啟動tomcat,頁面上的關機按鈕就有效了
    2013-08-08
  • springboot運行到dokcer中 dockerfile的場景分析

    springboot運行到dokcer中 dockerfile的場景分析

    這篇文章主要介紹了springboot運行到dokcer中 dockerfile,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • java實現文件上傳功能

    java實現文件上傳功能

    這篇文章主要為大家詳細介紹了java實現文件上傳功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • Springmvc ViewResolver設計實現過程解析

    Springmvc ViewResolver設計實現過程解析

    這篇文章主要介紹了Springmvc ViewResolver設計實現過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-10-10
  • Spring Boot jpa Service層代碼實例

    Spring Boot jpa Service層代碼實例

    這篇文章主要介紹了Spring Boot jpa Service層代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • Nacos框架服務注冊實現流程

    Nacos框架服務注冊實現流程

    這篇文章主要介紹了SpringCloud服務注冊之nacos實現過程,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08

最新評論

华容县| 泾阳县| 拉孜县| 河东区| 航空| 锡林郭勒盟| 运城市| 定边县| 当雄县| 桃园市| 湾仔区| 安化县| 赤峰市| 博客| 思茅市| 福建省| 安福县| 宿松县| 融水| 手机| 和平区| 兴文县| 阳高县| 内丘县| 天门市| 黔西| 长治县| 什邡市| 石河子市| 东乡县| 内江市| 运城市| 专栏| 佛坪县| 化德县| 郸城县| 岱山县| 简阳市| 北碚区| 临潭县| 阿荣旗|