PC 端微信掃碼註冊和登陸

1、前言

先聲明一下,本文所注重點爲實現思路,代碼及數據庫設計主要爲了展示思路,若是對代碼效率有着苛刻要求的項目切勿照搬。html

相信作過微信開發的人受權這塊都沒少作過,可是通常來講咱們更多的是爲移動端的網站作受權,確切來講是在微信端下作的一個受權。今天遇到的一個問題是,項目支持微信端以及 PC 端,而且開放註冊。要求作到不管在 PC 端註冊或者是在微信端註冊以後均可以在另一個端進行登陸。也就是說不管 PC 或是微信必須作到"你就是你"(經過某種方式關聯)。jquery

2、尋找解決方案

按傳統的方式來思考,微信端徹底能夠經過受權進行註冊,可是PC端呢,傳統的方式無非就是填填手機號碼啊,或者 Email 等等。若是採用這種方式註冊,會產生下面這的問題git

  1. 我先在微信端受權註冊,那麼若是我要登陸PC端仍是得進行註冊。

    對此解決方案能夠爲:微信受權註冊後「強制」要求用戶必須填寫基本信息,如手機號、Email 。這樣咱們能夠經過某種方式爲用戶生成PC端登陸的帳號密碼.例如以用戶的 nickname 爲帳號,手機號碼爲密碼,等等方式。github

    弊端:用戶體驗很差,再者有安全隱患。畢竟你的微信暱稱, Email 或者手機號碼都是暴露的。web

  2. 若是我先在 PC 端註冊,我在微信受權的時候怎樣關聯移動端

          固然,凡是問題總會有解決方案的。思路以下:數據庫

         方案一:當用戶在 PC 端註冊後,「強制」 用戶必須填寫微信暱稱。以此做爲微信受權時的關聯條件。可是很遺憾,微信暱稱能夠改,不是惟一的怎麼能夠用來作關聯?方案一陣亡。canvas

    

         方案二:在微信端受權後,以及在 PC 端註冊後「強制」要求用戶填寫手機號碼以此爲關聯。這樣衍生出一個問題,必須確保用戶手機的真實信,沒問題。這個能夠經過手機驗證碼來實現(Email也是同樣)。可是不妨假設一下有下面這種狀況,若是我有兩個手機號碼,PC 端註冊時填一個,微信註冊時填另外一個。關聯的了嗎?答案是很遺憾。再者,我在PC 端註冊後我就是不填(筆者把強制打上雙引號的緣由),而後我用微信端受權登陸一下。好吧,此時將會有兩條數據等着你想辦法去關聯,典型的開發者自挖坑。這種方式某種程度上行得通,可是嚴謹程度上是開發者沒法接受的。api

3、迴歸原點的解決方案

分析:既然方案上述方案都有問題,咱們先把它們都拋到一邊。整理一下思路,讓咱們回到問題的根本。關聯的問題,要的是一個惟一標識。惟一標識正如咱們的身份證號碼,咱們辦理信用卡的時候身份證是必須的,實名制下購買號碼卡,身份證是必須的。假設咱們是這系統管理員,那麼我徹底能夠經過你的身份證號碼查出你手機號碼,銀行卡號碼。安全

有了上面的思路以後,咱們須要作的就是找到一個惟一標識來做爲關聯.微信上有個重要的角色 openid。 它跟咱們上面提到的身份證號碼有這共同的做用,微信帳號對某一公衆號的惟一標識。微信

微信端的受權拿到 openid 作過微信開發的人都應該沒有問題。問題是怎樣來實現 PC 端 在註冊或者登錄的時候拿到 openid。筆者的實現思路以下。PC 端註冊,或者登錄時顯示一個二維碼引導用戶使用微信掃碼,使其跳轉到受權頁面。這一步有一個最爲關鍵的細節,二維碼請帶上一個惟一的受權碼(authCode)。試想一下若是用戶受權後咱們能把 openid 以及 authCode 寫入到數據庫。那麼咱們就能夠在 PC 端經過某個 API 獲取 authCode 所關聯的這個 openid。若是咱們作到這點咱們就能夠知道當前是誰在 PC 端進行掃碼註冊或登陸(沒註冊的註冊,有註冊的直接登陸)。 是否是忽然以爲 so easy. 若是以爲文字比較抽象,請看下面圖示

PC 端微信掃碼登陸流程

核心代碼

搞清楚了思路和流程接下來咱們直接上代碼啦.開發思路是共通的,開發語言就請各顯神通啦。

說明:下面代碼以 C# 語言爲例,採用 MVC + EF (注:uuid 等價於咱們上述的 authCode)

