.NET C#使用微信公众号登录网站

适用于:本文适用于有一定微信开发基础的用户  

引言:
花了300大洋申请了微信公众平台后,发现不能使用微信公众号登录网站(非微信打开)获得微信帐号。仔细研究后才发现还要再花300大洋申请微信开放平台才能接入网站的登录。于是做为屌丝程序员的我想到了自己做一个登录接口。

工具和环境:
1. VS2013 .net4.0 C# MVC4.0 Razor
2.插件
A. Microsoft.AspNet.SignalR;时时获取后台数据
B.Gma.QrCodeNet.Encoding;文本生成二维码

实现的目标
1. 在电脑上打开网站登录页,提示用户使用微信扫描登录确认。
2.用户通过微信扫描确认后,电脑自动收到确认信息跳转到网站主页。

原理分析
 1.SignalR是一个神奇的工具,能从浏览器A发送信息到服务器,服务器自动推送消息到指定的浏览器B。那么我的计划是用电脑的浏览器打开登录页,生成一个二维码(内容为带有微信公众平台网页用户受权的网址),用微信的描码功能打开这个网站。将获取的微信用户OPENID通过SignalR发送到电脑浏览器,实现登录功能

 实现过程
1.微信公从平台的注册和权限(略过...)
2.VS2013中新建MVC网站,我用的环境为.NET4.0 C# MVC4.0  Razor引擎(个人习惯)。

3.安装 SignalR
 VS2013 点击工具 ==> 库程序包管理器 ==> 程序包管理控制台

输入以下命令:
 Install-Package Microsoft.AspNet.SignalR -Version 1.1.4

.net4.0 Mvc4环境下建议安装1.1.4高版本安装不上

安装 SingnalR成功

设置SignalR

var config = new Microsoft.AspNet.SignalR.HubConfiguration();
 config.EnableCrossDomain = true;
 RouteTable.Routes.MapHubs(config);

新建一个类 PushHub.cs

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WD.C.Utility
{
 /// <summary>
 /// 标注Single javascription要连接的名称
 /// </summary>
 [HubName("pushHub")]
 public class PushHub : Hub
 {
 /// <summary>
 /// 临时保存请求的用户
 /// </summary>
 static Dictionary<string, string> rlist = new Dictionary<string, string>();

 /// <summary>
 /// 登录请求的用户;打开Login页执行本方法,用于记录浏览器连接的ID
 /// </summary>
 public void ruserConnected()
 {
 if (!rlist.ContainsKey(Context.ConnectionId))
 rlist.Add(Context.ConnectionId, string.Empty);

 //Client方式表示对指定ID的浏览器发送GetUserId方法,浏览器通过javascrip方法GetUserId(string)得到后台发来的Context.ConnectionId
 Clients.Client(Context.ConnectionId).GetUserId(Context.ConnectionId);
 }
 /// <summary>
 /// 实际登录的用户
 /// </summary>
 /// <param name="ruser">请求的用户ID</param>
 /// <param name="logUserID">微信OPENID</param>
 public void logUserConnected(string ruser, string logUserID)
 {
 if (rlist.ContainsKey(ruser))
 {
 rlist.Remove(ruser);

 //Client方式表示对指定ID的浏览器发送GetUserId方法,浏览器通过javascrip方法userLoginSuccessful(bool,string)得到后台发来的登录成功,和微信OPENID
 Clients.Client(ruser).userLoginSuccessful(true, logUserID);
 }
 }

 }
}

