成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringCloud微服務中如何實現多端認證?

開發 架構
本文提出了一種靈活、可擴展的方案,以滿足 DailyMart 在業務發展過程中的多端認證需求。通過使用請求路徑區分不同端的請求來源,并在 SpringCloud Gateway 網關中實現相應的過濾器進行認證,方案具有靈活性、可擴展性和可維護性。

概述

DailyMart是一個ToC的在線購物商城,目前僅支持通過瀏覽器訪問。在商城中的所有操作都需要用戶先登錄。為了實現這一需求,我們可以采用以下技術方案:

  1. 用戶通過SpringCloud Gateway訪問CustomerService進行登錄認證。認證成功后,服務器返回一個JWT(JSON Web Token)。在接下來的操作中,用戶需要在請求頭中攜帶此Token。
  2. 在網關服務中,我們創建了一個名為ApiAuthenticatorFilter的過濾器。該過濾器用于驗證請求頭中是否包含Token,并檢查Token的有效性。如果請求頭中沒有攜帶Token,或者Token失效,則不允許訪問后端接口。

詳細交互流程如下圖1所示:

圖1:PC認證流程圖1:PC認證流程

多端認證需求

這種架構在初期可以滿足業務的發展需求。然而,隨著業務的擴展,我們需要考慮到現在大部分用戶使用手機進行購物的情況。因此,DailyMart也需要支持手機端訪問。但與瀏覽器不同,手機端的認證機制可能會有所不同。

例如,瀏覽器端的Token有效期通常設定為1小時,而手機端的Token有效期通常設置為7天或更長。此外,瀏覽器端的Token采用JWT這種去中心化的認證機制,而手機端的Token采用中心化的認證機制,需要調用手機端服務進行登錄認證。

同時,為了擴展業務,其他一些第三方應用可能也需要調用DailyMart的后端服務來獲取數據,對于第三方的應用一般采用appId + appSecret的方式進行認證,同時需要對接口參數進行簽名防止出現篡改和重放。(此方案在前文中有詳細說明,可以通過鏈接跳轉訪問查看。)

現在的問題是,如何在原有架構的基礎上滿足這三種不同形式的認證需求呢?

圖片圖片

解決方案

要解決這個問題,最關鍵在于如何判斷請求的來源,是來自瀏覽器端的請求、手機端的請求還是第三方的請求?

我們可以通過請求路徑進行區分,對于不同端的請求使用不同的路徑進行標識,可以做如下約定:

  • 手機端請求,需要在請求路徑上帶有/ph/
  • 瀏覽器請求,需要在請求路徑上帶有/pd/
  • 第三方請求,需要在路徑請求上帶有/pt/
  • ...

最終規定接口的完整請求路徑為:/服務名/api/來源標識/接口路徑/,如:http://localhost:9090/customer-service/api/pd/customer/info

這樣在SpringCloud Gateway網關先獲取請求的路徑,再根據請求的路徑判斷請求來源,最后根據請求來源實現不同的認證方案。

解決這個問題的關鍵在于如何判斷請求的來源,即是來自瀏覽器端、手機端還是第三方應用?

我們可以通過請求路徑進行區分,對于不同端的請求使用不同的路徑進行標識。例如:

  • 手機端請求,在請求路徑上帶有 /ph/
  • 瀏覽器端請求,在請求路徑上帶有 /pd/
  • 第三方請求,在請求路徑上帶有 /pt/
  • ...

最終,我們規定接口的完整請求路徑為:/服務名/api/來源標識/接口路徑/,例如:http://localhost:9090/customer-service/api/pd/customer/info

這樣,在SpringCloud Gateway網關中,我們需要創建一個過濾器,首先獲取請求的路徑,然后根據請求的路徑判斷請求來源,最后根據請求來源實現不同的認證方案。

代碼實現

有了解決方案,我們就很容易完成代碼實現了。

為了滿足多端認證的需求,在網關服務中我們可以抽取一個公共的認證接口ApiAuthenticator,具體的認證邏輯由具體實現類實現。

圖片圖片

在上面的類圖中,ProtectedApiAuthenticator用于實現第三方的認證邏輯,DefaultApiAuthenticator用于實現瀏覽器端的認證邏輯。

在網關過濾器ApiAuthenticatorFilter中,我們首先根據請求路徑獲取請求來源,然后根據請求來源找到對應的實現類。

