C#開發微信門戶及應用(41)--基於微信開放平臺的掃碼登錄處理

来源:http://www.cnblogs.com/wuhuacong/archive/2016/06/14/5583389.html
-Advertisement-
Play Games

在現今很多網站裡面,都使用了微信開放平臺的掃碼登錄認證處理,這樣做相當於把身份認證交給較為權威的第三方進行認證,在應用網站裡面可以不需要存儲用戶的密碼了。本篇介紹如何基於微信開放平臺的掃碼進行網站的登陸處理。 ...


在現今很多網站裡面,都使用了微信開放平臺的掃碼登錄認證處理,這樣做相當於把身份認證交給較為權威的第三方進行認證,在應用網站裡面可以不需要存儲用戶的密碼了。本篇介紹如何基於微信開放平臺的掃碼進行網站的登陸處理。

1、開放平臺的認證

要使用網站的掃碼登錄處理,就需要先進行微信開放平臺帳號的開發者資質認證,提交相關的資料,以及交付每年300元的認證費用。

認證後,建立相關的網站應用後,就有相關的APPID和APPSecret了,這些關鍵的參數就可以用來獲取相關的用戶信息了。

網站應用的應用詳情界面如下所示。

整個開放平臺感覺沒有多少東西,不過需要收費認證才能使用這些功能,感覺不是很爽。

 

2、掃碼登錄的說明和具體使用

網站應用微信登錄是基於OAuth2.0協議標準構建的微信OAuth2.0授權登錄系統。

在進行微信OAuth2.在進行微信OAuth2.0授權登錄接入之前,在微信開放平臺註冊開發者帳號,並擁有一個已審核通過的網站應用,並獲得相應的AppID和AppSecret,申請微信登錄且通過審核後,可開始接入流程。

微信OAuth2.0授權登錄讓微信用戶使用微信身份安全登錄第三方應用或網站,在微信用戶授權登錄已接入微信OAuth2.0的第三方應用後,第三方可以獲取到用戶的介面調用憑證(access_token),通過access_token可以進行微信開放平臺授權關係介面調用,從而可實現獲取微信用戶基本開放信息和幫助用戶實現基礎開放功能等。

微信OAuth2.0授權登錄目前支持authorization_code模式,適用於擁有server端的應用授權。該模式整體流程為:

1. 第三方發起微信授權登錄請求,微信用戶允許授權第三方應用後,微信會拉起應用或重定向到第三方網站,並且帶上授權臨時票據code參數;

2. 通過code參數加上AppID和AppSecret等,通過API換取access_token;

3. 通過access_token進行介面調用,獲取用戶基本數據資源或幫助用戶實現基本操作。

獲取access_token時序圖:

 

從上圖我們可以大概瞭解整個掃碼登陸的處理過程。

 

3、掃碼登錄的各個步驟處理

1)用戶身份的綁定

為了實現二維碼掃碼登錄,我們需要在現有系統裡面綁定用戶的微信,這樣才能在用戶掃碼的時候,判斷用戶的身份從而實現自動登錄的過程。

我們可以在用戶管理裡面進行統一設置,也可以在常規用戶登錄(用戶名+密碼)後進行設置,這個主要看我們是否需要保留用戶名密碼登陸這種方式。

例如可以在用戶管理裡面統一綁定,也就是在創建用戶的時候,讓用戶綁定下微信,獲取微信的唯一標識。

也可以在保留用戶名密碼的登陸方式外,讓用戶登陸系統後自行進行綁定微信即可。

上面的界面,就是在一個頁面裡面彈出一個層,然後請求二維碼顯示即可,如下界面代碼所示。

        <div id="divWechat" class="easyui-dialog" style="width:450px;height:350px;padding:10px 20px"
             closed="true" resizable="true" modal="true" iconcls="icon-setting">
            <div>
                <h4>掃描用戶二維碼,進行綁定</h4>
            </div>
            <div align="center">
                <img id="imgQRcode" alt="使用微信掃碼進行綁定" style="height:200px;width:auto" />
            </div>

            <div align="right">
                <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-cancel" onclick="javascript: $('#divWechat').dialog('close')">關閉</a>
            </div>
        </div>