新建一个MVC控制器"LoginController.cs",这个不会看别的教程;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WD.C.Controllers
{
 public class LoginController : Controller
 {
 //
 // GET: /Login/

 /// <summary>
 /// 登录主页,电脑端打开
 /// </summary>
 /// <returns></returns>
 public ActionResult Index()
 {
 /*参考 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN
 *1.URL用于生成二维码给微信扫描
 *2.格式参考微信公从平台帮助
 * https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
 *3.REDIRECT_URI内容为返回地址,需要开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名
 *4.REDIRECT_URI应回调到WxLog页并进行URLEncode编码,如: redirect_uri=GetURLEncode("http://你的网站/Login/WxLog?ruser="); ruser为PushHub中的Context.ConnectionId到View中配置
 *
 */
 ViewBag.Url = string.Format("https://open.weixin.qq.com/connect/oauth2/authorize?appid={0}&redirect_uri={1}&response_type=code&scope=snsapi_base&state={2}#wechat_redirect", B.Helper.AppID, GetURLEncode("http://你的网站/Login/WxLog?ruser="), Guid.NewGuid());
 return View();
 }

 /// <summary>
 /// 登录确认页,微信端打开
 /// </summary>
 /// <param name="ruser"></param>
 /// <returns></returns>
 public ActionResult WxLog(string ruser)
 {
//使用微信登录
if (!string.IsNullOrEmpty(code))
 {
 string loguser= B.Helper.GetOpenIDByCode(code);
 Session["LogUserID"] =loguser;
 ViewBag.LogUserID = loguser;
 }

 ViewBag.ruser = ruser;
 return View();

 }

 }
}

控制器 "QRController.cs"用于文本生成二维码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WD.C.Controllers
{
 public class QRController : Controller
 {
 //
 // GET: /QR/

 public ActionResult Index()
 {
 return View();
 }
 /// <summary>
 /// 获得2维码图片
 /// </summary>
 /// <param name="str"></param>
 /// <returns></returns>
 public ActionResult GetQRCodeImg(string str)
 {
 using (var ms = new System.IO.MemoryStream())
 {

 string stringtest = str;
 GetQRCode(stringtest, ms);
 Response.ContentType = "image/Png";
 Response.OutputStream.Write(ms.GetBuffer(), 0, (int)ms.Length);
 System.Drawing.Bitmap img = new System.Drawing.Bitmap(100, 100);
 img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
 Response.End();
 return File(ms.ToArray(), @"image/jpeg");
 }
 }
 private static bool GetQRCode(string strContent, System.IO.MemoryStream ms)
 {

 Gma.QrCodeNet.Encoding.ErrorCorrectionLevel Ecl = Gma.QrCodeNet.Encoding.ErrorCorrectionLevel.M; //误差校正水平
 string Content = strContent;//待编码内容
 Gma.QrCodeNet.Encoding.Windows.Render.QuietZoneModules QuietZones = Gma.QrCodeNet.Encoding.Windows.Render.QuietZoneModules.Two; //空白区域
 int ModuleSize = 12;//大小
 var encoder = new Gma.QrCodeNet.Encoding.QrEncoder(Ecl);
 Gma.QrCodeNet.Encoding.QrCode qr;
 if (encoder.TryEncode(Content, out qr))//对内容进行编码,并保存生成的矩阵
 {
 var render = new Gma.QrCodeNet.Encoding.Windows.Render.GraphicsRenderer(new Gma.QrCodeNet.Encoding.Windows.Render.FixedModuleSize(ModuleSize, QuietZones));
 render.WriteToStream(qr.Matrix, System.Drawing.Imaging.ImageFormat.Png, ms);
 }
 else
 {
 return false;
 }
 return true;
 }
 }
}

视图 开启SignalR
  var chat = $.connection.pushHub;
        $.connection.hub.start().done(function () {
             chat.server.ruserConnected();
        });

$.connection.pushHub对应

chat.server.ruserConnected();对应

表示调用"pushHub"运行后执行 runserConnected方法,在临时表中增加当前浏览器的ConnectionID

chat.client.getUserId = function (ruserid)
{

  //二维码生成的文本
$("#loga").attr("src", "@ViewBag.Url" + ruserid);
}

表示台后数据 
收到数据后返回到游览器

chat.client.userLoginSuccessful = function (r, userid) {
 if (r) {
 $.post("/Login/AddSession/", { userid: userid }, function (r2) {
 if (r2) {
 location.href = "/Home/";
 }
 })
 }
 };

用户通过微信登录后

接收微信OpenID  
 $.post("/Login/AddSession/", { userid: userid }, function (r2) {
if (r2) {
location.href = "/Home/";
}
})

执行 Post到后台增加登录信息,成功后转到/Home/主页

