微信网页授权是 OAuth2.0 协议的一种应用,主要用于获取访问者的基本信息(如昵称、头像、openid 等),它分为两种作用域(scope):

asp.net 微信网页授权
(图片来源网络,侵删)
  1. snsapi_base:静默授权,只获取用户的 openid,用户无感知,不会弹出授权页面。
  2. snsapi_userinfo:弹出授权页面,用户同意后,可以获取用户的 openid、昵称、性别、所在地和头像,用户体验更好,但需要用户手动点击同意。

下面我将为你提供一个完整、详细的 ASP.NET (Web Forms / MVC) 实现方案。


第一步:准备工作

在开始编码之前,你必须在微信公众平台完成以下配置:

  1. 拥有一个认证服务号:只有认证的服务号才有权限使用网页授权。
  2. 获取 AppID 和 AppSecret:登录微信公众平台,在“开发” -> “基本配置”中找到你的 AppID 和 AppSecret。
  3. 配置网页授权域名
    • 登录微信公众平台。
    • 进入“设置” -> “公众号设置” -> “功能设置”。
    • 找到“网页授权域名”,点击“修改”。
    • 填写你的域名,www.yourdomain.com注意:这里只能填写顶级域名,并且需要先在“公众号设置” -> “授权事件接收URL”中验证过这个域名,验证方法通常是下载一个文件并上传到你的服务器根目录。

第二步:理解授权流程

