日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

基于IdentityServer的系统对接微信公众号

發布時間:2023/12/4 windows 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于IdentityServer的系统对接微信公众号 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

業務需求

公司有兩個業務系統,A和B,AB用戶之間屬于多對一的關系,數據庫里面也就是兩張表,A表有個外鍵指向B。現在需要實現以下幾個功能。

  • A用戶掃描B的二維碼,填寫相關的注冊信息,注冊完成之后自動屬于B。也就是表A的外加字段指向B。

  • 老用戶和微信openid綁定。

  • 用戶在公眾號里面自動登錄。

  • 項目結構

    公司項目基于.net core 2.1 + Vue,

    后端有以下幾個子系統:

  • 基于IdentityServer4?的asp.net mvc,簡稱account 項目,配了域名account.xxx.com

  • 兩個業務系統api。A和B。分別域名配置aapi.xxx.com 和bapi.xxx.com

  • 其他。。

  • 前端有以下幾個系統,都是基于Vue的SPA:

  • A業務系統,域名a.xxx.com

  • B業務系統,域名b.xxx.com

  • 其他。

  • 登錄這塊的邏輯實現方式是類似的。都是基于IdentityModel/oidc-client-js

    簡單介紹一下IdentityServer這個東西。

    用戶登錄A或B系統,就是調用A和B對應的webapi,webapi配置了自己的驗證服務器是account服務器,account驗證未通過,前端就得到401狀態碼,通過oidc-client-js的內部方法引導用戶進行登錄。跳轉account的頁面,用戶輸入用戶名密碼,登錄成功,account服務器判斷是A or B過來的登錄請求,帶上token回跳到配置的對應頁面。業務系統再次用獲取到的token請求api,調用成功。用一個圖來說。

    實現方法

    用了盛派微信sdk,特別感謝大佬的貢獻。

    推薦一下微信沙箱環境,項目做完下來除了"無法在測試的公眾號里面推送小程序消息”無法實現之外(因為推送的需要公眾號和小程序有一個綁定關系),其他都ok。

    因為版本的關系,account系統升級了asp.net core 2.2。

    先實現上面第一個需求

    這里用到微信里面生成帶參數的二維碼功能。B系統創建了用戶之后,生成一個對應的guid,然后把這個guid作為參數,調用sdk就能得到二維碼的url。


    var qrRstTicketRst = await QrCodeApi.CreateAsync(weixinSetting.WeixinAppId, 30, 100000,
    QrCode_ActionName.QR_LIMIT_STR_SCENE, sceneId);

    var url = QrCodeApi.GetShowQrCodeUrl(qrRstTicketRst.ticket);

    這里我們項目中用到的是永久二維碼,雖然這個二維碼上限10W個,我們業務系統B用戶不會超過那么多。

    B用戶展示二維碼給A用戶,A用戶掃描,根據文檔:

    如果用戶還未關注公眾號,則用戶可以關注公眾號,關注后微信會將帶場景值關注事件推送給開發者。

    如果用戶已經關注公眾號,在用戶掃描后會自動進入會話,微信也會將帶場景值掃描事件推送給開發者。

    觸發代碼里面分別對應的是OnEvent_SubscribeRequest?和OnEvent_ScanRequest,兩個方法里面的代碼基本上是一樣的。RequestMessageEvent_Scan.EventKey可以得到上面的guid值。Subscribe事件里面得到的EventKey會比Scan的多一個qrscene前綴,處理的時候要注意一點。兩個方法參數都能通過FromUserName獲取到掃描的用戶的openId,然后在這個方法里面返回一個帶參數(A的openId,和B的guid)的注冊鏈接,A用戶注冊的時候就提交了這兩個參數,后臺就能拿到。

    順道說一句,公眾號里面用戶每次操作只能被動返回一條消息。如要主動推送,需要用模板消息的方式。

    實現第二個需求

    對于老用戶,這里需要一個賬號綁定的功能。也就是業務系統的賬號和openId做一個關聯。綁定的關鍵在于這個如何獲取這個openId,這里有兩種方式。

  • 用戶點擊公眾號的菜單,后端獲取到這個事件,在OnEvent_ClickRequest中,判斷RequestMessageEvent_Click.EventKey==xxx,返回一個帶openId的綁定頁面的鏈接給用戶。比如/bind?openId=xxx,用戶點擊這個鏈接,系統引導用戶登錄,然后點擊綁定按鈕,實現綁定。

  • 基于微信網頁授權,這個在自動登錄里面也用到了,所以下面解釋。

  • 實現第三個需求

    系統中用戶和微信的openId已經綁定,所以,只要知道每次訪問頁面的openId就應該能實現自動登錄。openId是通過微信網頁授權的方式獲取到。流程可以看文檔。簡單來說,先拿code,再換token,同時拿到openId。實現步驟分以下幾步。

    • 添加一個公眾號菜單,type是view,也就是點了之后會打開一個頁面,頁面地址直接用獲取code的url.

    {
    "type": "view",
    "name": "登錄A",
    "url":"https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxb66259f2a353&redirect_uri=http%3A%2F%2Faccount.xxx.cn%2Fweixincallback%2Fcallback&response_type=code&scope=snsapi_base&state=spa.A#wechat_redirect"
    }

    url中的state參數會和code一起返回給設置的redirectUrl,這個可以用來給我們在account登錄中心判斷是需要登錄A還是B,以便最后回跳到對應的業務頁面。

    這里在沙箱配置跳轉域名的時候注意一下,只要寫域名就好。

    • 打開頁面,需要用戶點允許授權。通過之后瀏覽器會把code 和 state參數帶這get請求redirect_url

    • callback頁面的邏輯

    callback 接收code和state兩個參數。

    public async Task<IActionResult> Callback(string code, string state){...}

    用這個code調用sdk里面的api獲取token,同時可以拿到openid。

    var tokenResult = await OAuthApi.GetAccessTokenAsync(AppId, AppSecret, code);
    if (tokenResult.errcode != ReturnCode.請求成功)
    {
    throw new BizException("獲取微信用戶信息失敗");
    }
    var openId = tokenResult.openid;

    通過open獲取用戶信息。

    var userInfo = await userService.GetByOpenId(openId);

    然后調用HttpContext.SignInAsync登錄。

    public static async Task SignInAsync(this HttpContext context, string subject, string name, AuthenticationProperties properties, params Claim[] claims)
    {
    var clock = context.GetClock();
    var user = new IdentityServerUser(subject)
    {
    DisplayName = name,
    AdditionalClaims = claims,
    AuthenticationTime = clock.UtcNow.UtcDateTime
    };
    await context.SignInAsync(user, properties);
    }

    HttpContext是當前請求的上下文。

    subject可以理解為用戶的標識。

    name可以理解是用戶顯示的名字。

    AuthenticationProperties是此次認證的一些配置,比如有效時長之類的。

    Claim可以理解為這個subject帶的一些屬性。

    await HttpContext.SignInAsync(userMobile, userName, props, claims);

    調用完之后就登錄成功。

    然后通過帶來的state參數判斷需要跳轉的client。

    var client = await clientStore.FindClientByIdAsync(state);
    return Redirect($"{client.PostLogoutRedirectUris.FirstOrDefault()}?logined=true");

    這里帶一個logined=true參數,用來給client做一些邏輯。

    總結

    首先要感謝的肯定是盛派微信sdk的contributors,沒有他們系統對接起來應該會慢很多。

    然后我想說,IdentityServer是個好東西,現在公司.NET相關的系統都已經用這個實現統一的登錄邏輯了,系統維護的代價小了許多。

    說起來其實也是第一次對接微信公眾號相關的東西,在走通這條路之前走了不少彎路,不過好在走通了。希望對其他人有幫助。


    總結

    以上是生活随笔為你收集整理的基于IdentityServer的系统对接微信公众号的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。