掃碼登陸頁後臺代碼
public ActionResult Login()
{
    //若是已登陸,直接跳轉到首頁
    if (User.Identity.IsAuthenticated)
        return RedirectToAction("Index", "Home");

    string url = Request.Url.Host;
    string uuid = Guid.NewGuid().ToString();
    ViewBag.url = "http://" + url + "/home/loginfor?uuid=" + uuid;//構造受權連接
    ViewBag.uuid = uuid;//保存 uuid
    return View();
}

 

生成二維碼採用插件 jquery.qrcode.js,想詳細瞭解的朋友請移步 Github。 這裏須要注意的一點是,該插件能夠指定二維碼的生成方式,canvas 或者 table 請須要支持 IE 的朋友指定使用 table 生成

代碼以下:
jQuery('#qrcode').qrcode({
    render    : "table",
    text    : "http://baidu.com"
});

 

迴歸正題,登陸頁面的主要代碼以下

 

<!--生成二維碼的容器 div-->
<div id="qrcode-container">
</div>

<script src="~/Plugins/Jquery/jquery-1.9.1.min.js"></script>
<script src="~/Plugins/jquery-qrcode/jquery.qrcode.min.js"></script>
<script>
    jQuery(function () {
        //生成二維碼
        jQuery('#qrcode-container').qrcode("@ViewBag.url");

        //輪詢判斷用戶是否受權
        var interval = setInterval(function () {
            $.post("@Url.Action("UserLogin","Home")", { "uuid": "@ViewBag.uuid" }, function (data, status) {
                if ("success" == status) {
                    //用戶成功受權=>跳轉
                    if ("success" == data) {
                        window.location.href = '@Url.Action("Index", "Home")';
                        clearInterval(interval);
                    }
                }
            });
        }, 200);
    })
</script>

 

輪詢判斷用戶是否受權 API 代碼
public string UserLogin(string uuid)
{
    //驗證參數是否合法
    if (string.IsNullOrEmpty(uuid))
        return "param_error";

    WX_UserRecord user = db.WX_UserRecord.Where(u => u.uuId == uuid).FirstOrDefault();
    if (user == null)
        return "not_authcode";

    //寫入cookie
    FormsAuthentication.SetAuthCookie(user.OpenId, false);

    //清空uuid
    user.uuId = null;
    db.SaveChanges();

    return "success";
} 

 

微信端受權 Action
public ActionResult Loginfor(string uuid)
{

    #region 獲取基本信息 - snsapi_userinfo

    /*
     * 建立微信通用類 - 這裏代碼比較複雜不在這裏貼出
     * 遲點我會將整個 Demo 稍微整理放上 Github
    */
    WechatUserContext wxcontext = new WechatUserContext(System.Web.HttpContext.Current, uuid);

    //使用微信通用類獲取用戶基本信息
    wxcontext.GetUserInfo();

    if (!string.IsNullOrEmpty(wxcontext.openid))
    {
        uuid = Request["state"];
        //判斷數據庫是否存在
        WX_UserRecord user = db.WX_UserRecord.Where(u => u.OpenId == wxcontext.openid).FirstOrDefault();
        if (null == user)
        {
            user = new WX_UserRecord();
            user.OpenId = wxcontext.openid;
            user.City = wxcontext.city;
            user.Country = wxcontext.country;
            user.CreateTime = DateTime.Now;
            user.HeadImgUrl = wxcontext.headimgurl;
            user.Nickname = wxcontext.nickname;
            user.Province = wxcontext.province;
            user.Sex = wxcontext.sex;
            user.Unionid = wxcontext.unionid;                    
            user.uuId = uuid;
            db.WX_UserRecord.Add(user);
        }
        user.uuId = uuid;
        db.SaveChanges();
    }
    #endregion

    return View();
} 

 

最後附上數據庫表設計

沒什麼特殊的,就是微信返回的各個參數加多一個咱們自定義的 uuId

微信參數說明 詳情請見 微信開發者文檔

運行效果

1.掃碼登陸頁面

2.請求用戶受權

3.用戶確認受權

4.PC 端登陸完成

項目DEMO已上傳至 GitHub

附上兩張配置圖:

1.開發參數配置

 

2.公衆號配置

文章不免有不足之處,還請海涵。若有發現錯誤還望留言指出,筆者感激涕零! 微信掃碼註冊登陸 Demo 待筆者整理後放上 Github 但願幫到更多的朋友,請有須要的朋友留意該文更新。

本文爲做者原創,轉載請註明出處!

相關文章
相關標籤/搜索