ABP Zero集成微信小程序登陆

首先是ABPZero的第三方登陆模块,通过调用第三方的登录接口返回用户信息,再交给ABP的登陆验证模块去执行对应的登陆注册。

涉及的数据库表主要是这两个表,AbpUsers存储了用户信息,AbpUserLogins存储了登陆方式,第三方登陆的信息就是存储在这里的

主要是四个字段 LoginProvider ProviderKey TenantId UserId

        登陆提供器   用户唯一Id  对应的租户Id和用户Id

首先需要编写一个LoginProvider,代码如下

using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Abp.AspNetZeroCore.Web.Authentication.External;
using Castle.Core.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

namespace Web.Authentication.External
{
    public class WechatMiniProgramAuthProviderApi : ExternalAuthProviderApiBase
    {
        /// <summary>
        /// 微信小程序
        /// </summary>
        public const string ProviderName = "WeChatMiniProgram";
        WeChatMiniProgramOptions _options;
        JSchema schema = JSchema.Parse(JsonConvert.SerializeObject(new WeChatSession()));
        JSchema accessSchema = JSchema.Parse(JsonConvert.SerializeObject(new { AccessCode="", Name="" }));
        const string url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&grant_type=authorization_code&js_code={2}";
        private readonly IExternalAuthConfiguration _externalAuthConfiguration;
        private readonly ILogger logger;
        public WechatMiniProgramAuthProviderApi(IExternalAuthConfiguration externalAuthConfiguration, ILogger logger)
        {
            _externalAuthConfiguration = externalAuthConfiguration;
            var r = externalAuthConfiguration.Providers.First(p => p.Name == ProviderName);
            _options = new WeChatMiniProgramOptions
            {
                AppId = r.ClientId,
                Secret = r.ClientSecret
            };

            this.logger = logger;
        }

        public async override Task<ExternalAuthUserInfo> GetUserInfo(string accessCode)//因为需要获取微信放进User.Name
        {                                              //所以accessCode需要多一个Name
            JObject jObject = JObject.Parse(accessCode);              //就长这样 {"AccessCode":"xxxxxxxx", "Name":"Sam"}
            if (!jObject.IsValid(accessSchema))                    //所以用Jobect解析出来
            {
                throw new Abp.UI.UserFriendlyException("accessCode Json inVaild");
            }
            accessCode = jObject["AccessCode"].ToString();
            string name = jObject["Name"].ToString();
            //string rowData = jObject["RowData"].ToString();
            var result = await GetOpenId(accessCode);                 //获取到OpenId,说明accessCode是对的   实际上应该再通过OpenId解密数据后获取NickName的,偷懒了...
            //logger.Info("OpenId:" + result.Openid);                 //获取不到则在方法内部抛出异常,不会返回用户信息,也就不会执行之后的登陆注册操作
            var t = result == null ? new ExternalAuthUserInfo() : new ExternalAuthUserInfo//
            {
                EmailAddress = result.Openid + "@test.cn",
                Surname = name,
                ProviderKey = result.Openid,//唯一
                Provider = ProviderName,
                Name = name
            };
            return t;

        }

        private async Task<WeChatSession>  GetOpenId(string code)
        {
            string geturl = string.Format(url, _options.AppId, _options.Secret, code);
            HttpClient client = new HttpClient();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var result = await client.GetAsync(geturl);
            if (result.IsSuccessStatusCode)
            {                           //{"errcode":40163,"errmsg":"code been used, hints: [ req_id: tWZH6a0160th19 ]"}
                string re = await result.Content.ReadAsStringAsync();//{"session_key":"eafmjK9FYzCVpqPSo\/FBsQ==","openid":"oUigJ47QGkNOOXUjHkii5LyJbukw"}
                var jo = JObject.Parse(re);
                if (jo.IsValid(schema))
                {
                    var m = JsonConvert.DeserializeObject<WeChatSession>(re);
                    return m;
                }
            }
            return null ;
        }
    }

    class WeChatSession
    {
        public string Openid { get; set; }
        public string Session_key { get; set; }
    }

  /// <summary>    /// 微信小程序配置选项    /// </summary>    public class WeChatMiniProgramOptions    {        /// <summary>        /// AppId        /// </summary>        public string AppId { get; set; }        /// <summary>        /// 密钥        /// </summary>        public string Secret { get; set; }    }
}

然后在appsettings.json的Authentication节点中配置微信小程序的开启和appid 密钥的配置

然后在WebHostModule.cs中判断是否开启,执行配置(如果是MVC项目则是 项目名+WebMVCModule.cs)

因为默认的ProviderKey要求同一个登陆器下的同一用唯一,但是微信小程序里只有OpenId能做到用户唯一,OpenId又不能放到网络里传输,因此就需要修改一下默认的方式

注释掉 WebCore项目中Controller中TokenAuthController的GetExternalUserInfo方法中的判断调用接口传入ProviderKey和提供器返回用户信息ProviderKey一致。

这样Login表中的ProviderKey就会存储第一次登录时传入的accessCode。

最后只需要调用ExternalAuthenticate接口就可以了

