.netMVC企業微信網頁授權+註冊全局過濾器
阿新 • • 發佈:2018-05-07
glob for init cgi http 一個 使用 QQ == ))
微信網頁授權
達到效果:企業應用只能在微信中查看,在瀏覽器中打開企業頁面,顯示無權限!
原理,用session記錄用戶,如果用戶已經通過微信授權,記錄@Session["UserId"],如果用戶沒有登錄,則采用微信頁面跳轉的Code去換取UserId,如果能成功換取,則存入session,並登錄成功。
邏輯圖如下:
(小插曲:1 微信頁面重定向時,會發送多個請求,導致只能使用一次的Code失效 40029 報錯
處理邏輯是,采用同步鎖,頁面第一次跳轉到我們的服務器時,把code存入session,並且對這段代碼加鎖,如果微信又發一個請求,先對比session中的Code,如果有了,則不再使用第二個code(因為微信頁面授權code只能使用一次
private static object locker = new object(); //同步鎖
try { lock (locker) { if (Session["UserId"] == null)// 1 如果用戶未登錄 { if (!string.IsNullOrWhiteSpace(code) && Session["Code"] != (object)code)//2 有Code 參數,並且Code參數是第一次 { //處理邏輯Star Session["Code"] = code;//把Code記錄session var userid = WechatCheckCode(code).UserId; //調用微信接口,獲取用戶信息 if(string.IsNullOrWhiteSpace(userid)) { response.Redirect("/Admin/Admin/Error?msg=xxxxxx"); } Session["UserId"] = userid;//用戶寫入session //處理邏輯End } else { response.Redirect("/Admin/Admin/Error?msg=xxxxxx"); } } } } catch { response.Redirect("/Admin/Admin/Error?msg=xxxxxx"); }
(小插曲:2 為了讓所有的Controller都先進行一次校驗,采用全局過濾器)
// 1在Global中添加全局過濾器 GlobalFilters.Filters.Add(new AuthAttribute()); //2 AuthAttribute 過濾器邏輯 public class AuthAttribute : AuthorizeAttribute { private readonly string WeChatUrl = ConfigurationManager.AppSettings["WeChatUrl"]; private static object locker = new object();//使用同步鎖,防止微信一次跳轉多次請求 public override void OnAuthorization(AuthorizationContext filterContext) { var path = filterContext.HttpContext.Request.Path; if (!path.ToLower().StartsWith("/admin/admin/error")) { var response = filterContext.HttpContext.Response; var request = filterContext.HttpContext.Request; var Session = filterContext.HttpContext.Session; var code = request.Params["code"]; try { lock (locker) { if (Session["UserId"] == null) { if (!string.IsNullOrWhiteSpace(code) && Session["Code"] != (object)code)//1 判斷session裏面是否有用戶 { Session["Code"] = code; var userid = WechatCheckCode(code).UserId; if (string.IsNullOrWhiteSpace(userid)) { response.Redirect("/Admin/Admin/Error?msg=xxxxxx"); } Session["UserId"] = userid; } else { response.Redirect("/Admin/Admin/Error?msg=xxxxxx"); } } } } catch { response.Redirect("/Admin/Admin/Error?msg=xxxxxx"); } } } //微信檢查Code private Wechat_UserModel WechatCheckCode(string code) { Wechat_UserModel resultBack = null; string WeChat_Address = WeChatUrl; var url = WeChat_Address + "api/ApiGetUser/GetUser?code=" + code; var client = new HttpClient(); var result = client.GetAsync(url).Result; if (result.IsSuccessStatusCode) { LogManager.WriteLog("code日誌", string.Format("【獲取的用戶數據】:{0}", result.Content.ReadAsStringAsync().Result)); var json = result.Content.ReadAsStringAsync().Result; resultBack = JsonConvert.DeserializeObject<Wechat_UserModel>(json);//Json 反序列化成對象 } return resultBack; }
(小插曲:3 webApi,返回動態Json字符串是,不能直接返回string,應該 返回 HttpResponseMessage)
// 1 微信網頁授權根據Code,獲取用戶信息 public HttpResponseMessage GetUser(string code) { string access_token = wxAccess_token.IsExistAccess_Token(wxEnum.供應商系統); //獲取access_token var json = UserAdminAPI.GetWebUser(access_token, code);//調用微信接口,返回用戶JSon字符串 return new HttpResponseMessage() { Content = new StringContent(json, Encoding.UTF8, "application/json") }; }
/// <summary> /// 2 根據code獲取成員信息 /// </summary> /// <returns></returns> public static string GetWebUser(string access_token, string code) { var url = string.Format("https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token={0}&code={1}", access_token, code); var client = new HttpClient(); var result = client.GetAsync(url).Result; if (!result.IsSuccessStatusCode) return null; return result.Content.ReadAsStringAsync().Result; }
4 前端頁面資源
效果圖:
1 母版頁 @RenderBody()子頁面插入的位置,@RenderSection,子頁面自定義填充位置 @{ Layout = null; } <!doctype html> <html> <head> <meta charset="utf-8"> <title>供應商移動端</title> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0"> <link rel="stylesheet" href="~/Content/style/weui.css" /> <link rel="stylesheet" href="~/Content/style/weui2.css" /> <link rel="stylesheet" href="~/Content/style/weui3.css" /> <script src="~/Content/zepto.min.js"></script> @RenderSection("Head", required: false) </head> <body ontouchstart style="background-color: #f8f8f8;"> <div class="weui_tab tab-bottom"> </div> <div class="weui_tabbar "> <a href="/admin/admin/Index_mobile" class="weui_tabbar_item weui_bar_item_on"> <div class="weui_tabbar_icon"> <img src="~/Content/images/icon_nav_button.png" alt=""> </div> <p class="weui_tabbar_label">首頁</p> </a> </div> @RenderBody() //子頁面插入的地方 @RenderSection("Dialog", required: false) </body> </html> @RenderSection("Foot", required: false) 2 首頁 @{ ViewBag.Title = "Index_mobile"; Layout = "~/Views/Shared/_LayMobile.cshtml"; } <div class="page-hd"> <h1 class="page-hd-title"> 供應商系統 </h1> <p class="page-hd-desc">用戶:@Session["UserId"]</p> </div> <div class="weui_grids"> <a href="/admin/Reconciliations/Index" class="weui_grid js_grid"> <div class="weui_grid_icon"> <img src="~/Content/images/icon_nav_dialog.png" alt=""> </div> <p class="weui_grid_label"> 供應商對賬 </p> </a> <a href="/admin/Purchase/Index" class="weui_grid js_grid"> <div class="weui_grid_icon"> <img src="~/Content/images/icon_nav_cell.png" alt=""> </div> <p class="weui_grid_label"> 采購單查詢 </p> </a> </div> @section Foot{ <script> Zepto(function ($) { //$.ajax({ // type: ‘POST‘, // url: ‘WechatLogin‘, // dataType: ‘json‘, // success: function (data) { // alert(data.msg); // console.log(data); // }, // error: function (xhr, type) { // alert(‘Ajax error!‘) // } //}) }) </script> }
.netMVC企業微信網頁授權+註冊全局過濾器