上面的層在打開的時候,我們使用JS來動態獲取二維碼進行顯示,具體JS代碼如下所示。

    //綁定微信登陸
    function BindWechat() {
        var url = "http://www.iqidi.com/H5/BindWechat?id=@Session["UserID"]";
        url = encodeURIComponent(url);
        $("#imgQRcode").attr("src", "/H5/QR?url=" + url);
        //打開綁定視窗
        $("#divWechat").dialog('open').dialog('setTitle', '使用微信掃碼進行綁定');
    }

上面的JS只是做前端的數據請求和顯示,具體的QR動作Action其實就是生成掃描二維碼的過程,這個二維碼其實就是採用通用的方式,來構建一個指向我們綁定賬號的地址,從而實現我們綁定賬號的判斷,二維碼的生成過程如下所示。

        /// <summary>
        /// 轉換二維碼連接為圖片格式
        /// </summary>
        /// <param name="url">二維碼連接</param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult QR(string url)
        {
            //初始化二維碼生成工具
            QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
            qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
            qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
            qrCodeEncoder.QRCodeVersion = 0;
            qrCodeEncoder.QRCodeScale = 4;

            //將字元串生成二維碼圖片
            var image = qrCodeEncoder.Encode(url, Encoding.Default);
            //保存為PNG到記憶體流  
            MemoryStream ms = new MemoryStream();
            image.Save(ms, ImageFormat.Png);
            image.Dispose();

            return File(ms.ToArray(), "image/Png");
        }

為了實現用戶的綁定,我們需要獲取當前用戶的身份信息,因此需要在BindWeChat的操作裡面做一個轉向處理,如下介面所示。

        /// <summary>
        /// 生成綁定微信的地址
        /// </summary>
        /// <returns></returns>
        public ActionResult BindWechat()

這個函數處理裡面,我們需要重新定向處理,我們把它定向到BindAccount函數裡面,方便獲取用戶的openid和其他必要的信息。

另外我們基於微信開放平臺的應用,建立了一個和微信賬號信息的聯繫,因此創建資料庫信息如下所示。

也就是一個具體的開放平臺應用對應著一個具體的微信賬號,這樣我們就可以充分利用配置進行處理了。

上面提到的BindAccount的處理的邏輯就是獲取必要的信息,然後在資料庫層面對身份信息進行驗證,具體代碼如下所示。

        /// <summary>
        /// 綁定用戶微信號
        /// </summary>
        /// <param name="id">賬號ID</param>
        /// <returns></returns>
        public ActionResult BindAccount()
        {
            WebAppInfo appInfo = GetWebApp(ConfigData.WebAppId);
            AccountInfo accountInfo = GetAccount(appInfo.AccountNo);

            var htResult = GetOpenIdAndUnionId(accountInfo.UniteAppId, accountInfo.UniteAppSecret);//存儲openid方便使用
            string openid = htResult["openid"].ToString();
            var unionid = htResult["unionid"].ToString();
            var userid = Request.QueryString["id"];
            var state = Request.QueryString["state"];

            if (!string.IsNullOrEmpty(openid) && !string.IsNullOrEmpty(userid))
            {
                CommonResult result = BLLFactory<User>.Instance.BindUser(openid, unionid, userid.ToInt32());
                if (result.Success)
                {
                    return BindSuccess();
                }
                else
                {
                    return BindFail();
                }
            }
            else
            {
                throw new WeixinException("無法獲取openid" + string.Format(", openid:{0}, userid:{1}", openid, userid));
            }
        }

在綁定的過程,我們需要考慮綁定正確賬號,重覆綁定其他賬號,無效綁定幾種情況,如果成功綁定正確賬號(可多次處理結果一樣),那麼得到界面如下所示(這個界面的樣式採用了weui的樣式)。

  

 

2)用戶的掃碼登錄處理

上面綁定了賬號後,就可以通過掃碼進行登錄了,掃碼回調的時候我們有自己的判斷處理,掃碼界面如下所示(我們在保留用戶名密碼登陸的方式外,增加了一個掃碼登錄的處理)。

如果是Bootstrap的界面效果

如果是EasyUI的界面效果

