微信扫码登录实现

微信登录验证基于OAuth2.0

流程如下:

  1. 先申请公众号 ,然后在公众号里面配置应用的return域名
  2. 让用户通过扫码授权绑定微信号(绑定的时候就是将该用户的unioid和自己系统中的用户做一个对应关系,将unionid存下来)

具体程序流程:

A.通过初始url到微信获取登录二维码(如果是手机端则会直接弹出是否授权)url包含你的appid 和 redirect_uri(接收微信返回信息的API地址)例子:https://open.weixin.qq.com/connect/qrconnect?appid=wxXXXXXXXXXXX&redirect_uri=https%3A%2F%2Fpassport.XYZ.cn%2Fpassport2%2Flogin%3Fappid%3DCxaOne%26scope%3Duserinfo%26returnurl%3Dhttp%253A%252F%252Fdemo3.XYZ.cn%252Fauth%253Fr%253Dhttps%25253A%25252F%25252Fdemo3.XYZ.cn%25252Fme&response_type=code&scope=snsapi_login&state=XXXXa5

注意:

 redirect_uri 里面是你微信公众号中配置的网站url才行
而且网站目录里面要放一个用于验证的txt文件 

B.用户扫码登录/点击授权后,微信会返回一个appid+code回来到接收微信返回信息的API地址

C.API获取到code之后,通过appid+secret+code到微信获取该微信用户的信息,其中信息包括unionid(微信用户唯一id),还会返回一个openid 这个id是你这个应用内部针对这个微信用户的唯一id

 

D.如果正常返回unionid则表示用户登录成功,如果返回了errmsg,则失败

代码:

WechatLogin

 [Route("wechatlogin")]
        [HttpGet]
        [ResponseType(typeof(EmployeeSession))]
        public IHttpActionResult WechatLogin()
        {
            var allUrlKeyValues = ControllerContext.Request.GetQueryNameValuePairs();
            string appid = allUrlKeyValues.LastOrDefault(x => x.Key == "appid").Value;
            string state = allUrlKeyValues.LastOrDefault(x => x.Key == "state").Value;
            string code = allUrlKeyValues.LastOrDefault(x => x.Key == "code").Value;
            //根据不同的appid,获取不同的key,因pc端和手机端的appid不同
            var oauth_app_key = ConfigurationManager.AppSettings[appid];
            string send_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +
                              appid + "&secret=" + oauth_app_key + "&code=" + code + "&grant_type=authorization_code";
            //发送并接受返回值
            string result = HttpGet(send_url);
            if (result.Contains("errmsg"))
            {
                throw new Exception(result);//登录失败
            }
            try
            {
                //取到对应的unionid等信息
                Dictionary<string, object> ssoUserInfo = JsonConvert.DeserializeObject<Dictionary<string, object>>(result);
                //初始化时使用模板数据库
                var initialContext = new ApolloAppContextImp(ConfigurationManager.AppSettings["CLIENT_DB_TEMPLATE_NAME"]);
                using (var serviceContext = new ServiceContext(initialContext))
                {
                    var loginDataWeChat = serviceContext.AuthenticationService.GetCurrentLoginDataWeChat(ssoUserInfo);
                    if (null != loginDataWeChat)
                    {//已绑定,使用真实公司名称进入登录流程,并返回EmployeeSession
                        initialContext = new ApolloAppContextImp(loginDataWeChat.ClientId);
                        using (var serviceContextClient = new ServiceContext(initialContext))
                        {
                            var employeeSession = serviceContextClient.AuthenticationService.WechatLogin(ssoUserInfo, loginDataWeChat);
                            return Ok(employeeSession);
                        }
                    }
                    else
                    //未绑定,弹出公司ID,用户名,密码页面,让用户进行绑定
                    //用户输入后,mapping表添加数据
                    {
                        HttpContext.Current.Session["ssoUserInfo"] = ssoUserInfo;//暂存到session,往loginDataWeChat添加纪录的时候需要
                        var employeeSession = new EmployeeSession();
                        employeeSession.HasBeenBindWechat = false;
                        return Ok(employeeSession);
                    }
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
View Code

WechatLoginbind

[Route("wechatloginbind")]
        [HttpPost]
        [ResponseType(typeof(EmployeeSession))]
        public IHttpActionResult WechatLoginbind(UserCredentials userCredentials)
        {
            var initialContext = new ApolloAppContextImp(userCredentials.ClientName);
            //This is all we know at the moment. If the client id is wrong, it will be handled in the exception.
            try
            {
                using (var serviceContext = new ServiceContext(initialContext))
                {
                    EmployeeSession employeeSession;
                    Dictionary<string, object> ssoUserInfo = HttpContext.Current.Session["ssoUserInfo"] as Dictionary<string, object>;
                    if (serviceContext.AuthenticationService.UserLoginCheckAndBind(userCredentials, ssoUserInfo, out employeeSession))
                    {
                        return Ok(employeeSession);
                    }
                    else
                    {
                        throw new ApiException(ExceptionLevel.Normal, ExceptionCode.UnAuthorized, "You have provided the wrong credentials.Please check your entries again.");
                    }
                }
            }
            catch (ClientNotFoundException)
            {
                var appContext = new ApolloAppContextImp(userCredentials.ClientName);
                using (var serviceContext = new ServiceContext(appContext))
                {
                    throw new ApiException(ExceptionLevel.Critical, ExceptionCode.NotFound, serviceContext.GlobalizationService.GetLocalizationMessage(MessageDictionary.CLIENT_NOT_FOUND, CXA.Common.Enums.Globalization.LanguageEnum.enus, userCredentials.ClientName));
                }
            }
        }
        public static string HttpGet(string url)
        {
            using (HttpClient client = new HttpClient())
            {
                var result = client.GetAsync(url).Result;
                if (result.IsSuccessStatusCode == true)
                {
                    return result.Content.ReadAsStringAsync().Result;
                }
                else
                {
                    return "errmsg:" + result.Content.ReadAsStringAsync().Result;
                }
            }
        }
View Code

需要注意的就是pc端和手机端对微信来说属于不同的应用

posted @ 2019-04-12 18:58  龍☆  阅读(875)  评论(0编辑  收藏  举报