微信网页授权的流程如下(非常重要):

  1. 用户访问:用户在微信内置浏览器中访问你的网页(https://www.yourdomain.com/)。
  2. 重定向到微信:你的服务器检测到用户未授权,将其重定向到微信的授权 URL,这个 URL 包含了你的 AppID、回调地址、作用域等参数。
    • 微信授权 URL: https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
  3. 用户授权:微信服务器向用户展示授权页面。
    • 如果是 snsapi_userinfo,用户点击“同意授权”。
    • 如果是 snsapi_base,则静默授权。
  4. 回调到你的服务器:微信服务器将用户重定向回你在 redirect_uri 中指定的地址,并附带一个临时的 code 参数。
    • https://www.yourdomain.com/Auth/Callback?code=CODE&state=STATE
  5. 获取 Access Token:你的服务器接收到 code 后,用它向微信服务器请求换取 access_tokenopenid
    • 请求 URL: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
  6. 获取用户信息:使用上一步获取的 access_tokenopenid,向微信服务器请求用户信息(如果作用域是 snsapi_userinfo)。
    • 请求 URL: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
  7. 完成授权:你的服务器拿到用户信息后,可以进行业务逻辑处理(如登录、创建用户等),然后向用户展示最终页面。

第三步:在 ASP.NET 中实现代码

我们将创建一个通用的帮助类来处理授权逻辑,这样可以方便地在任何页面调用。

asp.net 微信网页授权
(图片来源网络,侵删)

创建微信配置类

将你的 AppID 和 AppSecret 存储在 web.config 中,避免硬编码。

web.config<appSettings> 节点中添加:

<add key="WeChatAppId" value="你的AppID"/>
<add key="WeChatAppSecret" value="你的AppSecret"/>
<add key="WeChatRedirectDomain" value="https://www.yourdomain.com"/> <!-- 你的授权回调域名 -->

创建微信授权帮助类

在项目中创建一个 WeChatHelper.cs 类。

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Web;
using System.Web.Script.Serialization; // 需要添加 System.Web.Extensions 引用
public class WeChatHelper
{
    private readonly string _appId;
    private readonly string _appSecret;
    private readonly string _redirectDomain;
    public WeChatHelper()
    {
        _appId = System.Configuration.ConfigurationManager.AppSettings["WeChatAppId"];
        _appSecret = System.Configuration.ConfigurationManager.AppSettings["WeChatAppSecret"];
        _redirectDomain = System.Configuration.ConfigurationManager.AppSettings["WeChatRedirectDomain"];
    }
    /// <summary>
    /// 生成微信授权链接
    /// </summary>
    /// <param name="redirectUri">授权成功后的回调地址</param>
    /// <param name="scope">作用域,snsapi_base 或 snsapi_userinfo</param>
    /// <param name="state">自定义参数,原样返回</param>
    /// <returns></returns>
    public string GenerateAuthUrl(string redirectUri, string scope = "snsapi_userinfo", string state = "")
    {
        // 回调地址需要进行 URL 编码
        var encodedRedirectUri = HttpUtility.UrlEncode(redirectUri);
        var authUrl = $"https://open.weixin.qq.com/connect/oauth2/authorize?appid={_appId}&redirect_uri={encodedRedirectUri}&response_type=code&scope={scope}&state={state}#wechat_redirect";
        return authUrl;
    }
    /// <summary>
    /// 通过 Code 获取 Access Token 和 OpenId
    /// </summary>
    /// <param name="code">微信回调返回的 code</param>
    /// <returns>包含 access_token, openid, unionid 等信息的字典</returns>
    public Dictionary<string, string> GetAccessTokenByCode(string code)
    {
        var tokenUrl = $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={_appId}&secret={_appSecret}&code={code}&grant_type=authorization_code";
        using (var client = new HttpClient())
        {
            var response = client.GetAsync(tokenUrl).Result;
            var result = response.Content.ReadAsStringAsync().Result;
            // 使用 JavaScriptSerializer 解析 JSON
            var serializer = new JavaScriptSerializer();
            return serializer.Deserialize<Dictionary<string, string>>(result);
        }
    }
    /// <summary>
    /// 通过 Access Token 和 OpenId 获取用户信息
    /// </summary>
    /// <param name="accessToken">Access Token</param>
    /// <param name="openId">用户的 OpenId</param>
    /// <returns>包含用户信息的字典</returns>
    public Dictionary<string, object> GetUserInfo(string accessToken, string openId)
    {
        var userInfoUrl = $"https://api.weixin.qq.com/sns/userinfo?access_token={accessToken}&openid={openId}";
        using (var client = new HttpClient())
        {
            var response = client.GetAsync(userInfoUrl).Result;
            var result = response.Content.ReadAsStringAsync().Result;
            var serializer = new JavaScriptSerializer();
            return serializer.Deserialize<Dictionary<string, object>>(result);
        }
    }
}

实现页面逻辑

假设你的项目结构如下:

  • Default.aspx (或 Home/Index):需要授权的页面。
  • Auth/Callback.aspx (或 Auth/Callback):微信授权后的回调页面。

A. 需要授权的页面 (Default.aspx)

这个页面会检查用户是否已经授权,如果没有,就引导用户去微信授权。

C# 代码 (Default.aspx.cs)

protected void Page_Load(object sender, EventArgs e)
{
    // 检查 Session 中是否已有 openid,如果有,说明已授权,直接显示用户信息
    if (Session["WeChatOpenId"] != null)
    {
        // 获取用户信息并显示
        DisplayUserInfo();
        return;
    }
    // 如果没有 openid,则进行授权
    // 1. 定义回调地址,这个地址必须是你在公众号配置的授权域名下的一个有效路径
    string callbackUrl = "https://www.yourdomain.com/Auth/Callback.aspx"; // 必须是完整 URL
    // 2. 创建帮助类实例
    var weChatHelper = new WeChatHelper();
    // 3. 生成授权 URL (这里使用 snsapi_userinfo,体验更好)
    string authUrl = weChatHelper.GenerateAuthUrl(callbackUrl, "snsapi_userinfo");
    // 4. 将页面重定向到微信授权页
    Response.Redirect(authUrl);
}
private void DisplayUserInfo()
{
    // 这里可以从 Session 或数据库中获取用户信息并显示
    // 示例:
    litUserInfo.Text = $"欢迎回来,您的 OpenId 是: {Session["WeChatOpenId"]}";
}

B. 回调页面 (Auth/Callback.aspx)

这个页面接收微信服务器返回的 code,并用它来换取 access_token 和用户信息。

C# 代码 (Auth/Callback.aspx.cs)

protected void Page_Load(object sender, EventArgs e)
{
    // 1. 获取微信回调传回的 code
    string code = Request.QueryString["code"];
    if (string.IsNullOrEmpty(code))
    {
        // 如果没有 code,说明用户拒绝了授权或发生错误
        Response.Write("授权失败,未获取到 code。");
        return;
    }
    // 2. 获取 state 参数 (可选,可用于防止 CSRF 攻击)
    string state = Request.QueryString["state"];
    // 3. 使用 code 换取 access_token 和 openid
    var weChatHelper = new WeChatHelper();
    Dictionary<string, string> tokenInfo = weChatHelper.GetAccessTokenByCode(code);
    if (tokenInfo.ContainsKey("errcode"))
    {
        // 如果返回了错误码
        string errorMsg = $"获取 access_token 失败: {tokenInfo["errmsg"]}";
        Response.Write(errorMsg);
        return;
    }
    string accessToken = tokenInfo["access_token"];
    string openId = tokenInfo["openid"];
    // 4. 将 openid 存入 Session,标记用户已登录
    Session["WeChatOpenId"] = openId;
    // 5. (可选) 获取用户详细信息
    Dictionary<string, object> userInfo = weChatHelper.GetUserInfo(accessToken, openId);
    if (userInfo.ContainsKey("errcode"))
    {
        // 获取用户信息失败
        // 可以只使用 openid 继续业务逻辑
        Response.Redirect("~/Default.aspx"); // 跳转到首页
        return;
    }
    // 将用户信息也存入 Session
    Session["WeChatUserInfo"] = userInfo;
    // 6. 授权成功,重定向回最初的页面
    // 这里简单起见,直接跳转到首页,实际项目中,应该记录用户最初想访问的页面,授权成功后再跳转回去。
    Response.Redirect("~/Default.aspx");
}

第四步:测试和注意事项

  1. 测试环境:微信网页授权必须在微信内置浏览器(手机微信、电脑版微信)中进行测试,普通浏览器无法触发流程。
  2. 回调域名redirect_uri 必须与你之前在公众号后台配置的授权域名完全一致,包括协议(httphttps),不一致会报错 redirect_uri domain error
  3. state 参数:强烈建议使用 state 参数,它可以用来防止 CSRF(跨站请求伪造)攻击,你可以在发起授权时生成一个随机字符串,并存入 Session 或 Cookie,在回调时进行验证。
  4. access_token 缓存access_token 是有有效期(2小时)的,不要每次都去微信服务器获取,应该缓存起来,过期后再重新获取,可以使用 HttpRuntime.Cache 或分布式缓存(如 Redis)来实现。
  5. 错误处理:对微信 API 的返回结果进行充分的错误判断,特别是 errcode 字段,避免因微信接口变更或网络问题导致程序崩溃。
  6. HttpUtility.UrlEncode:在拼接 redirect_uri 时,必须使用 HttpUtility.UrlEncode 进行编码,否则特殊字符会导致授权失败。
  7. HTTPS:现在所有涉及用户信息和支付的接口都强制要求使用 HTTPS,确保你的整个网站,特别是授权相关的页面,都部署在 HTTPS 之下。

通过以上步骤,你就可以在 ASP.NET 项目中成功实现微信网页授权功能了,这个方案适用于 ASP.NET Web Forms 和 MVC,核心逻辑是相通的。