之前微信的網站都是使用的是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(); }
大功告成,這種方式感覺還是有點兒不好,如果有做過類似功能的朋友,還請指點一下有沒有其他的實現方式,謝謝大家。