/// <summary>
 /// 保存微信确认登录后返回的OPENID,做为网站的Session["LogUserID"]
 /// </summary>
 /// <param name="userid"></param>
 /// <returns></returns>
 public JsonResult AddSession(string userid)
 {
 Session["LogUserID"] = userid;
 return Json(true);
 }

Login/WxLog.cshtml 本页在微信上打开

@{
 ViewBag.Title = "WxLog";
}
<script src="~/Scripts/jquery.signalR-1.1.4.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
 $(function () {
 //连接SignalR pushHab
 var chat = $.connection.pushHub;
 //启动
 $.connection.hub.start().done();

 $("#btnLog").click(function () {
 //登录,发送信息到服务器
 chat.server.logUserConnected("@ViewBag.ruser","@ViewBag.LogUserID");
 });
 });
</script>
<h2>WxLog</h2>

<a href="#" id="btnLog">登录</a>

@{
 ViewBag.Title = "Index";
}
 @Scripts.Render("~/bundles/jquery")
<script src="~/Scripts/jquery.signalR-1.1.4.min.js"></script>
<script src="~/signalr/hubs"></script>

<script type='text/javascript'>
 $(function () {
 var chat = $.connection.pushHub;
 $.connection.hub.start().done(function () {
 chat.server.ruserConnected();
 });
 chat.client.getUserId = function (ruserid)
 {
 $("#loga").attr("src", "@ViewBag.Url" + ruserid);
 }
 chat.client.userLoginSuccessful = function (r, userid) {
 if (r) {
 location.href = "/Home/";
 })
 }
 };
 });

</script>
<header>
 <a href="~/Home/" class="iconfont backIcon"><</a>
 <h1>用户登录</h1>
</header>
<div style="height:1rem;"></div>
请使用微信登录扫描以下二维码生产图片
<div>
 <img id="loga" src="#" width="90%" />
</div>

GetOpenIDByCode(code)方法

参考 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN

对于已关注公众号的用户,如果用户从公众号的会话或者自定义菜单进入本公众号的网页授权页,即使是scope为snsapi_userinfo,也是静默授权,用户无感知。

