ASP.NET MVC 支持微信OpenId登陆

  之前微信的网站都是使用的是identity来做用户登录的,用户都是要每次输入用户账号和密码。然后identity把用户信息保存在本地一段时间。现在是需要当用户在登录的时候绑定当前的微信账户的OpenId,通过OpenId来获取用户信息实现自动登录。

  在用户进入Login这个Action之前,获取到OpenId,判断该OpenId是否绑定用户信息,如果绑定则自动登陆,并返回redirectUrl。否则把OpenId保存到Cookie,然后跳转到LoginAction,在登录验证成功之后把OpenId绑定到该用户信息上。继承实现AuthorizeAttribute,

  

    public class WXFilterAttribute : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            string userAgent = httpContext.Request.UserAgent;
            if (userAgent.IndexOf("MicroMessenger") <= -1)//不是微信浏览器
            {
                return true;
            }
             
            if (!httpContext.User.Identity.IsAuthenticated)
            {
                ApplicationSignInManager SignInManager = httpContext.GetOwinContext().Get<ApplicationSignInManager>();
                ApplicationUserManager UserManager = httpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
                string appid = string.Empty;
                string secret = string.Empty;

                
                appid = WxPayConfig.APPID;
                secret = WxPayConfig.APPSECRET;

                var code = httpContext.Request["Code"];
                string returnUrl = HttpUtility.UrlDecode(httpContext.Request["ReturnUrl"] ?? "/");


                if (string.IsNullOrEmpty(code))
                {                    
                    string host = httpContext.Request.Url.Host;
                    string path = httpContext.Request.Path;
                    string redirectUrl = "http://" + host + path + "?ReturnUrl=" + HttpUtility.UrlEncode(returnUrl);//重定向的url,这里不需要进行编码,在后面会自己编码
                    try
                    {
                        //todo:通过微信获取2.0授权的url
                        string url = GetAuthorizeUrl(appid, redirectUrl, "state", "snsapi_base");
                        
                        httpContext.Response.Redirect(url);
                    }
                    catch (System.Exception ex)
                    {
#if DEBUG
                        httpContext.Response.Write("构造网页授权获取code的URL时出错,错误是:" + ex.Message);
                        httpContext.Response.End(); 
#endif
                    }
                }
                else
                {
                    var client = new System.Net.WebClient();
                    client.Encoding = System.Text.Encoding.UTF8;
                    string url = GetAccessTokenUrl(appid, secret, code);
                    var data = client.DownloadString(url);
                    var obj = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
                    string accessToken;
                    if (!obj.TryGetValue("access_token", out accessToken))
                    {
#if DEBUG
                        httpContext.Response.Write("构造网页授权获取access_token的URL时出错");
                        httpContext.Response.End();
#endif
                    }
                    var openid = obj["openid"];
                    Utils.WidgetCode.ServerInfo.SetCookies("WXopenid", openid, DateTime.MinValue);
                    
                    var existUser = UserManager.Users.FirstOrDefault(p => p.OpenId == openid);
                    if (existUser != null)
                    {
                        SignInManager.SignInAsync(existUser, false, false);
                        httpContext.Response.Redirect(returnUrl);
                    }
                }
            }
            return true;
        }
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
            if (filterContext.HttpContext.Response.StatusCode == 401)
            {
                filterContext.Result = new RedirectResult("/403.htm");//跳转异常页面
            }
        }

        //扩展
        public string GetAuthorizeUrl(string appId, string redirectUrl, string state, string scope, string responseType = "code")
        {
            if (!string.IsNullOrEmpty(redirectUrl))
            {
                redirectUrl = HttpUtility.UrlEncode(redirectUrl, System.Text.Encoding.UTF8);
            }
            else
            {
                redirectUrl = null;
            }
            object[] args = new object[] { appId, redirectUrl, responseType, scope, state };
            return string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type={2}&scope={3}&state={4}#wechat_redirect", args);
        }
        public string GetAccessTokenUrl(string appId, string secret, string code, string grantType = "authorization_code")
        {
            object[] args = new object[] { appId, secret, code, grantType };
            string requestUri = string.Format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type={3}", args);
            //return GetAccessTokenInfo(_httpClient.GetAsync(requestUri).Result.Content.ReadAsStringAsync().Result);
            return requestUri;
        }
    }

  然后在LoginAction上添加Attribute

  

        [WXFilterAttribute]
        public ActionResult Login()
        {

            return View();
        }

    大功告成,这种方式感觉还是有点儿不好,如果有做过类似功能的朋友,还请指点一下有没有其他的实现方式,谢谢大家。

 

ASP.NET MVC 支持微信OpenId登陆

上一篇:iOS 模仿微信的照片选择器


下一篇:微信企业号开发[三]——调用微信接口