@Component
@Slf4j
public class ApiAuthenticatorFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        URI uri = exchange.getRequest().getURI();
        String rawPath = uri.getRawPath();
        // 靜態接口直接過濾
        if (handleExcludeUrl(rawPath)) {
            return chain.filter(exchange);
        }
      
        // 獲取認證邏輯
        ApiAuthenticator apiAuthenticator = getApiAuthenticator(rawPath);
        AuthenticatorResult authenticatorResult = apiAuthenticator.auth(exchange);
        
        if (!authenticatorResult.isResult()) {
            return Mono.error(new HttpServerErrorException(
                    HttpStatus.METHOD_NOT_ALLOWED, authenticatorResult.getMessage()));
        }
        
        return chain.filter(exchange);
        
    }
    
    
    
    /**
     * 確定認證策略
     * @param rawPath 請求路徑
     */
    private ApiAuthenticator getApiAuthenticator(String rawPath) {
        String[] parts = rawPath.split("/");
        if (parts.length >= 4) {
            String parameter = parts[3];
            return switch (parameter) {
                case PROTECT_PATH -> new ProtectedApiAuthenticator();
                case PRIVATE_PATH -> new PrivateApiAuthenticator();
                case PUBLIC_PATH -> new PublicApiAuthenticator();
                case DEFAULT_PATH -> new DefaultApiAuthenticator();
                default -> throw new IllegalStateException("Unexpected value: " + parameter);
            };
        }
        return new DefaultApiAuthenticator();
    }
 
}

以下是瀏覽器端的認證邏輯,它會驗證JWT token的有效性。如果token失效,則直接返回錯誤提示給用戶,引導其重新登錄。

@Component
@Slf4j
public class DefaultApiAuthenticator implements ApiAuthenticator {
    
    @Override
    public AuthenticatorResult auth(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders httpHeaders = request.getHeaders();
        
        // 獲取JWT請求頭 Authorization
        String token = httpHeaders.getFirst(HttpHeaders.AUTHORIZATION);
        
        if (Objects.nonNull(token)) {
            try {
                String subjectFromJWT = JwtUtil.getSubjectFromJWT(token);
                log.info("用戶請求token: {} , 身份Subject:{}", token, subjectFromJWT);
                //重新設置請求頭
                mutateNewHeader(exchange, subjectFromJWT);

                return new AuthenticatorResult(true, "認證通過");
            } catch (ParseException | JOSEException e) {
                log.error("token解析失敗");
                return new AuthenticatorResult(false, "Token錯誤,請重新登錄!");
            }
            
        }
        
        return new AuthenticatorResult(false, "Token為空,請重新登錄!");
    }
}

小結

本文提出了一種靈活、可擴展的方案,以滿足 DailyMart 在業務發展過程中的多端認證需求。通過使用請求路徑區分不同端的請求來源,并在 SpringCloud Gateway 網關中實現相應的過濾器進行認證,方案具有靈活性、可擴展性和可維護性。

責任編輯:武曉燕 來源: JAVA日知錄
相關推薦

2024-09-04 11:16:44

端口Spring配置類

2024-03-06 08:36:36

2024-06-04 10:05:48

微服務網關日志

2025-01-07 14:09:58

微服務授權模式

2022-03-03 08:51:09

微服務認證中心授權模式

2024-07-31 09:09:20

2023-03-01 08:57:32

2024-12-27 10:12:28

2020-12-17 08:10:19

身份驗證授權微服務

2022-04-14 08:51:49

微服務Redisson分布式鎖

2021-06-09 09:42:50

SpringCloud微服務灰度發布

2021-03-09 09:33:42

網關授權微服務

2022-04-09 14:45:02

微服務常見概念Spring

2023-02-07 07:43:27

微服務應用框架

2020-11-15 23:48:57

服務網格微服務網絡網絡技術

2021-12-29 08:30:48

微服務架構開發

2024-11-06 16:27:12

2022-03-31 08:15:38

微服務服務拆分架構

2022-07-11 14:53:37

微服務容器IT

2022-09-06 10:29:27

無服務器Serverless
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 夜夜艹| 欧美在线综合 | 精品久久九九 | 中文字幕亚洲视频 | 国产一区 | 9191av| 99综合在线 | 久久精品久久精品久久精品 | 日韩精品免费 | 中文字幕一区二区三区四区五区 | 亚洲欧美在线观看视频 | 国产成人精品久久二区二区91 | 亚洲精品免费看 | 天天夜碰日日摸日日澡 | 久久久久亚洲精品 | 99精品国自产在线 | 91精品国产一二三 | 久久久.com| 羞羞视频网站在线观看 | 伊人网站在线 | 久久久av | www.久久| 亚洲精品综合一区二区 | 91pao对白在线播放 | av在线播放网址 | 亚洲成人久久久 | 五月天天丁香婷婷在线中 | 国产精品亚洲综合 | 一区二区三区免费 | 九九精品网| 国产一级免费视频 | 在线看av的网址 | h片在线免费观看 | 日本成人福利视频 | 国产日韩欧美在线 | 免费看一级毛片 | 欧美日韩91 | 国产乡下妇女做爰 | 国产精品毛片一区二区三区 | 国产一二区视频 | 精品国产一区二区 |