千家信息网

ASP.NET Core集成微信登录的示例分析

发表于:2024-11-30 作者:千家信息网编辑
千家信息网最后更新 2024年11月30日,这篇文章主要为大家展示了"ASP.NET Core集成微信登录的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"ASP.NET Core集成微信登录
千家信息网最后更新 2024年11月30日ASP.NET Core集成微信登录的示例分析

这篇文章主要为大家展示了"ASP.NET Core集成微信登录的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"ASP.NET Core集成微信登录的示例分析"这篇文章吧。

工具:

Visual Studio 2015 update 3

Asp.Net Core 1.0

1 准备工作

申请微信公众平台接口测试帐号,申请网址:(mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login)。申请接口测试号无需公众帐号,可以直接体验和测试公众平台所有高级接口。

1.1 配置接口信息

1.2 修改网页授权信息

点击"修改"后在弹出页面填入你的网站域名:

2 新建网站项目

2.1 选择ASP.NET Core Web Application 模板

2.2 选择Web 应用程序,并更改身份验证为个人用户账户

3 集成微信登录功能

3.1添加引用

打开project.json文件,添加引用Microsoft.AspNetCore.Authentication.OAuth

3.2 添加代码文件

在项目中新建文件夹,命名为WeChatOAuth,并添加代码文件(本文最后附全部代码)。

3.3 注册微信登录中间件

打开Startup.cs文件,在Configure中添加代码:

app.UseWeChatAuthentication(new WeChatOptions(){ AppId = "******", AppSecret = "******"});

注意该代码的插入位置必须在app.UseIdentity()下方。

4 代码

WeChatAppBuilderExtensions.cs

// Copyright (c) .NET Foundation. All rights reserved.// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using System;using Microsoft.AspNetCore.Authentication.WeChat;using Microsoft.Extensions.Options;namespace Microsoft.AspNetCore.Builder{ ///  /// Extension methods to add WeChat authentication capabilities to an HTTP application pipeline. ///  public static class WeChatAppBuilderExtensions {  ///   /// Adds the  middleware to the specified , which enables WeChat authentication capabilities.  ///   /// The  to add the middleware to.  /// A reference to this instance after the operation has completed.  public static IApplicationBuilder UseWeChatAuthentication(this IApplicationBuilder app)  {   if (app == null)   {    throw new ArgumentNullException(nameof(app));   }   return app.UseMiddleware();  }  ///   /// Adds the  middleware to the specified , which enables WeChat authentication capabilities.  ///   /// The  to add the middleware to.  /// A  that specifies options for the middleware.  /// A reference to this instance after the operation has completed.  public static IApplicationBuilder UseWeChatAuthentication(this IApplicationBuilder app, WeChatOptions options)  {   if (app == null)   {    throw new ArgumentNullException(nameof(app));   }   if (options == null)   {    throw new ArgumentNullException(nameof(options));   }   return app.UseMiddleware(Options.Create(options));  } }}

WeChatDefaults.cs:

// Copyright (c) .NET Foundation. All rights reserved.// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.namespace Microsoft.AspNetCore.Authentication.WeChat{ public static class WeChatDefaults {  public const string AuthenticationScheme = "WeChat";  public static readonly string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth3/authorize";  public static readonly string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth3/access_token";  public static readonly string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo"; }}

WeChatHandler.cs

