前言

在我们的开发工作中有可能会对接过各种各样的第三方平台的登录授权,来获取用户的相关账号信息(如:微信登录、支付宝登录、飞书登录、钉钉登录、GitHub登录等等)。今天大姚给大家推荐一个基于 C# 开源的第三方 OAuth2 授权登录整合库:Netnr.Login。

项目介绍

Netnr.Login是一个基于 C# 开源(MIT License)的第三方 OAuth2 授权登录整合库,集成了QQ、微信开放平台(Weixin)、微信公众平台(WeixinMP)、微博(Weibo)、淘宝(Taobao)、支付宝(Alipay)、钉钉(DingTalk)、飞书(Feishu)、华为(Huawei)、小米(Xiaomi)、AtomGit、码云(Gitee)、GitHub、GitLab、微软(Microsoft )、StackOverflow等授权登录功能,可以帮助大家快速完成常见的第三方平台的登录授权功能。

支持第三方登录

项目源码

快速接入

使用说明

        /// <summary>
        /// 说明
        /// </summary>
        /// <returns></returns>
        public IActionResult Index()
        {
            /*
                LoginTo.EntryOfStep<TBefore, TReq>(LoginWhich, LoginStep, Func<string, string> stateCall)
                每个步骤入口,接收5个参数:LoginWhich、LoginStep、TBefore、TReq、stateCall

                LoginWhich 哪家,枚举对象,如 QQ GitHub 等
                LoginStep 步骤,枚举对象,顺序 Authorize(跳转授权链接)、AccessToken(根据授权码 code 请求令牌)、RefreshToken(刷新令牌,可选)、OpenId(仅QQ)、User(用户信息,不支持Taobao)

                TBefore 之前的结果(上一步返回的结果,用于自动生成请求对象 TReq)
                TReq 请求对象,自定义构建请求参数,传值则不从 TBefore 构建,两者二选一

                stateCall 步骤为 Authorize 构建授权链接 state 字段回调方法

                请求参数类名遵循 LoginWhich + LoginStep + Model
                如 GitHub Authorize Model => GitHub AccessToken Model => GitHub User Model

                AuthorizeResult 为统一接收授权码对象,其它步骤返回的对象均为 DocModel
                DocModel 对象中 Raw 为原始结果字符串,Doc 为 System.Text.Json 组件下的仅读对象            
             */

            return Ok();
        }

三方登录并跳转授权页面

        /// <summary>
        /// 三方登录并跳转授权页面
        /// </summary>
        /// <param name="id">哪家</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Auth([FromRoute] LoginWhich? id)
        {
            AssignKey();

            if (id.HasValue)
            {
                var loginType = id.Value;

                //默认构建请求链接
                DocModel authResult = LoginTo.EntryOfStep<object, object>(loginType, LoginStep.Authorize, stateCall: (state) => $"login_{state}");
                if (!string.IsNullOrEmpty(authResult.Raw))
                {
                    return Redirect(authResult.Raw);
                }

                //或 自定义构建请求链接
                authResult = LoginTo.EntryOfStep<object, QQAuthorizeModel>(loginType, LoginStep.Authorize, reqModel: new()
                {
                    State = $"bind_{DateTime.Now:yyyyMMddHHmmss}"
                });
                Console.WriteLine(authResult.Raw);
            }

            return BadRequest();
        }

