ASP.NET MVC5+EF6+EasyUI 后台管理系統(76)-微信公眾平台開發-網頁授權


 前言

網頁授權是:應用或者網站請求你用你的微信帳號登錄,同意之后第三方應用可以獲取你的個人信息

網上說了一大堆參數,實際很難理解和猜透,我們以實際的代碼來演示比較通俗易懂

 

配置

實現之前我們必須配置用戶授權獲取用戶信息的域名或者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>
Index
@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>
UserInfoCallback

第三步:測試(必須在微信里面測試)

在公眾號里面調用這個鏈接,我們在圖文回復中,設置一個鏈接是指向這個授權頁面的測試一下,即:

http://ymnets.imwork.net/WC/OAuth2/Index?returnUrl=http://ymnets.imwork.net/WC/OAuth2/UserInfoCallBack

理論是只要能通過微信打開這個鏈接就好,什么方式都是可以的

注意格式:retuenUrl是校驗成功要返回的Url地址

----------------------------------演示開始--------------------------------------

 

 

成功后獲取用戶信息

----------------------------------演示結束--------------------------------------

總結

授權之后我們應該利用cookie來記錄用戶登錄狀況,下次登錄時候判斷是否有cookie來跳過授權

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM