C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理

在现今很多网站里面,都使用了微信开放平台的扫码登录认证处理,这样做相当于把身份认证交给较为权威的第三方进行认证,在应用网站里面可以不需要存储用户的密码了。本篇介绍如何基于微信开放平台的扫码进行网站的登陆处理。

1、开放平台的认证

要使用网站的扫码登录处理,就需要先进行微信开放平台帐号的开发者资质认证,提交相关的资料,以及交付每年300元的认证费用。

认证后,建立相关的网站应用后,就有相关的APPID和APPSecret了,这些关键的参数就可以用来获取相关的用户信息了。

网站应用的应用详情界面如下所示。

整个开放平台感觉没有多少东西,不过需要收费认证才能使用这些功能,感觉不是很爽。

我们采用的扫码登录,需要通过开放平台获取用户的信息,因此还需要设置获取用户基本信息接口的域名,否则无法获取信息,从而会导致重定向出错。

设置域名在【接口权限】【网页账号】【网页授权获取用户基本信息】的修改入口,如下图所示。

然后在弹出的对话框里面输入授权回调的域名即可。

 这样设置就可以确保获取到用户信息了。

2、扫码登录的说明和具体使用

网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。

在进行微信OAuth2.在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:

1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;

2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;

3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

获取access_token时序图:

 

从上图我们可以大概了解整个扫码登陆的处理过程。

3、扫码登录的各个步骤处理

1)用户身份的绑定

为了实现二维码扫码登录,我们需要在现有系统里面绑定用户的微信,这样才能在用户扫码的时候,判断用户的身份从而实现自动登录的过程。

我们可以在用户管理里面进行统一设置,也可以在常规用户登录(用户名+密码)后进行设置,这个主要看我们是否需要保留用户名密码登陆这种方式。

例如可以在用户管理里面统一绑定,也就是在创建用户的时候,让用户绑定下微信,获取微信的唯一标识。

也可以在保留用户名密码的登陆方式外,让用户登陆系统后自行进行绑定微信即可。

上面的界面,就是在一个页面里面弹出一个层,然后请求二维码显示即可,如下界面代码所示。

        <div id="divWechat" class="easyui-dialog" style="width:450px;height:350px;padding:10px 20px"
             closed="true" resizable="true" modal="true" iconcls="icon-setting">
            <div>
                <h4>扫描用户二维码,进行绑定</h4>
            </div>
            <div align="center">
                <img id="imgQRcode" alt="使用微信扫码进行绑定" style="height:200px;width:auto" />
            </div>

            <div align="right">
                <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-cancel" onclick="javascript: $('#divWechat').dialog('close')">关闭</a>
            </div>
        </div>

上面的层在打开的时候,我们使用JS来动态获取二维码进行显示,具体JS代码如下所示。

    //绑定微信登陆
    function BindWechat() {
        var url = "http://www.iqidi.com/H5/BindWechat?id=@Session["UserID"]";
        url = encodeURIComponent(url);
        $("#imgQRcode").attr("src", "/H5/QR?url=" + url);
        //打开绑定窗口
        $("#divWechat").dialog('open').dialog('setTitle', '使用微信扫码进行绑定');
    }

上面的JS只是做前端的数据请求和显示,具体的QR动作Action其实就是生成扫描二维码的过程,这个二维码其实就是采用通用的方式,来构建一个指向我们绑定账号的地址,从而实现我们绑定账号的判断,二维码的生成过程如下所示。

        /// <summary>
        /// 转换二维码连接为图片格式
        /// </summary>
        /// <param name="url">二维码连接</param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult QR(string url)
        {
            //初始化二维码生成工具
            QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
            qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
            qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
            qrCodeEncoder.QRCodeVersion = 0;
            qrCodeEncoder.QRCodeScale = 4;

            //将字符串生成二维码图片
            var image = qrCodeEncoder.Encode(url, Encoding.Default);
            //保存为PNG到内存流
            MemoryStream ms = new MemoryStream();
            image.Save(ms, ImageFormat.Png);
            image.Dispose();

            return File(ms.ToArray(), "image/Png");
        }

为了实现用户的绑定,我们需要获取当前用户的身份信息,因此需要在BindWeChat的操作里面做一个转向处理,如下接口所示。

        /// <summary>
        /// 生成绑定微信的地址
        /// </summary>
        /// <returns></returns>
        public ActionResult BindWechat()

这个函数处理里面,我们需要重新定向处理,我们把它定向到BindAccount函数里面,方便获取用户的openid和其他必要的信息。

另外我们基于微信开放平台的应用,建立了一个和微信账号信息的联系,因此创建数据库信息如下所示。

也就是一个具体的开放平台应用对应着一个具体的微信账号,这样我们就可以充分利用配置进行处理了。