// Copyright (c) .NET Foundation. All rights reserved.// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authentication.OAuth;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.Http.Authentication;using Microsoft.AspNetCore.Http.Extensions;using Microsoft.Extensions.Primitives;using Newtonsoft.Json.Linq;using System;using System.Collections.Generic;using System.Net.Http;using System.Net.Http.Headers;using System.Security.Claims;using System.Text;using Microsoft.AspNetCore.Mvc;using System.Threading.Tasks;namespace Microsoft.AspNetCore.Authentication.WeChat{ internal class WeChatHandler : OAuthHandler {  public WeChatHandler(HttpClient httpClient)   : base(httpClient)  {  }  protected override async Task HandleRemoteAuthenticateAsync()  {   AuthenticationProperties properties = null;   var query = Request.Query;   var error = query["error"];   if (!StringValues.IsNullOrEmpty(error))   {    var failureMessage = new StringBuilder();    failureMessage.Append(error);    var errorDescription = query["error_description"];    if (!StringValues.IsNullOrEmpty(errorDescription))    {     failureMessage.Append(";Description=").Append(errorDescription);    }    var errorUri = query["error_uri"];    if (!StringValues.IsNullOrEmpty(errorUri))    {     failureMessage.Append(";Uri=").Append(errorUri);    }    return AuthenticateResult.Fail(failureMessage.ToString());   }   var code = query["code"];   var state = query["state"];   var oauthState = query["oauthstate"];   properties = Options.StateDataFormat.Unprotect(oauthState);   if (state != Options.StateAddition || properties == null)   {    return AuthenticateResult.Fail("The oauth state was missing or invalid.");   }   // OAuth3 10.12 CSRF   if (!ValidateCorrelationId(properties))   {    return AuthenticateResult.Fail("Correlation failed.");   }   if (StringValues.IsNullOrEmpty(code))   {    return AuthenticateResult.Fail("Code was not found.");   }   //获取tokens   var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath));   var identity = new ClaimsIdentity(Options.ClaimsIssuer);   AuthenticationTicket ticket = null;   if (Options.WeChatScope == Options.InfoScope)   {    //获取用户信息    ticket = await CreateTicketAsync(identity, properties, tokens);   }   else   {    //不获取信息,只使用openid    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, tokens.TokenType, ClaimValueTypes.String, Options.ClaimsIssuer));    ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.AuthenticationScheme);   }   if (ticket != null)   {    return AuthenticateResult.Success(ticket);   }   else   {    return AuthenticateResult.Fail("Failed to retrieve user information from remote server.");   }  }    ///   /// OAuth第一步,获取code  ///   ///   ///   ///   protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)  {   //加密OAuth状态   var oauthstate = Options.StateDataFormat.Protect(properties);   //   redirectUri = $"{redirectUri}?{nameof(oauthstate)}={oauthstate}";   var queryBuilder = new QueryBuilder()   {    { "appid", Options.ClientId },    { "redirect_uri", redirectUri },    { "response_type", "code" },    { "scope", Options.WeChatScope },         { "state", Options.StateAddition },   };   return Options.AuthorizationEndpoint + queryBuilder.ToString();  }  ///   /// OAuth第二步,获取token  ///   ///   ///   ///   protected override async Task ExchangeCodeAsync(string code, string redirectUri)  {   var tokenRequestParameters = new Dictionary()   {    { "appid", Options.ClientId },    { "secret", Options.ClientSecret },    { "code", code },    { "grant_type", "authorization_code" },   };   var requestContent = new FormUrlEncodedContent(tokenRequestParameters);   var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);   requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));   requestMessage.Content = requestContent;   var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted);   if (response.IsSuccessStatusCode)   {    var payload = JObject.Parse(await response.Content.ReadAsStringAsync());    string ErrCode = payload.Value("errcode");    string ErrMsg = payload.Value("errmsg");    if (!string.IsNullOrEmpty(ErrCode) | !string.IsNullOrEmpty(ErrMsg))    {     return OAuthTokenResponse.Failed(new Exception($"ErrCode:{ErrCode},ErrMsg:{ErrMsg}"));     }    var tokens = OAuthTokenResponse.Success(payload);    //借用TokenType属性保存openid    tokens.TokenType = payload.Value("openid");    return tokens;   }   else   {    var error = "OAuth token endpoint failure";    return OAuthTokenResponse.Failed(new Exception(error));   }  }  ///   /// OAuth第四步,获取用户信息  ///   ///   ///   ///   ///   protected override async Task CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)  {   var queryBuilder = new QueryBuilder()   {    { "access_token", tokens.AccessToken },    { "openid", tokens.TokenType },//在第二步中,openid被存入TokenType属性    { "lang", "zh_CN" }   };   var infoRequest = Options.UserInformationEndpoint + queryBuilder.ToString();   var response = await Backchannel.GetAsync(infoRequest, Context.RequestAborted);   if (!response.IsSuccessStatusCode)   {    throw new HttpRequestException($"Failed to retrieve WeChat user information ({response.StatusCode}) Please check if the authentication information is correct and the corresponding WeChat Graph API is enabled.");   }   var user = JObject.Parse(await response.Content.ReadAsStringAsync());   var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.AuthenticationScheme);   var context = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, user);   var identifier = user.Value("openid");   if (!string.IsNullOrEmpty(identifier))   {    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, identifier, ClaimValueTypes.String, Options.ClaimsIssuer));   }   var nickname = user.Value("nickname");   if (!string.IsNullOrEmpty(nickname))   {    identity.AddClaim(new Claim(ClaimTypes.Name, nickname, ClaimValueTypes.String, Options.ClaimsIssuer));   }   var sex = user.Value("sex");   if (!string.IsNullOrEmpty(sex))   {    identity.AddClaim(new Claim("urn:WeChat:sex", sex, ClaimValueTypes.String, Options.ClaimsIssuer));   }   var country = user.Value("country");   if (!string.IsNullOrEmpty(country))   {    identity.AddClaim(new Claim(ClaimTypes.Country, country, ClaimValueTypes.String, Options.ClaimsIssuer));   }   var province = user.Value("province");   if (!string.IsNullOrEmpty(province))   {    identity.AddClaim(new Claim(ClaimTypes.StateOrProvince, province, ClaimValueTypes.String, Options.ClaimsIssuer));   }   var city = user.Value("city");   if (!string.IsNullOrEmpty(city))   {    identity.AddClaim(new Claim("urn:WeChat:city", city, ClaimValueTypes.String, Options.ClaimsIssuer));   }   var headimgurl = user.Value("headimgurl");   if (!string.IsNullOrEmpty(headimgurl))   {    identity.AddClaim(new Claim("urn:WeChat:headimgurl", headimgurl, ClaimValueTypes.String, Options.ClaimsIssuer));   }   var unionid = user.Value("unionid");   if (!string.IsNullOrEmpty(unionid))   {    identity.AddClaim(new Claim("urn:WeChat:unionid", unionid, ClaimValueTypes.String, Options.ClaimsIssuer));   }   await Options.Events.CreatingTicket(context);   return context.Ticket;  } }}