具体而言,网页授权流程分为四步:
1、引导用户进入授权页面同意授权,获取code  
2、通过code换取网页授权access_token(与基础支持中的access_token不同)  
3、如果需要,开发者可以刷新网页授权access_token,避免过期  
4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

 public static string GetOpenIDByCode(string code)
 {
 string url =string.Format( "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code",AppID,AppSecret, code);
 using (System.Net.WebClient client = new System.Net.WebClient())
 {
 string tempstr= client.DownloadString( url);
 var regex= new Regex(@"\""openid\"":\""[^\""]+?\"",", RegexOptions.IgnoreCase);
 string tempstr2= regex.Match(tempstr).Value;
 return tempstr2.Substring(10, tempstr2.Length - 12);
 }
 }

精彩专题分享:ASP.NET微信开发教程汇总,欢迎大家学习。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#.NET实现网页自动登录的方法

    本文实例讲述了C#.NET实现网页自动登录的方法.分享给大家供大家参考.具体如下: 用C#语言编写一个Windows Form应用程序,实现自动登录一个特定的页面. 下面以自动登录:http://localhost/Web/Login.aspx 作为例子,讲解如何模拟手工输入用户名密码并点击登录,实现自动登录. 新建一个C#应用程序,给应用程序起个名字,如AutoLogin,在窗体中添加一个TextBox.Button,及WebBrowser控件,并为WebBrowser控件添加webBrows

  • div弹出层的ajax登录(Jquery版+c#)

    页面初始化,界面如图所示: Server name文本框获取焦点时候,界面如图所示(这里可以改成你登录的验证码): 可以加载SQL Server服务列表,也是我的简易SQL查询分析器评论中静夜妙思给予的方法,非常感谢! 加载列表如下图所示: 可以随意地点击添加到Server name中,登录时截图所示: 文本框验证都写好了!还有Authentication验证方式,windows验证下面Login,Password文本框禁掉!由于时间原因,不上图了 demo.html(全部前台代码,js/css

  • c#通过进程调用cmd判断登录用户权限代码分享

    复制代码 代码如下: /// <summary>/// 应用程序的主入口点./// </summary>[STAThread]static void Main(){ if (RunCmd("net localgroup administrators").IndexOf(System.Environment.UserName) >= 0)    { //顺利执行.    }    else    {        //报错提示系统不是管理员用户登录,容易导致

  • C# Winform中实现主窗口打开登录窗口关闭的方法

    在使用C#进行Winform编程时,我们经常需要使用一个登录框来进行登录,一旦输入的用户名密码登录成功,这时登录窗口应该关闭,而且同时打开主程序窗口.该如何来实现呢? 乍一想,很简单啊,打开主窗口就用主窗口的Show()方法,而关闭登录窗口就用登录窗口的Close()方法即可.即代码如下: Program.cs中代码: 复制代码 代码如下: Application.Run(new FormLogin()); 登录窗口(FormLogin)代码: 复制代码 代码如下: private void b

  • asp.net c#采集需要登录页面的实现原理及代码

    首先说明:代码片段是从网络获取,然后自己修改.我想好的东西应该拿来分享. 实现原理:当我们采集页面的时候,如果被采集的网站需要登录才能采集.不管是基于Cookie还是基于Session,我们都会首先发送一个Http请求头,这个Http请求头里面就包含了网站需要的Cookie信息.当网站接收到发送过来的Http请求头时,会从Http请求头获取相关的Cookie或者Session信息,然后由程序来处理,决定你是否有权限访问当前页面. 好了,原理搞清楚了,就好办了.我们所要做的仅仅是在采集的时候(或者

  • C#实现登录窗口(不用隐藏)

    (1).在程序入口处,打开登录窗口 复制代码 代码如下: static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Form form = new login(); form.Show(); Application.Run(); }   复制代码 代码如下: private void button1_Click(object sender

  • C#中登录窗体和欢迎窗体关闭方法分析

    本文实例分析了C#中登录窗体和欢迎窗体关闭方法.分享给大家供大家参考.具体分析如下: 在c#的winform编程中,我们经常会做登录窗体或欢迎窗体,并把他们作为启动窗体.   但是,我们有可能会遇到一些问题.   请看下面的代码: 复制代码 代码如下: private void button1_Click(object sender, EventArgs e) {     this.Close();     new Form2().Show(); } 这段代码想让form1中的button1在点

  • c#通用登录模块分享

    // 举个例子:一个网站有用户系统.商家系统.网站后台3个系统 //可以分3个userType, user ,shop , system //网站后台一般都有角色,如admin,employee //那么网站的角色就有 user,shop,admin,employee,但是admin和employee在一个客户端是不能同时登陆的,所以他们是同一类用户(system) 使用方法: 1.添加一个类LoginUser.cs 代码如下: 代码: namespace MVCCommonAuth { #re

  • C#实现简单的登录界面

    首先我们来看一个简单的制作过程 打开visual 2010,新建窗体,既然是登录窗口,那么就不让它出现最大化.最小化以及拖拉大小功能(上一节已经提到过怎么设置大小),如图所示,甚至窗体的Text属性值为"登录窗口",大小随意. 创建窗体之后就开始界面详细的组件布局了,主要是在左边拖拉控件,然后放到窗体中去,定义属性值.这些都比较简单. 到了代码响应阶段,双击登录按钮,进入代码视图: private void button1_Click(object sender, EventArgs

  • C#实现的三种模拟自动登录和提交POST信息的方法

    本文实例讲述了C#实现的三种模拟自动登录和提交POST信息的方法.分享给大家供大家参考,具体如下: 网页自动登录(提交Post内容)的用途很多,如验证身份.程序升级.网络投票等,以下是用C#实现的方法. 网页自动登录和提交POST信息的核心就是分析网页的源代码(HTML),在C#中,可以用来提取网页HTML的组件比较多,常用的用WebBrowser.WebClient.HttpWebRequest这三个.以下就分别用这三种方法来实现: 1.WebBrowser是个"迷你"浏览器,其特点

  • C#实现的WINDOWS登录功能示例

    本文实例讲述了C#实现的WINDOWS登录功能.分享给大家供大家参考,具体如下: using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.Web

随机推荐