先聲明一下,本文所注重點爲實現思路,代碼及數據庫設計主要爲了展示思路,若是對代碼效率有着苛刻要求的項目切勿照搬。html
相信作過微信開發的人受權這塊都沒少作過,可是通常來講咱們更多的是爲移動端的網站作受權,確切來講是在微信端下作的一個受權。今天遇到的一個問題是,項目支持微信端以及 PC 端,而且開放註冊。要求作到不管在 PC 端註冊或者是在微信端註冊以後均可以在另一個端進行登陸。也就是說不管 PC 或是微信必須作到"你就是你"(經過某種方式關聯)。jquery
按傳統的方式來思考,微信端徹底能夠經過受權進行註冊,可是PC端呢,傳統的方式無非就是填填手機號碼啊,或者 Email 等等。若是採用這種方式註冊,會產生下面這的問題git
對此解決方案能夠爲:微信受權註冊後「強制」要求用戶必須填寫基本信息,如手機號、Email 。這樣咱們能夠經過某種方式爲用戶生成PC端登陸的帳號密碼.例如以用戶的 nickname 爲帳號,手機號碼爲密碼,等等方式。github
弊端:用戶體驗很差,再者有安全隱患。畢竟你的微信暱稱, Email 或者手機號碼都是暴露的。web
固然,凡是問題總會有解決方案的。思路以下:數據庫
方案一:當用戶在 PC 端註冊後,「強制」 用戶必須填寫微信暱稱。以此做爲微信受權時的關聯條件。可是很遺憾,微信暱稱能夠改,不是惟一的怎麼能夠用來作關聯?方案一陣亡。canvas
方案二:在微信端受權後,以及在 PC 端註冊後「強制」要求用戶填寫手機號碼以此爲關聯。這樣衍生出一個問題,必須確保用戶手機的真實信,沒問題。這個能夠經過手機驗證碼來實現(Email也是同樣)。可是不妨假設一下有下面這種狀況,若是我有兩個手機號碼,PC 端註冊時填一個,微信註冊時填另外一個。關聯的了嗎?答案是很遺憾。再者,我在PC 端註冊後我就是不填(筆者把強制打上雙引號的緣由),而後我用微信端受權登陸一下。好吧,此時將會有兩條數據等着你想辦法去關聯,典型的開發者自挖坑。這種方式某種程度上行得通,可是嚴謹程度上是開發者沒法接受的。api
分析:既然方案上述方案都有問題,咱們先把它們都拋到一邊。整理一下思路,讓咱們回到問題的根本。關聯的問題,要的是一個惟一標識。惟一標識正如咱們的身份證號碼,咱們辦理信用卡的時候身份證是必須的,實名制下購買號碼卡,身份證是必須的。假設咱們是這系統管理員,那麼我徹底能夠經過你的身份證號碼查出你手機號碼,銀行卡號碼。安全
有了上面的思路以後,咱們須要作的就是找到一個惟一標識來做爲關聯.微信上有個重要的角色 openid。 它跟咱們上面提到的身份證號碼有這共同的做用,微信帳號對某一公衆號的惟一標識。微信
微信端的受權拿到 openid 作過微信開發的人都應該沒有問題。問題是怎樣來實現 PC 端 在註冊或者登錄的時候拿到 openid。筆者的實現思路以下。PC 端註冊,或者登錄時顯示一個二維碼引導用戶使用微信掃碼,使其跳轉到受權頁面。這一步有一個最爲關鍵的細節,二維碼請帶上一個惟一的受權碼(authCode)。試想一下若是用戶受權後咱們能把 openid 以及 authCode 寫入到數據庫。那麼咱們就能夠在 PC 端經過某個 API 獲取 authCode 所關聯的這個 openid。若是咱們作到這點咱們就能夠知道當前是誰在 PC 端進行掃碼註冊或登陸(沒註冊的註冊,有註冊的直接登陸)。 是否是忽然以爲 so easy. 若是以爲文字比較抽象,請看下面圖示
搞清楚了思路和流程接下來咱們直接上代碼啦.開發思路是共通的,開發語言就請各顯神通啦。
說明:下面代碼以 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>
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"; }
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
微信參數說明 詳情請見 微信開發者文檔
項目DEMO已上傳至 GitHub
附上兩張配置圖:
1.開發參數配置
2.公衆號配置
文章不免有不足之處,還請海涵。若有發現錯誤還望留言指出,筆者感激涕零! 微信掃碼註冊登陸 Demo 待筆者整理後放上 Github 但願幫到更多的朋友,請有須要的朋友留意該文更新。
本文爲做者原創,轉載請註明出處!