• 微信扫码登录实现


    微信登录验证基于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端和手机端对微信来说属于不同的应用

  • 相关阅读:
    [Linux] VIM Practical Note
    [JAVA] JAVA 文档注释
    [JAVA] JAVA 类路径
    [JAVA] JAVA JDK 安装配置
    [Dynamic Language] Python定时任务框架
    [DataBase] MongoDB (8) 副本集
    [DataBase] MongoDB (7) MongoDB 索引
    [DabaBase] MongoDB (6) 启动、停止、相关系统配置及安全性设置
    [Dynamic Language] 用Sphinx自动生成python代码注释文档
    [JAVA] java class 基本定义 Note
  • 原文地址:https://www.cnblogs.com/tylertang/p/10697899.html
Copyright © 2020-2023  润新知