需要注意的是这几个参数需要全部传入,哪怕传入为空。providerKey和ProviderAccessCode都传入微信小程序提供的accessCode。

这样就会返回accessToken了,调用接口时Hearder加上Bearer  accessToken就可以了

原文地址:https://www.cnblogs.com/turingguo/p/9019026.html

时间: 2024-08-03 02:05:07

ABP Zero集成微信小程序登陆的相关文章

补充ABP Zero集成微信小程序登陆的BUG修复部分

感谢园友 @turingguo 发布的 https://www.cnblogs.com/turingguo/p/9019026.html  文章,详细介绍了ABP Zero集成微信小程序登陆的实现过程. 经测试,abp的外部登陆有几处bug,在此做记录. 1.xxxxWebHostModule.cs文件 1 public override void PostInitialize() 2 { 3 4 if (!IocManager.Resolve<IMultiTenancyConfig>().I

微信小程序-登陆、支付、模板消息

wx.login(OBJECT) 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key).用户数据的加解密通讯需要依赖会话密钥完成. OBJECT参数说明: success返回参数说明: 示例代码: //app.js App({ onLaunch: function() { wx.login({ success: function(res) { if (res.code) { //发起网络请求 wx.reque

我感觉这个书上的微信小程序登陆写得不好

基本功能是OK,但是感觉传的数据太多,不安全,需要改写. App({ d: { hostUrl: 'http://www.test.com/index.php', //请填写您自己的小程序主机URL appId: "xxx", appKey: "xxx", ceshiUrl: 'http://www.test.com/index.php',//请填写您自己的测试URL }, //小程序初始化完成时触发,全局只触发一次 onLaunch: function () {

[小程序]微信小程序登陆并获取用户信息

1.小程序js端调用框架登陆API,获取到一个临时code,拿着这个code去调用自己的服务端接口 2.在自己的服务器端,使用app_id app_secrect code可以获取到用户的openid,这个id是用户唯一的id并且不会改变,可以把这个id返回给小程序端小程序端本地保存openid 3.获取用户信息很简单,并且不需要自己的服务器处理,只需要小程序端提供的API.前端页面wxml使用一个按钮,按钮里增加几个属性,就可以回调到小程序js部分的方法上,并且带着用户的个人信息,如昵称 头像

从session原理出发解决微信小程序的登陆问题

原理知识准备  对于已经熟悉了session原理的同学来说,我们都清楚:在浏览器端我们会存储一个sessionId,用它来作为凭证,在服务器端得到有关本次浏览器与服务器会话的所有信息,这些信息是储存在服务器端的存储空间中的,它完全可以用来判断一个浏览器端的登录状态,因为它是由服务器端来掌控的,是安全的. 那么浏览器端是用什么来存储这个sessionId? 并且浏览器又是如何将sessionId传回给服务器的呢? 大体上是有两种方法的: 1.使用浏览器端实现的cookie功能,每次浏览器都会将服务

微信小程序 使用HMACSHA1和md5为登陆注册报文添加指纹验证签名

对接口请求报文作指纹验证签名相信在开发中经常碰到, 这次在与java后端一起开发小程序时,就碰到需求对登陆注册请求报文添加指纹验证签名来防止信息被修改 先来看下我们与后端定制签名规则 2.4. 签名规则 原文规则:采用标准的JSON格式,null值字段舍去,按照key值字符串升序排列 例如:{"appId":"1100310061380986","outTradeNo":"1515120685073","timest

微信小程序之微信登陆 —— 微信小程序教程系列(20)

简介: 微信登陆,在新建一个微信小程序Hello World项目的时候,就可以看到项目中出现了我们的微信头像,其实这个Hello World项目,就有一个简化版的微信登陆.只不过是,还没有写入到咱们自家的后台中而已. 新建一个Hello World项目,找到app.js文件打开,代码如下: app.js: App({ onLaunch: function () { //调用API从本地缓存中获取数据 var logs = wx.getStorageSync('logs') || [] logs.

SAP成都研究院大卫哥:SAP C4C中国本地化之微信小程序集成

今天的文章来自Wu David,SAP成都研究院C4C开发团队的架构师,在加入团队之前曾经在SAP上海研究院工作,组内同事习惯亲切地称呼他为大卫哥. 大卫哥身高据Jerry目测有1米8以上,是成都C4C开发团队身高最高的几位男同事之一.身体非常结实,是成都SAP篮球队的成员之一.有一次大卫哥坐在自己座位上,一手撑在桌子上认真地看着向他求助的同事电脑上打印的日志,飞机哥张航拍了一张大卫哥的背影,评价道:"从照片里看出了大卫哥发达的背阔肌." 飞机哥张航后来完成了一幅素描,下图左边正在沉思

微信小程序开发 - 用户授权登陆

准备:微信开发者工具下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 微信小程序开发文档:https://developers.weixin.qq.com/miniprogram/dev/index.html 开发:在开发之初,我们需要先明确微信方已经制定好的授权登陆流程,参看 官方API - 登陆接口. 你会看到微信方为开发者制定好的登陆授权流程: 如图,即为一个顺向的用户登陆授权的流程.