如何實現H5端對接釘釘登錄并優雅擴展其他平臺

如何實現H5端對接釘釘登錄并優雅擴展其他平臺

    • 釘釘H5登錄邏輯
    • 后端代碼如何實現?
    • 本次采用策略模式+工廠方式進行
      • 定義接口確定會使用的基本鑒權步驟
      • 具體邏輯類進行實現
      • 采用注冊表模式(Registry Pattern)
      • 抽象工廠進行基本邏輯定義
      • 具體工廠進行對接口中的邏輯步驟具體----實例化----邏輯進行重寫
    • 總結

釘釘H5登錄邏輯

下圖中需要說明的一點是,準確來說步驟3來說是釘釘API返回給前端,前端攜帶一次性校驗碼token給后端進行后續的鑒權。
還有一點需要注意獲得權限之后,如果前端需要回調接口獲取用戶信息,則需要增加上下文中的用戶信息存儲

image-20250407212849539

后端代碼如何實現?

具體的偽代碼如下所述,下面細聊一下如何進行實現獲取用戶信息這一步。其中本次采用了設計模式進行實現。

    public Result<LoginResp> h5Login(LoginH5UserReq loginH5UserReq) throws ApiException {// 獲取租戶信息xxxxx// 查詢三方鑒權配置信息xxxxx// 獲取用戶信息 這一步很關鍵后面細說如何實現H5AuthHandler H5AuthHandler = H5AuthHandlerRegistry.createHandler(loginH5UserReq.getTypePlatForm());String userUniqueIdentifier = H5AuthHandler.getUserDetail(loginH5UserReq);// 系統校驗根據手機號查詢用戶信息SysUser sysUser = sysUserMapper.selectOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getTel, userUniqueIdentifier), false);// 使用斷言進行優雅校驗Assert.notNull(sysUser, () -> new BizException(ErrorCodeEnum.NOT_AVAILABLE));// 校驗通過下發tokenString accessToken = StpUtil.getTokenInfo().getTokenValue();xxxxreturn Result.success(loginResult);}

本次我的思路是實現針對不同平臺,例如對接釘釘、企業微信、飛書、三方,具體的邏輯是不一樣的,使用設計模式中的工廠模式進行構建,實現不同的邏輯進行創建不同類進行完成。

簡單羅列一下可以采用的設計模式的具體之間的區別

image-20250407214413483

本次采用策略模式+工廠方式進行

定義接口確定會使用的基本鑒權步驟

public interface AuthHandler {// 獲取訪問令牌(需處理OAuth2 code校驗)String getAccessToken(String code) throws AuthException;// 使用令牌換取用戶唯一標識(需處理令牌失效場景)String getUserId(String token) throws AuthException;// 獲取用戶詳細信息(需處理多層級JSON解析)UserDetail getUserDetail(String userId) throws AuthException;
}

具體邏輯類進行實現

下面代碼是大致思路展示,直接run是會出現問題。涉及公司保密協議不可以直接上我的源碼望讀者朋友見諒~

public class DingTalkAuthHandler implements AuthHandler {private static final String API_HOST = "https://oapi.dingtalk.com";private final String appKey;private final String appSecret;// 依賴配置注入(參考網頁6的釘釘配置)public DingTalkAuthHandler(String appKey, String appSecret) {this.appKey = appKey;this.appSecret = appSecret;}@Overridepublic String getAccessToken(String code) {// 構建認證請求參數(參考網頁7的code交換邏輯)Map<String, String> params = new HashMap<>();params.put("appkey", appKey);params.put("appsecret", appSecret);// 調用釘釘API(網頁6的接口文檔)String url = API_HOST + "/gettoken?" + buildQueryString(params);JsonNode response = HttpUtil.get(url);// 錯誤碼校驗(參考網頁6的errcode處理)if(response.get("errcode").asInt() != 0) {throw new DingTalkAuthException(response.get("errmsg").asText());}return response.get("access_token").asText();}@Overridepublic String getUserId(String token) {// 安全域名驗證(參考網頁7的domain校驗)String url = API_HOST + "/user/getuserinfo?access_token=" + token;JsonNode userInfo = HttpUtil.get(url);return userInfo.get("userid").asText();}@Overridepublic UserDetail getUserDetail(String userId) {// 多層級數據解析(參考網頁6的JSON結構)String url = API_HOST + "/user/get?userid=" + userId;JsonNode data = HttpUtil.get(url).get("result");return UserDetail.builder().mobile(data.at("/mobile").asText()) // JSONPath定位.name(data.get("name").asText()).avatar(data.get("avatar").asText()).build();}// 私有方法封裝請求構建private String buildQueryString(Map<String, String> params) {return params.entrySet().stream().map(e -> e.getKey() + "=" + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8)).collect(Collectors.joining("&"));}
}

上述代碼通過接口 + 實現類的方式進行大致邏輯的定義,具體邏輯的展開,不是本次的重點,主要想記錄一下如何實現下述的調用:

// 需要實現根據loginH5UserReq.getTypePlatForm() 傳入不同的類型,實現實例化對應的實體類進行處理對應邏輯
H5AuthHandler H5AuthHandler = H5AuthHandlerRegistry.createHandler(loginH5UserReq.getTypePlatForm());
// 得到具體邏輯類之后根據請求信息返回用戶唯一的id進行后續鑒權
String userUniqueIdentifier = H5AuthHandler.getUserDetail(loginH5UserReq);

采用注冊表模式(Registry Pattern)

集中管理平臺與工廠映射關系,提供統一訪問入口

@Component
// 為什么要采用ApplicationContextAware?文末解釋
public class H5AuthHandlerRegistry implements ApplicationContextAware {private static final Map<String, H5AuthHandlerFactory<?>> REGISTRY = new ConcurrentHashMap<>();private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext context) {applicationContext = context;// Spring容器初始化完成后動態注冊平臺registerPlatforms();}// 具體平臺注冊private void registerPlatforms() {// 釘釘平臺注冊(依賴注入已生效)H5DingTalkAuthFactory dingTalkFactory = new H5DingTalkAuthFactory(applicationContext);REGISTRY.put(Platforms.DING_TALK.name(), dingTalkFactory);// 其他平臺注冊xxxxxxx}// 獲取處理器工廠public static H5AuthHandlerFactory<?> getFactory(String platform) {return Optional.ofNullable(REGISTRY.get(platform)).orElseThrow(() -> new IllegalArgumentException("未注冊的平臺: " + platform));}// 全局同意訪問入口public static H5AuthHandler createHandler(String platform) {return getFactory(platform).createHandler();}
}

抽象工廠進行基本邏輯定義

為什么這里要使用抽象類?

首先我想定義基本的創建邏輯,其次抽象類不能被實例化。還有抽象類一般用于設計模式中一種通用寫法規范,為子類提供公共的代碼實現(如非抽象方法)和強制約束(如抽象方法),子類繼承并實現所有抽象方法后才能實例化。

public abstract class H5AuthHandlerFactory<T extends H5AuthHandler> {private final Class<T> handlerClass;protected H5AuthHandlerFactory(Class<T> handlerClass) {this.handlerClass = handlerClass;}// 定義基本創建邏輯,采用反射方式進行。支持反射創建(需無參構造)// PS:如果具體進行邏輯類不涉及采用spring容器管理類,可以使用直接newInstance。不然會出現創建失敗,spring容器ioc和Java創建對象是割裂的兩派public T createHandler() {try {return handlerClass.getDeclaredConstructor().newInstance();} catch (Exception e) {throw new RuntimeException("H5端登錄邏輯抽象工廠---H5AuthHandlerFactory---處理器實例化失敗", e);}}}

具體工廠進行對接口中的邏輯步驟具體----實例化----邏輯進行重寫

public class H5DingTalkAuthFactory extends H5AuthHandlerFactory<H5DingTalkAuthHandler> {private final ApplicationContext context;// 這里是因為具體實例化處理釘釘H5登錄邏輯類會使用到spring容器中的類,所以需要采用上下文的方式public H5DingTalkAuthFactory(ApplicationContext context) {super(H5DingTalkAuthHandler.class);this.context = context;}@Overridepublic H5DingTalkAuthHandler createHandler() {// 從Spring容器獲取依賴項ThreePartyLoginRuleConfig ruleConfig = context.getBean(ThreePartyLoginRuleConfig.class);ObjectMapper objectMapper = context.getBean(ObjectMapper.class);// 通過構造器注入依賴return new H5DingTalkAuthHandler(ruleConfig, objectMapper);}
}

總結

總體來說,要實現其他平臺的擴展。本次的使用中,由于對接不同平臺,具體邏輯中涉及了配置文件配置不同平臺JSON數據的解析,所以會使用sping中IOC功能,所以在工廠類中存在上下文部分。

擴展其他平臺部分就需要創建兩個類,一個類是集成抽象工廠實現其中的createHandler()方法,還有一個是實現接口中定義的三部曲。

H5xxxxxxxAuthFactory extends H5AuthHandlerFactory
H5xxxxxxxxAuthHandler implements H5AuthHandler

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/76252.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/76252.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/76252.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32F103C8T6單片機開發:簡單說說單片機的外部GPIO中斷(標準庫)

目錄 前言 如何使用STM32F1系列的標準庫完成外部中斷的抽象 初始化我們的GPIO為輸入的一個模式 初識GPIO復用&#xff0c;開啟GPIO的復用功能時鐘 GPIO_EXTILineConfig和EXTI_Init配置外部中斷參數 插入一個小知識——如何正確的配置結構體&#xff1f; 初始化中斷&#…

【自然語言處理】深度學習中文本分類實現

文本分類是NLP中最基礎也是應用最廣泛的任務之一&#xff0c;從無用的郵件過濾到情感分析&#xff0c;從新聞分類到智能客服&#xff0c;都離不開高效準確的文本分類技術。本文將帶您全面了解文本分類的技術演進&#xff0c;從傳統機器學習到深度學習&#xff0c;手把手實現一套…

Java Lambda與方法引用:函數式編程的顛覆性實踐

在Java 8引入Lambda表達式和方法引用后&#xff0c;函數式編程范式徹底改變了Java開發者的編碼習慣。本文將通過實戰案例和深度性能分析&#xff0c;揭示如何在新項目中優雅運用這些特性&#xff0c;同時提供傳統代碼與函數式代碼的對比優化方案。 文章目錄 一、Lambda表達式&a…

劍指offer經典題目(三)

目錄 動態規劃入門 二進制運算 鏈表相關 動態規劃入門 題目1&#xff1a;一只青蛙一次可以跳上1級臺階&#xff0c;也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法&#xff08;先后次序不同算 不同的結果&#xff09;。OJ地址 簡單圖示如下。 題目分析&#…

【每日隨筆】叢林法則 ( 弱肉強食 | 適者生存 | 資源有限稀缺 | 沒有道德約束 | 自發性與無序性 | 叢林法則映射 - 資源分配 與 社會分層 )

文章目錄 一、叢林法則1、弱肉強食2、適者生存3、資源有限稀缺4、沒有道德約束5、自發性與無序性6、叢林法則映射 - 資源分配 與 社會分層 一、叢林法則 叢林法則 是 在 資源有限 的環境中 , 競爭 是生存的基礎 , 弱肉強食 , 適者生存 , 且過程 不受道德約束 ; 叢林法則 在 自…

【含文檔+PPT+源碼】基于小程序的智能停車管理系統設計與開發

項目視頻介紹&#xff1a; 畢業作品基于小程序的智能停車管理系統設計與開發 課程簡介&#xff1a; 本課程演示的是一款基于小程序的智能停車管理系統設計與開發&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Java 學習者。 1.包含&#xff1a;…

Navicat連接遠程PostGreSQL失敗

問題描述 使用本地Navicat連接Windows遠程服務器上部署的PostGreSQL數據庫時,出現以下錯誤: 解決方案 出現以上報錯信息,是因為PostGreSQL數據庫服務尚未設置允許客戶端建立遠程連接。可做如下配置, 1. 找到PostGreSQL數據庫安裝目錄下的data子文件夾,重點關注:postgres…

【Linux】jumpserver開源堡壘機部署

JumpServer 安裝部署指南 本文檔詳細記錄了 JumpServer 安裝部署的過程、核心腳本功能說明以及后續管理使用提示&#xff0c;方便運維人員快速查閱和二次安裝。 1. 前提條件 操作系統要求&#xff1a; 僅支持 Linux 系統&#xff0c;不支持 Darwin&#xff08;macOS&#xff0…

餐飲廚房開源監控安全系統的智能革命

面對日益嚴格的合規要求和消費者對衛生的信任危機&#xff0c;傳統人工監督已力不從心&#xff1a;衛生死角難發現、違規操作難追溯、安全隱患防不勝防。如何讓后廚更透明、更安全、更可信&#xff1f;餐飲廚房視頻安全系統橫空出世&#xff01;這套系統融合實時監控與AI技術&a…

HashMap為什么擴容為原來2倍呢?

1、減少哈希碰撞 核心原因&#xff1a;HashMap的所有設計都依賴于數組長度為2的冪次方這一前提。 索引計算使用 &#xff08;n-1)&hash &#xff0c;其中 n 是數組長度當 n 是 2 的冪次方時&#xff0c;n-1 的二進制形式是全 1&#xff08;例如&#xff0c;15——>111…

debian系統中文輸入法失效解決

在 Debian 9.6 上無法切換中文輸入法的問題通常與輸入法框架&#xff08;如 Fcitx 或 IBus&#xff09;的配置或依賴缺失有關。以下是詳細的解決步驟&#xff1a; 1. 安裝中文語言包 確保系統已安裝中文語言支持&#xff1a; sudo apt update sudo apt install locales sudo…

3DGS之光柵化

光柵化&#xff08;Rasterization&#xff09;是計算機圖形學中將連續的幾何圖形&#xff08;如三角形、直線等&#xff09;轉換為離散像素的過程&#xff0c;最終在屏幕上形成圖像。 一、光柵化的核心比喻 像畫家在畫布上作畫 假設你是一個畫家&#xff0c;要把一個3D立方體畫…

學習51單片機Day02---實驗:點亮一個LED燈

目錄 1.先看原理圖 2.思考一下&#xff08;sbit的使用&#xff09;&#xff1a; 3.給0是要讓這個LED亮&#xff08;LED端口設置為低電平&#xff09; 4.完成的代碼 1.先看原理圖 比如我們要讓LED3亮起來&#xff0c;對應的是P2^2。 2.思考一下&#xff08;sbit的使用&…

Redis與Lua原子操作深度解析及案例分析

一、Redis原子操作概述 Redis作為高性能的鍵值存儲系統&#xff0c;其原子性操作是保證數據一致性的核心機制。在Redis中&#xff0c;原子性指的是一個操作要么完全執行&#xff0c;要么完全不執行&#xff0c;不會出現部分執行的情況。 Redis原子性的實現原理 單線程模型&a…

深入理解 GLOG_minloglevel 與 GLOG_v:原理與使用示例

文章目錄 深入理解 GLOG_minloglevel 與 GLOG_v&#xff1a;原理與使用示例1. GLOG_minloglevel&#xff1a;最低日志等級控制2. GLOG_v&#xff1a;控制 VLOG() 的詳細輸出等級3. GLOG_minloglevel 與 GLOG_v 的優先級關系4. 使用示例4.1 基礎示例&#xff1a;不同日志等級4.2…

Cline Memory Bank 結構化文檔持久化 AI 上下文詳解

&#x1f3ae; 什么是 Cline Memory Bank&#xff1f; Memory Bank 是一個結構化文檔系統&#xff0c;允許 Cline 在會話之間保持上下文。它能讓 Cline 從無狀態的助手轉變為持久記憶的開發伙伴&#xff0c;隨著時間推移有效地“記住”項目細節。 &#x1f5e1;? 關鍵優勢 上…

【JavaScript】面向對象與設計模式

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;HTML CSS JavaScript 文章目錄 1. JavaScript 中的面向對象編程1.1 對象基礎1.2 構造函數1.3 原型和原型鏈1.4 ES6 類1.5 繼承1.6 封裝 2. 創建型設計模式2.1 工廠模式2.2 單例模式2.3 建造者模式2.4 原型模式 3. 結構型設計模式…

網絡安全防護技術

邊界安全防護——防火墻 控制&#xff1a;在網絡連接點上建立一個安全控制點&#xff0c;對進出數據進行限制隔離&#xff1a;將需要保護的網絡與不可信任網絡進行隔離&#xff0c;隱藏信息并進行安全防護記錄&#xff1a;對進出數據進行檢查&#xff0c;記錄相關信息 防火墻…

Spring MVC 視圖解析器(JSP、Thymeleaf、Freemarker、 JSON/HTML、Bean)詳解

Spring MVC 視圖解析器詳解 1. 視圖解析器概述 視圖解析器&#xff08;ViewResolver&#xff09;是 Spring MVC 的核心組件&#xff0c;負責將控制器返回的視圖名稱&#xff08;如 success&#xff09;轉換為具體的 View 對象&#xff08;如 Thymeleaf 模板或 JSP 文件&#x…

# 爬蟲技術的實現

手把手教你網絡爬蟲&#xff1a;從入門到實踐 一、網絡爬蟲簡介 網絡爬蟲&#xff08;Web Crawler&#xff09;是一種自動化獲取互聯網數據的程序&#xff0c;廣泛應用于搜索引擎、數據分析、市場調研等領域。通過模擬瀏覽器行為&#xff0c;爬蟲可以高效地從網頁中提取結構化…