這個和前面的二維碼顯示規則差不多,不過他們的連接地址是不同的,這個地方用到了開放平臺的介面,也就是我們前面提到開放平臺認證的介面了。

上面的掃碼登錄的界面代碼如下所示。

    <!--二維碼掃描登陸的界面層-->
    <div id="divWechat" class="easyui-dialog" style="width:550px;height:500px;padding:10px 20px"
         closed="true" resizable="true" modal="true" iconcls="icon-setting">
        <div id="login_container" align="center">
        </div>

        <div align="right">
            <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-cancel" onclick="javascript: $('#divWechat').dialog('close')">關閉</a>
        </div>
    </div>

上面代碼需要引入JS文件,並使用微信JSSDK的API進行顯示的。

    <!--使用微信掃碼進行登陸-->
    <script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
    <script language="javascript">

        function OpenJSLogin() {
            var obj = new WxLogin({
                id: "login_container",
                appid: "@ViewBag.appid",
                scope: "snsapi_login",
                redirect_uri: "@ViewBag.redirect_uri",
                state: "@ViewBag.state",
                style: "black",
                href: ".impowerBox .qrcode {width: 200px;}"
            });

            //打開綁定視窗
            $("#divWechat").dialog('open').dialog('setTitle', '使用微信掃碼進行登陸');
        }
    </script>

這個裡面的參數,如APPID就是來源我們認證後的開放平臺參數。

這些信息我們在MVC控制器後面獲取後綁定在ViewBag,方便界面前端的使用。

            //使用JSLogin登陸
            WebAppInfo appInfo = BLLFactory<WebApp>.Instance.FindByID(ConfigData.WebAppId);
            ArgumentValidation.CheckForNullReference(appInfo, "Web應用程式appInfo");

            if (appInfo != null)
            {
                ViewBag.appid = appInfo.OpenAppID;
                ViewBag.redirect_uri = appInfo.LoginCallBackUrl;
                ViewBag.state = ConfigData.AuthState;
            }

其中的redirect_uri是通過資料庫獲取的LoginCallBackUrl地址,這個地址類似如下格式:http://www.iqidi.com/H5/callback?uid=iqidiSoftware

也就是我們在開放平臺處理返回後進行的回調處理。

通過開放平臺的APPID和APPSecret,我們可以獲取到對應的介面調用憑證,然後根據介面憑證,以及openid,獲得用戶的公眾平臺統一的UnionID,這個標識是我們用戶的唯一標識,代碼如下所示。

                var result = baseApi.GetAuthToken(appid, appsecret, code);
                if (result != null && !string.IsNullOrEmpty(result.openid))
                {
                    openid = result.openid;
                    var unionResult = baseApi.GetSnsapiUserInfo(result.access_token, result.openid);

                    ht.Add("openid", openid);
                    ht.Add("unionid", unionResult != null ? unionResult.unionid : "");
                }

有了unionid我們就可以根據這個標識在我們的用戶資料庫裡面查找對應的用戶,如下代碼所示。

            //開放平臺的OpenID,不是公眾號的OpenID,需要轉換為unionid
            if (!string.IsNullOrEmpty(openid) && !string.IsNullOrEmpty(unionid))
            {
                UserInfo userInfo = BLLFactory<User>.Instance.FindByUnionId(unionid);

然後判斷我們去到的用戶信息是否正確,如下代碼所示

                if (userInfo != null)
                {
                    CommonResult loginResult = CheckLogin(userInfo.Name);
                    if (!loginResult.Success)
                    {
                        LogHelper.Info(string.Format("用戶登陸不成功,{0}", loginResult.ErrorMessage));
                    }

                    //登陸成功後的重定向地址
                    var url = appInfo.HomeUrl;  //例如:http://www.iqidi.com/Home
                    return Redirect(url);
                }

如果不成功,那麼我們定向到指定的界面即可。

            //如不成功,最後都統一提示信息
            ViewBag.Error = "獲取信息失敗,登陸錯誤";
            return View("LoginError");

如果我們登陸成功後,需要設置一些Session信息或者Cookie信息,那麼就可以通過CheckLogin函數進行處理即可。

以上就是我們結合微信開放平臺實現微信掃碼登錄的過程,其中整個過程就是用到了下麵幾個過程。

1)使用JSSDK的腳本實現掃碼獲取code

