之前微信的网站都是使用的是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(); }
大功告成,这种方式感觉还是有点儿不好,如果有做过类似功能的朋友,还请指点一下有没有其他的实现方式,谢谢大家。