上面提到的BindAccount的处理的逻辑就是获取必要的信息,然后在数据库层面对身份信息进行验证,具体代码如下所示。

        /// <summary>
        /// 绑定用户微信号
        /// </summary>
        /// <param name="id">账号ID</param>
        /// <returns></returns>
        public ActionResult BindAccount()
        {
            WebAppInfo appInfo = GetWebApp(ConfigData.WebAppId);
            AccountInfo accountInfo = GetAccount(appInfo.AccountNo);

            var htResult = GetOpenIdAndUnionId(accountInfo.UniteAppId, accountInfo.UniteAppSecret);//存储openid方便使用
            string openid = htResult["openid"].ToString();
            var unionid = htResult["unionid"].ToString();
            var userid = Request.QueryString["id"];
            var state = Request.QueryString["state"];

            if (!string.IsNullOrEmpty(openid) && !string.IsNullOrEmpty(userid))
            {
                CommonResult result = BLLFactory<User>.Instance.BindUser(openid, unionid, userid.ToInt32());
                if (result.Success)
                {
                    return BindSuccess();
                }
                else
                {
                    return BindFail();
                }
            }
            else
            {
                throw new WeixinException("无法获取openid" + string.Format(", openid:{0}, userid:{1}", openid, userid));
            }
        }

在绑定的过程,我们需要考虑绑定正确账号,重复绑定其他账号,无效绑定几种情况,如果成功绑定正确账号(可多次处理结果一样),那么得到界面如下所示(这个界面的样式采用了weui的样式)。

  

2)用户的扫码登录处理

上面绑定了账号后,就可以通过扫码进行登录了,扫码回调的时候我们有自己的判断处理,扫码界面如下所示(我们在保留用户名密码登陆的方式外,增加了一个扫码登录的处理)。

如果是Bootstrap的界面效果

如果是EasyUI的界面效果

这个和前面的二维码显示规则差不多,不过他们的连接地址是不同的,这个地方用到了开放平台的接口,也就是我们前面提到开放平台认证的接口了。

上面的扫码登录的界面代码如下所示。

    <!--二维码扫描登陆的界面层-->
    <div id="divWechat" class="easyui-dialog" style="width:550px;height:500px;padding:10px 20px"
         closed="true" resizable="true" modal="true" iconcls="icon-setting">
        <div id="login_container" align="center">
        </div>

        <div align="right">
            <a href="javascript:void(0)" class="easyui-linkbutton" iconcls="icon-cancel" onclick="javascript: $('#divWechat').dialog('close')">关闭</a>
        </div>
    </div>

上面代码需要引入JS文件,并使用微信JSSDK的API进行显示的。

    <!--使用微信扫码进行登陆-->
    <script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
    <script language="javascript">

        function OpenJSLogin() {
            var obj = new WxLogin({
                id: "login_container",
                appid: "@ViewBag.appid",
                scope: "snsapi_login",
                redirect_uri: "@ViewBag.redirect_uri",
                state: "@ViewBag.state",
                style: "black",
                href: ".impowerBox .qrcode {width: 200px;}"
            });

            //打开绑定窗口
            $("#divWechat").dialog('open').dialog('setTitle', '使用微信扫码进行登陆');
        }
    </script>

这个里面的参数,如APPID就是来源我们认证后的开放平台参数。

这些信息我们在MVC控制器后面获取后绑定在ViewBag,方便界面前端的使用。

            //使用JSLogin登陆
            WebAppInfo appInfo = BLLFactory<WebApp>.Instance.FindByID(ConfigData.WebAppId);
            ArgumentValidation.CheckForNullReference(appInfo, "Web应用程序appInfo");

            if (appInfo != null)
            {
                ViewBag.appid = appInfo.OpenAppID;
                ViewBag.redirect_uri = appInfo.LoginCallBackUrl;
                ViewBag.state = ConfigData.AuthState;
            }

其中的redirect_uri是通过数据库获取的LoginCallBackUrl地址,这个地址类似如下格式:http://www.iqidi.com/H5/callback?uid=iqidiSoftware

也就是我们在开放平台处理返回后进行的回调处理。

通过开放平台的APPID和APPSecret,我们可以获取到对应的接口调用凭证,然后根据接口凭证,以及openid,获得用户的公众平台统一的UnionID,这个标识是我们用户的唯一标识,代码如下所示。

                var result = baseApi.GetAuthToken(appid, appsecret, code);
                if (result != null && !string.IsNullOrEmpty(result.openid))
                {
                    openid = result.openid;
                    var unionResult = baseApi.GetSnsapiUserInfo(result.access_token, result.openid);

                    ht.Add("openid", openid);
                    ht.Add("unionid", unionResult != null ? unionResult.unionid : "");
                }

有了unionid我们就可以根据这个标识在我们的用户数据库里面查找对应的用户,如下代码所示。

            //开放平台的OpenID,不是公众号的OpenID,需要转换为unionid
            if (!string.IsNullOrEmpty(openid) && !string.IsNullOrEmpty(unionid))
            {
                UserInfo userInfo = BLLFactory<User>.Instance.FindByUnionId(unionid);

然后判断我们去到的用户信息是否正确,如下代码所示

                if (userInfo != null)
                {
                    CommonResult loginResult = CheckLogin(userInfo.Name);
                    if (!loginResult.Success)
                    {
                        LogHelper.Info(string.Format("用户登陆不成功,{0}", loginResult.ErrorMessage));
                    }

                    //登陆成功后的重定向地址
                    var url = appInfo.HomeUrl;  //例如:http://www.iqidi.com/Home
                    return Redirect(url);
                }

如果不成功,那么我们定向到指定的界面即可。

            //如不成功,最后都统一提示信息
            ViewBag.Error = "获取信息失败,登陆错误";
            return View("LoginError");

如果我们登陆成功后,需要设置一些Session信息或者Cookie信息,那么就可以通过CheckLogin函数进行处理即可。

以上就是我们结合微信开放平台实现微信扫码登录的过程,其中整个过程就是用到了下面几个过程。

1)使用JSSDK的脚本实现扫码获取code

JS微信登录主要用途:网站希望用户在网站内就能完成登录,无需跳转到微信域下登录后再返回,提升微信登录的流畅性与成功率。 网站内嵌二维码微信登录JS实现办法:

步骤1:在页面中先引入如下JS文件(支持https):

<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>

步骤2:在需要使用微信登录的地方实例以下JS对象:

                          var obj = new WxLogin({
                              id:"login_container",
                              appid: "",
                              scope: "",
                              redirect_uri: "",
                              state: "",
                              style: "",
                              href: ""
                            });

2) 第二步:通过code获取access_token

通过code获取access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

3)第三步:通过access_token调用接口

获取access_token后,进行接口调用,

对于接口作用域(scope),能调用的接口有以下:

授权作用域(scope) 接口 接口说明
snsapi_base /sns/oauth2/access_token 通过code换取access_token、refresh_token和已授权scope
/sns/oauth2/refresh_token 刷新或续期access_token使用
/sns/auth 检查access_token有效性
snsapi_userinfo /sns/userinfo 获取用户个人信息

其中snsapi_base属于基础接口,若应用已拥有其它scope权限,则默认拥有snsapi_base的权限。使用snsapi_base可以让移动端网页授权绕过跳转授权登录页请求用户授权的动作,直接跳转第三方网页带上授权临时票据(code),但会使得用户已授权作用域(scope)仅为snsapi_base,从而导致无法获取到需要用户授权才允许获得的数据和基础功能。

4)获取信息在回调界面中进行登录前处理

通过上面接口,我们可以获得相应的用户身份信息,因此可以结合我们用户数据库进行用户身份的认定和处理,并设置必要的Session或者Cookie信息等,最后定位到我们的应用主界面即可。

本文转自博客园伍华聪的博客,原文链接:C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理,如需转载请自行联系原博主。

时间: 2024-09-10 15:47:57

C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理的相关文章

C#开发微信门户及应用(46)-基于Bootstrap的微信门户应用管理系统功能介绍

在前面介绍很多的微信框架,基本上都采用EasyUI的界面来搭建的微信框架,如随笔<C#开发微信门户及应用(8)-微信门户应用管理系统功能介绍>介绍的一样,不过随着微信的H5应用越来越多,因此转换为更适合做H5页面应用框架的Bootstrap开发框架,本文介绍的整个微信模块都是基于Bootstrap的应用. 微信开发包括公众号.企业号.微信小程序等方面的开发内容,需要对腾信的微信API接口进行封装:包括事件.菜单.订阅用户.多媒体文件.图文消息.消息群发.微信支付和企业红包.摇一摇设备.语义理解

C#开发微信门户及应用(45)--微信扫码登录

在前面随笔<C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理>介绍了基于微信开放平台接口实现的微信扫码直接登录的过程.本篇介绍对扫码登录的一些改进和处理,以便更方便应用在实际项目中. 1.扫码登录配置处理 在我前面的随笔扫码登录处理中,介绍了账号登陆和扫码登录并存的情况,有时候我们可能想只是允许用户扫码登录即可,也就是不需要账号登陆,这种情况我们可以通过进行配置实现处理. 例如我在一个基于微信的系统应用里面,通过配置实现了仅仅允许扫码登录的效果. 也就是我们可以根据配置,因此其

C#开发微信门户及应用(14)-在微信菜单中采用重定向获取用户数据

原文:C#开发微信门户及应用(14)-在微信菜单中采用重定向获取用户数据 我曾经在系列文章中的<C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍>中介绍了微信菜单里面的重定向操作,通过这个重定向操作,我们可以获取一个code值,然后获取用户的openID,进而就能获取到更多的用户信息,这个在会员信息的场景里面用的很多,本篇介绍在网站中迅速配置这样的菜单链接,并介绍如何在后台获取相关的用户信息,实现页面数据个性化的展现操作. 我们知道,微信的自定义菜单分为两大类,分别对应Click类

C#开发微信门户及应用(48) - 在微信框架中整合CacheManager 缓存框架

 在我们的很多框架或者项目应用中,缓存在一定程度上可以提高程序的响应速度,以及减轻服务器的承载压力,因此在一些地方我们都考虑引入缓存模块,这篇随笔介绍使用开源缓存框架CacheManager来实现数据的缓存,在微信开发框架中,我们有一些常用的处理也需要应用到缓存,因此本随笔以微信框架为例介绍缓存的实际使用,实际上,在我们很多框架中,如混合式开发框架.Web开发框架.Bootstrap开发框架中,这个模块都是通用的. 1.框架的缓存设计 在我们的微信开发框架中,缓存作为数据库和对外接口之间的一个分

C#开发微信门户及应用(39)--使用微信JSSDK实现签到的功能

随着微信开逐步开放更多JSSDK的接口,我们可以利用自定义网页的方式来调用更多微信的接口,实现我们更加丰富的界面功能和效果,例如我们可以在页面中调用各种手机的硬件来获取信息,如摄像头拍照,GPS信息.扫描二维码等等,本篇介绍如何利用这些JSSDK接口实现签到的功能,其中签到需要报送地理坐标和地址,调用摄像头实时拍照,以及获取当前用户的相关信息等等. 1.JSSDK的说明 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包.通过使用微信JS-SDK,网页开发者可借助微信高

C#开发微信门户及应用(40)--使用微信JSAPI实现微信支付功能

在我前面的几篇博客,有介绍了微信支付.微信红包.企业付款等各种和支付相关的操作,不过上面都是基于微信普通API的封装,本篇随笔继续微信支付这一主题,继续介绍基于微信网页JSAPI的方式发起的微信支付功能实现,微信的JSAPI相对于普通的API操作,调试没有那么方便,而且有时候有些错误需要反复核实.本篇随笔基于实际的微信网页支付案例,对微信JSAPI的支付实现进行介绍. 1.微信JS-SDK的知识 在我前面<C#开发微信门户及应用(39)--使用微信JSSDK实现签到的功能>介绍的内容里面,有介

数据库-微信扫码登录的服务端编写思路

问题描述 微信扫码登录的服务端编写思路 各位大神好,小菜鸟第一次提问,还望大家多多关照. 问题如下: 我们都知道网页版的微信是通过扫码登录的,网页端和服务端建立一个长连接,手机扫码后后将登录许可传到服务端,服务端收到请求后将用户信息网页通过长连接返回给网页端.大概思路如下图: 那么问题来了,在长连接存在的这段时间里,服务端是如何得知手机发送了登录许可?如果是将许可存入表,那服务端要想知道值更新,不是得不断查询数据库吗?还是有其他方法? 期待大神们的精彩回答! 解决方案 这是个很好的问题,涉及到系

为了安全微信公众平台将逐步开启帐号扫码登录

4月5日消息,为了公众号的安全微信公众平台将逐步开启帐号扫码登录.帐号安全与公众号运营者的利益密切相关,一旦帐号密码泄露,有可能被盗号者利用来发送欺诈等恶意信息,对运营者及平台都造成巨大的损失. 为了加强公众号的帐号安全,微信公众平台于2014年推出了安全中心,用户可通过安全中心开启保护.开启提醒.开启保护后,即使盗号者获取到帐号密码,也无法登录公众号进行下一步操作,提高了帐号的安全性. 部分用户安全意识仍较薄弱,近期平台对存在盗号风险的帐号开启登录保护后,运营者仍进行了关闭,盗号者仍能恶意使用

兼顾门户与大数据才是开放平台出路

中介交易 SEO诊断 淘宝客 云主机 技术大厅 前几日我们公司的产品负责人说企业和产品都必须在合适的时间点"挥刀自宫",这让黑苹果博客联想起<定位>里面关于福特汽车舍弃一些看上去还在为公司带来业务的产品线,而专注于自己更擅长的部分,最后把公司市值达到另一个顶峰的案例.而在我们所关注的互联网行业,当下有一个热词big data,我想大家一定觉得这又是个被说滥了的词,言必说云计算,观点一定有大数据,如果品评个时事不说这俩词,都表示不敢表达,outman.对于这样的想法,一直持有