JS微信登錄主要用途:網站希望用戶在網站內就能完成登錄,無需跳轉到微信域下登錄後再返回,提升微信登錄的流暢性與成功率。 網站內嵌二維碼微信登錄JS實現辦法:

步驟1:在頁面中先引入如下JS文件(支持https):

<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>

步驟2:在需要使用微信登錄的地方實例以下JS對象:

                          var obj = new WxLogin({
                              id:"login_container", 
                              appid: "", 
                              scope: "", 
                              redirect_uri: "",
                              state: "",
                              style: "",
                              href: ""
                            });

2) 第二步:通過code獲取access_token

通過code獲取access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

3)第三步:通過access_token調用介面

獲取access_token後,進行介面調用,

對於介面作用域(scope),能調用的介面有以下:

授權作用域(scope)介面介面說明
snsapi_base /sns/oauth2/access_token 通過code換取access_token、refresh_token和已授權scope
/sns/oauth2/refresh_token 刷新或續期access_token使用
/sns/auth 檢查access_token有效性
snsapi_userinfo /sns/userinfo 獲取用戶個人信息

其中snsapi_base屬於基礎介面,若應用已擁有其它scope許可權,則預設擁有snsapi_base的許可權。使用snsapi_base可以讓移動端網頁授權繞過跳轉授權登錄頁請求用戶授權的動作,直接跳轉第三方網頁帶上授權臨時票據(code),但會使得用戶已授權作用域(scope)僅為snsapi_base,從而導致無法獲取到需要用戶授權才允許獲得的數據和基礎功能。

4)獲取信息在回調界面中進行登錄前處理

通過上面介面,我們可以獲得相應的用戶身份信息,因此可以結合我們用戶資料庫進行用戶身份的認定和處理,並設置必要的Session或者Cookie信息等,最後定位到我們的應用主界面即可。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用vim打造IDE, 針對C語言開發者建議使用gvim 先上兩個截圖 # 安裝ctags1. 下載地址: http://ctags.sourceforge.net/# 安裝cscope1. 下載地址: http://cscope.sourceforge.net/ 2. 修改源碼,使其支持遞歸搜索文 ...
  • 1.首先安裝nfs-kernel-server apt-get install nfs-kernel-server 2.然後創建一個目錄: mkdir -p /opt/share 並賦予許可權777: chmod -R 777 /opt/share 3.在/etc/exports文件中添加配置:(打開 ...
  • 使普通用戶也能使用wireshark轉包 > 創建wireshark組 sudo groupadd wireshark> 將dumpcap加入wireshark組 sudo chgrp wireshark /usr/bin/dumpcap> 使wireshark有許可權使用dumpcap sudo c ...
  • locate命令可以快速搜索文件,與find不同,locate直接檢索系統維護的資料庫。 ...
  • linux系統中通過find命令來查找文件,該命令有眾多參數,這裡只是列舉了一些常見用法。 ...
  • Linux下運行的Web伺服器Apache,預設日誌文件是不分割的,一個整文件既不易於管理,也不易於分析統計。安裝cronolog後,可以將日誌文件按時間分割,易於管理和分析。 cronolog安裝配置非常簡單,下載後只需要輸入幾個命令即可完成。 1、下載(最新版本) 如果這個鏈接失效,請上這個鏈接 ...
  • 總結一下上一個項目中對webapi 用戶登錄許可權控制的設計 目的:前端可以根據介面的狀態碼來判斷用戶的登錄狀態,以及訪問許可權 1.首先我們在webconfig裡面添加一條配置,用於開啟或關閉許可權控制 2.先瞭解一下 ActionFilterAttribute 這個類,該類可以在action方法執行前 ...
  • 1 環境搭建:安裝CAD 和objectArx庫,這裡安裝的是cad2012和objectArx2010 ,vs是2010 2 新建一個類庫項目,引用objectArx安裝目錄下inc文件夾下的AcDbMgd.dll和AcMgd.dll,這裡註意X86和X64系統的區別 3 添加兩個類,一個繼承IE ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...