WeChatMiddleware.cs

// Copyright (c) .NET Foundation. All rights reserved.// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using System;using System.Globalization;using System.Text.Encodings.Web;using Microsoft.AspNetCore.Authentication.OAuth;using Microsoft.AspNetCore.Builder;using Microsoft.AspNetCore.DataProtection;using Microsoft.AspNetCore.Http;using Microsoft.Extensions.Logging;using Microsoft.Extensions.Options;namespace Microsoft.AspNetCore.Authentication.WeChat{ ///  /// An ASP.NET Core middleware for authenticating users using WeChat. ///  public class WeChatMiddleware : OAuthMiddleware {  ///   /// Initializes a new .  ///   /// The next middleware in the HTTP pipeline to invoke.  ///   ///   ///   ///   /// Configuration options for the middleware.  public WeChatMiddleware(   RequestDelegate next,   IDataProtectionProvider dataProtectionProvider,   ILoggerFactory loggerFactory,   UrlEncoder encoder,   IOptions sharedOptions,   IOptions options)   : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options)  {   if (next == null)   {    throw new ArgumentNullException(nameof(next));   }   if (dataProtectionProvider == null)   {    throw new ArgumentNullException(nameof(dataProtectionProvider));   }   if (loggerFactory == null)   {    throw new ArgumentNullException(nameof(loggerFactory));   }   if (encoder == null)   {    throw new ArgumentNullException(nameof(encoder));   }   if (sharedOptions == null)   {    throw new ArgumentNullException(nameof(sharedOptions));   }   if (options == null)   {    throw new ArgumentNullException(nameof(options));   }   if (string.IsNullOrEmpty(Options.AppId))   {    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, nameof(Options.AppId)));   }   if (string.IsNullOrEmpty(Options.AppSecret))   {    throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, nameof(Options.AppSecret)));   }  }  ///   /// Provides the  object for processing authentication-related requests.  ///   /// An  configured with the  supplied to the constructor.  protected override AuthenticationHandler CreateHandler()  {   return new WeChatHandler(Backchannel);  } }}

WeChatOptions.cs

// Copyright (c) .NET Foundation. All rights reserved.// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using System.Collections.Generic;using Microsoft.AspNetCore.Authentication.WeChat;using Microsoft.AspNetCore.Http;using Microsoft.AspNetCore.Identity;namespace Microsoft.AspNetCore.Builder{ ///  /// Configuration options for . ///  public class WeChatOptions : OAuthOptions {  ///   /// Initializes a new .  ///   public WeChatOptions()  {   AuthenticationScheme = WeChatDefaults.AuthenticationScheme;   DisplayName = AuthenticationScheme;   CallbackPath = new PathString("/signin-wechat");   StateAddition = "#wechat_redirect";   AuthorizationEndpoint = WeChatDefaults.AuthorizationEndpoint;   TokenEndpoint = WeChatDefaults.TokenEndpoint;   UserInformationEndpoint = WeChatDefaults.UserInformationEndpoint;   //SaveTokens = true;      //BaseScope (不弹出授权页面,直接跳转,只能获取用户openid),   //InfoScope (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)   WeChatScope = InfoScope;  }  // WeChat uses a non-standard term for this field.  ///   /// Gets or sets the WeChat-assigned appId.  ///   public string AppId  {   get { return ClientId; }   set { ClientId = value; }  }  // WeChat uses a non-standard term for this field.  ///   /// Gets or sets the WeChat-assigned app secret.  ///   public string AppSecret  {   get { return ClientSecret; }   set { ClientSecret = value; }  }  public string StateAddition { get; set; }  public string WeChatScope { get; set; }  public string BaseScope = "snsapi_base";  public string InfoScope = "snsapi_userinfo"; }}

以上是"ASP.NET Core集成微信登录的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

代码 信息 登录 文件 用户 接口 示例 分析 公众 内容 篇文章 页面 测试 属性 平台 网站 项目 帐号 学习 帮助 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库设计用一个大表如何分区 中教数据库官网打不开 服务器托管方案有哪种形式 mysql 数据库约束添加 以下属于网络安全事件的有哪 全网最火的小说9.9分服务器 厦门大象精灵软件开发公司怎么样 嵌入式软件开发好学么 2021网易mc较火的服务器 启动自己的监听服务器 软件开发维护管理制度怎么编写 方舟多人服务器精灵球模组 数据库系统设计方案 属于网络安全技术的是什么 浙江嘉友网络技术有限公司 传奇外传哪个服务器好 服务器本地连接在哪 江西人设服务器异常 用户头像图片存数据库 求生之路怎么创建服务器 男变女小说软件开发 服务器管理后台密钥 数据库系统及应用实验报告 应用软件开发学习网站 服务器运营商哪家好 网络安全手抄报模板通用 深圳奇点网络技术有限公司 服务器信息安全管理 软件开发环境的目标是提高 微信等社交媒体网络安全警示教育
0