三方登录回调

        /// <summary>
        /// 三方登录回调
        /// </summary>
        /// <param name="id">哪家</param>
        /// <param name="authResult">接收授权码</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AuthCallback([FromRoute] LoginWhich id, AuthorizeResult authResult)
        {
            //极简拿到最终用户信息
            var publicUser = LoginTo.Entry(id, authResult);

            var result = publicUser.ToJson(true);
            Console.WriteLine(result);

            return Ok(result);
        }

        /// <summary>
        /// 三方登录回调,所有步骤的信息
        /// </summary>
        /// <param name="id">哪家</param>
        /// <param name="authResult">接收授权码</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AuthCallback_Steps([FromRoute] LoginWhich id, AuthorizeResult authResult)
        {
            //含步骤信息
            (DocModel tokenResult, DocModel openidResult, DocModel userResult, PublicUserResult publicUser) = LoginTo.EntryOfSteps(id, authResult);

            var result = new
            {
                tokenResult,
                openidResult,
                userResult,
                publicUser
            }.ToJson(true);
            Console.WriteLine(result);

            return Ok(result);
        }

        /// <summary>
        /// 三方登录回调,逐步
        /// </summary>
        /// <param name="id">哪家</param>
        /// <param name="authResult">接收授权码</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AuthCallback_Step([FromRoute] LoginWhich? id, AuthorizeResult authResult)
        {
            try
            {
                if (id == null)
                {
                    throw new Exception($"不支持该方式授权 {RouteData.Values["id"]?.ToString()}");
                }
                else if (authResult.NoAuthCode())
                {
                    throw new Exception($"授权失败");
                }
                else
                {
                    var loginType = id.Value;
                    Console.WriteLine($"{Environment.NewLine}----- Sign in with {loginType} {DateTime.Now:yyyy-MM-dd HH:mm:ss}{Environment.NewLine}");

                    //step: access token(非 旧版 DingTalk)
                    DocModel tokenResult = null;
                    //step: openid (仅 QQ)
                    DocModel openidResult = null;
                    //step: user (非 Taobao)
                    DocModel userResult = null;

                    if (!(loginType == LoginWhich.DingTalk && DingTalk.IsOld))
                    {
                        tokenResult = LoginTo.EntryOfStep<AuthorizeResult, object>(loginType, LoginStep.AccessToken, beforeResult: authResult);
                        Console.WriteLine($"{Environment.NewLine}{nameof(LoginStep.AccessToken)}");
                        Console.WriteLine(tokenResult.Doc.ToJson(true));

                        //step: refresh token (可选,仅支持部分)
                        if (!new[] { LoginWhich.Weibo, LoginWhich.Taobao, LoginWhich.GitHub, LoginWhich.StackOverflow }.Contains(loginType)
                            && !(loginType == LoginWhich.Microsoft && Login.Microsoft.IsOld))
                        {
                            tokenResult = LoginTo.EntryOfStep<DocModel, object>(loginType, LoginStep.RefreshToken, beforeResult: tokenResult);
                            Console.WriteLine($"{Environment.NewLine}{nameof(LoginStep.RefreshToken)}");
                            Console.WriteLine(tokenResult.Doc.ToJson(true));
                        }
                    }
                    if (loginType == LoginWhich.QQ)
                    {
                        openidResult = LoginTo.EntryOfStep<DocModel, object>(loginType, LoginStep.OpenId, beforeResult: tokenResult);
                        userResult = LoginTo.EntryOfStep<DocModel[], object>(loginType, LoginStep.User, beforeResult: [tokenResult, openidResult]);
                    }
                    else if (loginType == LoginWhich.DingTalk && DingTalk.IsOld)
                    {
                        userResult = LoginTo.EntryOfStep<object, AuthorizeResult>(loginType, LoginStep.User, reqModel: authResult);
                    }
                    else if (loginType != LoginWhich.Taobao)
                    {
                        userResult = LoginTo.EntryOfStep<DocModel, object>(loginType, LoginStep.User, beforeResult: tokenResult);
                    }

                    if (openidResult != null)
                    {
                        Console.WriteLine($"{Environment.NewLine}{nameof(LoginStep.OpenId)}");
                        Console.WriteLine(openidResult.Doc.ToJson(true));
                    }
                    if (userResult != null)
                    {
                        Console.WriteLine($"{Environment.NewLine}{nameof(LoginStep.User)}");
                        Console.WriteLine(userResult.Doc.ToJson(true));
                    }

                    return Ok("Done!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return BadRequest($"授权失败 {ex.Message}");
            }
        }

        /// <summary>
        /// 三方登录回调,自定义构建请求参数
        /// </summary>
        /// <param name="code">接收授权码</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AuthCallback_GitHub(string code)
        {
            //step: access token
            DocModel tokenResult = LoginTo.EntryOfStep<object, GitHubAccessTokenModel>(LoginWhich.GitHub, LoginStep.AccessToken, reqModel: new GitHubAccessTokenModel()
            {
                Code = code
            });
            Console.WriteLine(tokenResult.Doc.ToJson(true));

            //step: user
            DocModel userResult = LoginTo.EntryOfStep<object, GitHubUserModel>(LoginWhich.GitHub, LoginStep.User, reqModel: new GitHubUserModel()
            {
                Access_Token = tokenResult.Doc.GetValue("access_token")
            });

            Console.WriteLine(userResult.Doc.ToJson(true));

            return Content(userResult.Raw);
        }

项目源码地址

更多项目实用功能和特性欢迎前往项目开源地址查看,别忘了给项目一个Star支持。

优秀项目和框架精选

该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没)。

一个基于 C# 开源的第三方 OAuth2 授权登录整合库的更多相关文章

  1. 第三方OAuth授权登录,QQ、微信(WeChat)、微博、GitHub、码云(Gitee)、淘宝(天猫)、微软(Microsoft )、钉钉、谷歌(Google)、支付宝(AliPay)、StackOverflow

    Netnr.Login 第三方OAuth授权登录 支持第三方登录 三方 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 参考文档 安装 ( ...

  2. 基于第三方微信授权登录的iOS代码分析

    本文转载至 http://www.cocoachina.com/ios/20140922/9715.html 微信已经深入到每一个APP的缝隙,最常用的莫过分享和登录了,接下来就以代码的形式来展开微信 ...

  3. 解决微信公众号授权登录和开放平台微信第三方应用授权登录获取到的用户Openid关联问题

    开发背景: 最近一段时间一直在做关于微信方面的网站应用开发,这段时间也收获的不少关于微信开发方面的开发技能,接触的比较多的主要有微信公众号和微信网站app第三方登录授权,以及微信会员卡,优惠券和扫描二 ...

  4. iOS 基于第三方QQ授权登录

    基于iOS实现APP的第三方QQ登陆.接入第三方SDK时的一个主要的步骤: 1,找到相关的开放平台.QQ互联平台,http://connect.qq.com/: 2,注冊成功后创建自己的APP.填写一 ...

  5. AbpZero之企业微信---登录(拓展第三方auth授权登录)---第二步:开始逐步实现企业微信登录

    上回分解到AbpZero的auth登录机制,这里我们开始着手逐步实现我们的auth登录. 我们新建一个类库XXXX.Web.Authentication.External 在类库下新建一个类QYWec ...

  6. 发布一个基于协程和事件循环的c++网络库

    目录 介绍 使用 性能 实现 日志库 协程 协程调度 定时器 Hook RPC实现 项目地址:https://github.com/gatsbyd/melon 介绍 开发服务端程序的一个基本任务是处理 ...

  7. Yoshino: 一个基于React的可定制化的PC组件库

    Github: https://github.com/Yoshino-UI... Docs: https://yoshino-ui.github.io/#/ Cli-Tool: https://git ...

  8. 一个基于Unix套接字的注册登录系统

    2016/5/5 今天,我参考<Unix网络编程-卷1>第5章的TCP回射客户/服务器程序写了一个简单的注册登录系统,其功能如下:(1)注册.客户端向服务器发送个人信息请求注册,服务器查询 ...

  9. AbpZero之企业微信---登录(拓展第三方auth授权登录)---第三步:需要注意事项

    1.AbpZero的auth登录会在数据库中的AbpUserLogins表会根据你登录的ProviderKey和Provider来生成生成一条记录,ProviderKey在表中是唯一的: 2.要登录成 ...

  10. AbpZero之企业微信---登录(拓展第三方auth授权登录)---第一步:查看AbpZero的auth第三方登录的底层机制

    在AbpZero框架中,auth登录接口位于Web.Core库下的Controllers文件夹的TokenAuthController.cs的ExternalAuthenticate方法 Extern ...

随机推荐

  1. 霍夫丁(Hoeffding)不等式证明

    马尔可夫不等式 结论 对于任意非负随机变量$X$,$\forall \epsilon>0$,有: $\displaystyle P(X\ge\epsilon)\le\frac{E(X)}{\ep ...

  2. Blazor 组件库 BootstrapBlazor 中Card组件介绍

    一个较为完整的Card样子 Card组件介绍 Card组件分为三部分,CardHeader.CardBody.CardFooter. 代码格式如下: <Card> <CardHead ...

  3. Codeforces Round 856 (Div2)

    Counting Factorizations 任何一个正整数 \(m\) 都可以被唯一的分解为 \(p_1^{e_1} \cdot p_2^{e_2} \ldots p_k^{e_k}\) 的形式. ...

  4. winform窗体无边框拖动

    1:引用命名空间 using System.Runtime.InteropServices; 2:想要拖动窗体的控件绑定MouseDown事件 点击查看代码 //窗体移动 [DllImport(&qu ...

  5. Kettle连接MySQL数据库时提示Driver class 'org.gjt.mm.mysql.Driver' could not be found

    使用Kettle连接MySQL数据库时,提示以下连接提示信息导致我们无法对数据库进行连接: Driver class 'org.gjt.mm.mysql.Driver' could not be fo ...

  6. 零基础学习人工智能—Python—Pytorch学习(十)

    前言 本文的内容是来自教程视频的第十五集,个人感觉,这个教程是有点虎头蛇尾,就是前面开始的教程,是非常惊人的好,但到这里,就有点水了,可以说就是把代码一铺,然后简单介绍一遍,很多细节都没有讲,所以,我 ...

  7. windbg 调试 c++ std::exception

    由于c++ std::exception在windbg里面调用堆栈显示不正确,可以通过加载了系统pdb和软件pdb后,!analyze -v可以分析出来,所有需要配置系统pdb. 1.把exe,pdb ...

  8. manim边做边学--淡入淡出

    本篇介绍Manim中的淡入和淡出动画效果. 淡入FadeIn 主要用于让对象以渐变的方式在场景中显现. 它的特点是视觉上柔和过渡,能自然地引导观众注意新出现的元素. 淡出FadeOut 则是使对象逐渐 ...

  9. docker创建Tomcat

    安装docker 查找tomcat docker search tomcat 下载镜像 docker pull tomcat 查看下载的镜像 docker images 运行Tomcat docker ...

  10. COS 音视频实践|播放多场景下的 COS 视频文件

    导语 上回 (COS音视频实践|多种姿势让你的视频"跑"起来)说道,基于您的实际场景,可以选择不同的方式,在 Web 浏览器端播放您的 COS 视频文件.本文将基于腾讯云超级播放器 ...