前言
網頁授權是:應用或者網站請求你用你的微信帳號登錄,同意之后第三方應用可以獲取你的個人信息
網上說了一大堆參數,實際很難理解和猜透,我們以實際的代碼來演示比較通俗易懂
配置
實現之前我們必須配置用戶授權獲取用戶信息的域名或者IP。正式公眾號只能配置(域名)
第一步:登錄公眾號平台
跟我們之前配置公眾號平台信息一樣
第二步: 打開開發者工具
拉到下半部分位置的網頁賬號
第三步:配置你的授權回調域名
實現
我們模擬一個需要授權的頁面(代碼提供來自Senparc)
第一步:新建一個Controller
里面只有2個方法,一個是Index即需要授權的頁面,第二個是BaseCallback頁面即授權成功后要跳轉的頁面
public class OAuth2Controller : Controller { [Dependency] public IWC_OfficalAccountsBLL account_BLL { get; set; } /// <summary> /// /// </summary> /// <param name="returnUrl">用戶嘗試進入的需要登錄的頁面</param> /// <returns></returns> public ActionResult Index(string returnUrl) { WC_OfficalAccountsModel model = account_BLL.GetCurrentAccount(); //獲取用戶保存的cookie //判斷是否已經授權過 var state = "YMNETS-" + DateTime.Now.Millisecond;//隨機數,用於識別請求可靠性 Session["State"] = state;//儲存隨機數到Session ViewData["returnUrl"] = returnUrl; //此頁面引導用戶點擊授權 ViewData["UrlUserInfo"] = OAuthApi.GetAuthorizeUrl(model.AppId, "http://ymnets.imwork.net/WC/OAuth2/UserInfoCallback?returnUrl=" + returnUrl.UrlEncode(), state, OAuthScope.snsapi_userinfo); ViewData["UrlBase"] = OAuthApi.GetAuthorizeUrl(model.AppSecret, "http://ymnets.imwork.net/WC/OAuth2/BaseCallback?returnUrl=" + returnUrl.UrlEncode(), state, OAuthScope.snsapi_base); return View(); } /// <summary> /// OAuthScope.snsapi_userinfo方式回調 /// </summary> /// <param name="code"></param> /// <param name="state"></param> /// <param name="returnUrl">用戶最初嘗試進入的頁面</param> /// <returns></returns> public ActionResult UserInfoCallback(string code, string state, string returnUrl) { if (string.IsNullOrEmpty(code)) { return Content("您拒絕了授權!"); } if (state != Session["State"] as string) { //這里的state其實是會暴露給客戶端的,驗證能力很弱,這里只是演示一下, //建議用完之后就清空,將其一次性使用 //實際上可以存任何想傳遞的數據,比如用戶ID,並且需要結合例如下面的Session["OAuthAccessToken"]進行驗證 return Content("驗證失敗!請從正規途徑進入!"); } OAuthAccessTokenResult result = null; //通過,用code換取access_token try { WC_OfficalAccountsModel model = account_BLL.GetCurrentAccount(); result = OAuthApi.GetAccessToken(model.AppId, model.AppSecret, code); } catch (Exception ex) { return Content(ex.Message); } if (result.errcode != ReturnCode.請求成功) { return Content("錯誤:" + result.errmsg); } //下面2個數據也可以自己封裝成一個類,儲存在數據庫中(建議結合緩存) //如果可以確保安全,可以將access_token存入用戶的cookie中,每一個人的access_token是不一樣的 Session["OAuthAccessTokenStartTime"] = DateTime.Now; Session["OAuthAccessToken"] = result; //因為第一步選擇的是OAuthScope.snsapi_userinfo,這里可以進一步獲取用戶詳細信息 try { if (!string.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); } OAuthUserInfo userInfo = OAuthApi.GetUserInfo(result.access_token, result.openid); return View(userInfo); } catch (ErrorJsonResultException ex) { return Content(ex.Message); } } } }
獲取接口的方法
/*此接口不提供異步方法*/ /// <summary> /// 獲取驗證地址 /// </summary> /// <param name="appId">公眾號的唯一標識</param> /// <param name="redirectUrl">授權后重定向的回調鏈接地址,請使用urlencode對鏈接進行處理</param> /// <param name="state">重定向后會帶上state參數,開發者可以填寫a-zA-Z0-9的參數值,最多128字節</param> /// <param name="scope">應用授權作用域,snsapi_base (不彈出授權頁面,直接跳轉,只能獲取用戶openid),snsapi_userinfo (彈出授權頁面,可通過openid拿到昵稱、性別、所在地。並且,即使在未關注的情況下,只要用戶授權,也能獲取其信息)</param> /// <param name="responseType">返回類型,請填寫code(或保留默認)</param> /// <param name="addConnectRedirect">加上后可以解決40029-invalid code的問題(測試中)</param> /// <returns></returns> public static string GetAuthorizeUrl(string appId, string redirectUrl, string state, OAuthScope scope, string responseType = "code", bool addConnectRedirect = true) { var url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}{5}#wechat_redirect", appId.AsUrlData(), redirectUrl.AsUrlData(), responseType.AsUrlData(), scope.ToString("g").AsUrlData(), state.AsUrlData(), addConnectRedirect ? "&connect_redirect=1" : ""); /* 這一步發送之后,客戶會得到授權頁面,無論同意或拒絕,都會返回redirectUrl頁面。 * 如果用戶同意授權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE。這里的code用於換取access_token(和通用接口的access_token不通用) * 若用戶禁止授權,則重定向后不會帶上code參數,僅會帶上state參數redirect_uri?state=STATE */ return url; }
通過這個接口就可以組成調用微信API的參數
第二步:界面數據

@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>OAuth2.0授權測試</title> <style> .green { color: green; } </style> @Scripts.Render("~/bundles/modernizr") @Scripts.Render("~/bundles/jquery") </head> <body> <h2>OAuth2.0授權測試</h2> <p>注意:此頁面僅供測試,測試號隨時可能過期。請將此DEMO部署到您自己的服務器上,並使用自己的appid和secret。</p> <p> 當前returnUrl: @if (ViewData["returnUrl"] == null || ViewData["returnUrl"] as string == "") { <span> <strong>不帶returnUrl</strong>。 </span><br /> <span class="green">使用不帶returnUrl的頁面會停留在Callback頁面,此頁面如果刷新(或后退到此頁面),會導致code過期的錯誤,只建議在測試階段使用。</span> <br/> <span> 測試帶returnUrl@(Html.ActionLink("點擊這里", "Index", new { returnUrl = Url.Action("TestReturnUrl") }))。 </span> } else { <span><strong>@ViewData["returnUrl"]</strong>。</span><br /> <span class="green">攜帶returnUrl后,頁面最終會跳轉到returnUrl對應頁面,避免刷新頁面導致code的錯誤。</span> } </p> <p><a href="@ViewData["UrlUserInfo"]">點擊這里測試snsapi_userinfo</a></p> <p> 將要鏈接到的地址:<br /> <textarea rows="10" cols="40">@ViewData["UrlUserInfo"]</textarea> </p> <p><a href="@ViewData["UrlBase"]">點擊這里測試snsapi_base</a></p> <p> 將要鏈接到的地址:<br /> <textarea rows="10" cols="40">@ViewData["UrlBase"]</textarea> </p> </body> </html>

@model Senparc.Weixin.MP.AdvancedAPIs.OAuth.OAuthUserInfo @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>OAuth2.0授權測試授權成功</title> </head> <body> <h2>OAuth2.0授權測試授權成功!</h2> @if (ViewData.ContainsKey("ByBase")) { <p><strong>您看到的這個頁面來自於snsapi_base授權,因為您已關注本微信,所以才能查詢到詳細用戶信息,否則只能進行常規的授權。</strong></p> } else { <p><strong>您看到的這個頁面來自於snsapi_userinfo授權,可以直接獲取到用戶詳細信息。</strong></p> } <p>下面是通過授權得到的您的部分個人信息:</p> <p>openid:@Model.openid</p> <p>nickname:@Model.nickname</p> <p>country:@Model.country</p> <p>province:@Model.province</p> <p>city:@Model.city</p> <p>sex:@Model.sex</p> @if (Model.unionid != null) { <p>unionid:@Model.unionid</p> } <p> 頭像:<br /> <img src="@Model.headimgurl" style="width: 50%"/>(直接調用可能看不到,需要抓取) </p> </body> </html>
第三步:測試(必須在微信里面測試)
在公眾號里面調用這個鏈接,我們在圖文回復中,設置一個鏈接是指向這個授權頁面的測試一下,即:
http://ymnets.imwork.net/WC/OAuth2/Index?returnUrl=http://ymnets.imwork.net/WC/OAuth2/UserInfoCallBack
理論是只要能通過微信打開這個鏈接就好,什么方式都是可以的
注意格式:retuenUrl是校驗成功要返回的Url地址
----------------------------------演示開始--------------------------------------
成功后獲取用戶信息
----------------------------------演示結束--------------------------------------
總結
授權之后我們應該利用cookie來記錄用戶登錄狀況,下次登錄時候判斷是否有cookie來跳過授權