.netMVC企业微信网页授权+注册全局过滤器

微信网页授权

  达到效果:企业应用只能在微信中查看,在浏览器中打开企业页面,显示无权限!

原理,用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>
}
原文地址:https://www.cnblogs.com/zoumin123/p/9005132.html