首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Swashbuckle .NET Core2中JWT承载的授权

Swashbuckle .NET Core2中JWT承载的授权
EN

Stack Overflow用户
提问于 2018-02-26 09:33:57
回答 3查看 10.4K关注 0票数 10

我将身份验证服务生成的令牌用于我的应用程序。这没什么问题。现在,我已经引入Swashbuckle来记录我的API,我可以通过使用下面的代码向每个请求发送JWT来进行如下身份验证;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
services.AddSwaggerGen(c =>
{
    var a = new ApiKeyScheme();
    //c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
    //{ In = "header", Description = "Please insert JWT with Bearer into field", Name = "Authorization", Type = "apiKey" });

    c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();

    c.SwaggerDoc("v2", new Info
    {
        Version = "v2",
        Title = "MyTitle",
        Description = "An interface for ...",
        TermsOfService = "None",
        Contact = new Contact() { Name = "MyApp", Email = "a@example.com", Url = "www.example.com" }
    });
    // Set the comments path for the Swagger JSON and UI.
    var basePath = AppContext.BaseDirectory;
    var xmlPath = Path.Combine(basePath, "cpDataCore.xml");
    c.IncludeXmlComments(xmlPath);
});

public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
        var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
        var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);

        if (isAuthorized && !allowAnonymous)
        {
            if (operation.Parameters == null)
                operation.Parameters = new List<IParameter>();

            operation.Parameters.Add(new NonBodyParameter
            {
                Name = "Authorization",
                In = "header",
                Description = "access token",
                Required = true,
                Type = "string"
            });
        }
    }
}

这给了我下面的头--不出所料

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
accept:application/json
Accept-Encoding:gzip, deflate, br
Accept-Language:en-AU,en;q=0.9
Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9naXZlbm5hbWUiOiJEZW5uaXMiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zdXJuYW1lIjoiR2FzY29pZ25lIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZSI6ImRlbm5pc2ciLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zaWQiOiI1NCIsIlJlZnJlc2hUb2tlbiI6IjY5OTA1NTFmLTNhOTQtNDVmYi1hYjc2LTZlOTQyNGE3NjJmOCIsIkFsbERhdGFSZWFkT25seUZvckFwcHJvdmVycyI6IlRydWUiLCJQcm9qZWN0SUQiOiI2IiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoic3lzYWRtaW4iLCJuYmYiOjE1MTk2MzY2NDIsImV4cCI6MTUxOTYzODQ0MiwiaXNzIjoiaHR0cHM6Ly9kYXRhLmNpdmlscHJvc29mdHdhcmUuY29tLyIsImF1ZCI6Imh0dHBzOi8vcm1zLmNpdmlscHJvc29mdHdhcmUuY29tLyJ9.nBEZgzcmZVGhFJmKI8u7p7g7xPU13HEAGJu_lrWylnc
Connection:keep-alive
Cookie:username=demo; jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9naXZlbm5hbWUiOiJUcm95IiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvc3VybmFtZSI6IkVsZGVyIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZSI6InRyb3kiLCJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zaWQiOiI1IiwiUmVmcmVzaFRva2VuIjoiMTNhNzRmNDQtNmVmOC00MDQ3LTlmYWYtOWQ3MzI4MmNhZjQ4IiwiUHJvamVjdElEIjoiLTEiLCJuYmYiOjE1MDUwOTc3MjEsImV4cCI6MTUwNTA5ODYyMSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo2MDAwMC8iLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjYwMDAwLyJ9.8You0XiUlvdHb2TRuDzaiXv6r74v7ga1Av_Z3ikmblU
Host:localhost:60000
Referer:http://localhost:60000/swagger/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36

虽然,我不确定Cookie是从哪里来的。这与我的代码没有任何关系。我只是忽略它--到目前为止一切都很好。

问题是,这意味着每个请求都必须输入令牌,这是一件痛苦的事情。理想情况下,我希望使用内置的swagger接口进行身份验证-根据几篇文章,我应该能够做到这一点;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
{ In = "header", Description = "Please insert JWT with Bearer into field", Name = "Authorization", Type = "apiKey" });

这可以很好地工作,我可以添加令牌,只是似乎缺少一个步骤来将令牌添加到每个请求的头部。如果我只是添加auth,那么就会得到下面的头信息,这当然会导致身份验证失败。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
GET /api/ApprovalItemTypes HTTP/1.1
Host: localhost:60000
Connection: keep-alive
accept: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36
Referer: http://localhost:60000/swagger/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-AU,en;q=0.9
Cookie: username=demo; jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW5_xxx__LTEiLCJuYmYiOjE1MDUwOTc3MjEsImV4cCI6MTUwNTA5ODYyMSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo2MDAwMC8iLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjYwMDAwLyJ9.8You0XiUlvdHb2TRuDzaiXv6r74v7ga1Av_Z3ikmblU

为了让请求包含每个后续请求的令牌,我还需要做些什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-04-22 04:04:06

最后,我转到了NSwag,所以我不确定最初的问题是什么。Nswag中的解决方案如下;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    services.AddSwaggerDocument(document =>
        {
            document.DocumentName = "CPSwagger";
            document.Title = "My Mobile API";
            document.Version = "v10.3.4";
            document.Description = "An interface for some software.";

            document.DocumentProcessors.Add(
                new SecurityDefinitionAppender("JWT token", new NSwag.OpenApiSecurityScheme
                {
                    Type = NSwag.OpenApiSecuritySchemeType.ApiKey,
                    Name = "Authorization",
                    Description = "Copy 'Bearer ' + valid JWT token into field",
                    In = NSwag.OpenApiSecurityApiKeyLocation.Header
                }));
            document.OperationProcessors.Add(new OperationSecurityScopeProcessor("JWT token"));
        });
票数 0
EN

Stack Overflow用户

发布于 2018-03-19 17:22:28

如果您在您的方法上指定了过滤器,Swagger将添加authorzation头。如果您在全局范围内需要授权,我猜swagger无法识别它们。

您需要在ConfigureServices中添加一个如下所示的SecurityRequirement:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>()
{
  { "Bearer", new string[]{ } }
});

如果设置了令牌,这将要求在每个请求中使用发送报头。如果您没有设置标题之前,它将不会发送它,但您仍然会有挂锁标志旁边的api描述。

票数 1
EN

Stack Overflow用户

发布于 2019-02-14 17:32:11

如果您在代码中定义

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
c.AddSecurityDefinition("jwt", new ApiKeyScheme()
{ 
   In = "header", Description = "Please insert JWT with Bearer into field", Name = "Authorization", Type = "apiKey" });

然后在.Security中而不是在.Parameters中使用它

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
operation.Security = new List<IDictionary<string, IEnumerable<string>>> {
            new Dictionary<string, IEnumerable<string>>
            {
                {"jwt", _scopes }
            }

那么一切都应该正常工作:

我做的和你做的一样,但是你应该添加如下内容(对于oauth2或jwt持有者令牌身份验证):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static class ServiceCollectionExtension
{
    private static string XmlCommentsFilePath
    {
        get
        {
            var basePath = PlatformServices.Default.Application.ApplicationBasePath;
            var fileName = Assembly.GetEntryAssembly().GetName().Name + ".xml";
            return Path.Combine(basePath, fileName);
        }
    }

    public static void AddMySwagger(
        this IServiceCollection services,
        ApiVersion defaultApiVersion,
        Func<ApiVersionDescription, Info> info,
        string authority = null,
        Dictionary<string, string> scopes = null)
    {
        services.AddMvcCore().AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV");

        services.AddApiVersioning(o =>
        {
            o.ReportApiVersions = true;
            o.AssumeDefaultVersionWhenUnspecified = true;
            o.DefaultApiVersion = defaultApiVersion;
        });

        services.AddSwaggerGen(
            options =>
            {
                var provider = services.BuildServiceProvider()
                    .GetRequiredService<IApiVersionDescriptionProvider>();

                foreach (var description in provider.ApiVersionDescriptions)
                {
                    if (!description.IsDeprecated)
                        options.SwaggerDoc(description.GroupName, info(description));
                }

                options.OperationFilter<DefaultValues>();

                options.IncludeXmlComments(XmlCommentsFilePath);

                if (!string.IsNullOrEmpty(authority))
                {
                    options.AddSecurityDefinition("jwt", new ApiKeyScheme()
                    {
                        Description = "JWT Authorization header using the Bearer scheme. Example: \"Bearer {token}\"",
                        Name = "Authorization",
                        In = "header",
                        Type = "apiKey"
                    });
                    //options.AddSecurityDefinition("oauth2", new OAuth2Scheme
                    //{
                    //  Flow = "implicit",
                    //  AuthorizationUrl = $"{authority}/connect/authorize",
                    //  Scopes = scopes ?? new Dictionary<string, string>()
                    //});
                    options.OperationFilter<AuthorizeCheckOperationFilter>(scopes?.Select(_ => _.Key).ToList() ?? new List<string>());
                }
            });
    }

    class AuthorizeCheckOperationFilter : IOperationFilter
    {
        private readonly IEnumerable<string> _scopes;

        public AuthorizeCheckOperationFilter(IEnumerable<string> scopes)
        {
            _scopes = scopes;
        }

        public void Apply(Operation operation, OperationFilterContext context)
        {
            var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType<AuthorizeAttribute>().Any() ||
                               context.ApiDescription.ActionAttributes().OfType<AuthorizeAttribute>().Any();

            if (hasAuthorize)
            {
                operation.Responses.Add("401", new Response { Description = "Unauthorized" });
                operation.Responses.Add("403", new Response { Description = "Forbidden" });

                operation.Security = new List<IDictionary<string, IEnumerable<string>>> {
                new Dictionary<string, IEnumerable<string>>
                {
                    //{"oauth2", _scopes},
                    {"jwt", _scopes }
                }
            };
            }
        }
    }
}

用法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        services.AddMySwagger(
            new ApiVersion(1, 0),
            __description => new Info { Title = $"API v{__description.ApiVersion}", Version = __description.ApiVersion.ToString() },
            Configuration.GetValue<string>("Authentication:Authority"),
            new Dictionary<string, string> { { Configuration.GetValue<string>("Authentication:Scope"), "Partnership API" } }
        );
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48985240

复制
相关文章
SQL Server数据仓库的基础架构规划
SQL Server数据仓库具有自己的特征和行为属性,有别去其他。从这个意义上说,数据仓库基础架构规划需要与标准SQL Server OLTP数据库系统的规划不同。在本文中,我们将介绍在计划数据仓库时应该考虑的一些事项。
用户1217611
2019/05/25
1.8K0
这是Blazor上传文件的最佳方式吗?
Blazor不得不说真是好东西,极大的提升了开发效率,很多的页面交互功能基本上只需要写很少的代码就能实现了,而且还是无js实现,你也绝对没有想到过,Blazor实现文件上传是有多么简单!
沙漠尽头的狼
2022/03/26
1.4K0
这是Blazor上传文件的最佳方式吗?
和我从头学SQL Server Integration Services
本人一个IT屌丝男,一直在ITPRO的圈子里面混着,从来不是一个程序猿,水平就是开开关关windows的水平。昏昏然,成了一个油腻的大叔,但我的内心和业务水平还是停留在26岁啊! 周围的同事好友一个个都一日千里的学习进步着,实在看不下去自己了,决定整理整理,给自己,给儿子摆一个努力学习的POSE出来。
盆盆
2019/04/24
3.3K0
和我从头学SQL Server Integration Services
「集成架构」2020年最好的15个ETL工具(第一部)
ETL代表提取、转换和加载。它是从任何数据源中提取数据并将其转换为适当格式以供存储和将来参考的过程。
架构师研究会
2021/01/06
4.2K0
「集成架构」2020年最好的15个ETL工具(第一部)
微服务之间的最佳调用方式
在微服务架构中,需要调用很多服务才能完成一项功能。服务之间如何互相调用就变成微服务架构中的一个关键问题。
Bug开发工程师
2020/03/16
8010
微服务之间的最佳调用方式
微服务之间的最佳调用方式
在微服务架构中,需要调用很多服务才能完成一项功能。服务之间如何互相调用就变成微服务架构中的一个关键问题。
用户1516716
2019/12/26
3.4K0
SSIS 关于并发的两个设置
MaxConcurrentExecutables, a package level property in SSIS determines the number of control flow items that can be executed in parallel. The default value is -1. This is equivalent to number of processors (logical and physical) plus 2.
全栈程序员站长
2022/07/05
6930
SSIS 关于并发的两个设置
使用 SQL NOWAIT 的最佳方式
摘要:SQL NOWAIT使我们能够在获取行级锁时避免阻塞,本文中我们将学会使用这个功能最佳方法。
姚远OracleACE
2023/04/06
1K0
使用 SQL NOWAIT 的最佳方式
Android开发(25) 两个App之间使用intent交换数据
两个App之间如何进行数据交换,像“使用intent调用系统自带的拍照应用并获得结果” 是一种很方便的形式。 它发送一个 Intent,这个Intent指明启动了另外一个App,完成任务后指定返回结果,原先的App接收返回的结果。
张云飞Vir
2020/03/16
1.6K0
不用 SQL 的数据仓库
当前绝大部分数据仓库都会采用 SQL,SQL 发展了几十年已经成为数据库界的标准语言,用户量巨大,所以支持 SQL 对于数据仓库来讲也是很正常的。但是,在当代大数据背景下,业务复杂度节节攀升,在以计算为主要任务的数据仓库场景下,SQL 似乎越来越不够用了。典型表现是一些数据仓库开始集成 Python 的能力,将 Python 这样的非 SQL 语言融入到数据仓库中。且不论两种风格迥异的开发语言是否能很好融合互补,单看这样的趋势已经足够表现出业界对 SQL 能力的一些质疑。
搜云库技术团队
2023/10/21
2200
不用 SQL 的数据仓库
介绍几种SSIS部署方式
介绍     如果你已经开发完一个不错的SSIS包并且能够在你的本地完美的运行,每个任务都亮起绿色的通过标志。这时为了能够让这个包处理能够在指定时间运行,你需要将其发布到一个服务器上,并做好相关配置。作为开发人员可能我们不能直接在生产环境去做这个事情,这需要我们有一个开发或者测试环境来完成整个部署测试,因为DBA有时候不会允许你去直接访问生产环境。     本篇将介绍几种从本地到服务器的部署包的方法。SQLServer 2012中引入的项目部署模型不再重复记述了,因为SSIS2012的报部署模型也是用来相似
用户1217611
2018/01/30
1.8K0
介绍几种SSIS部署方式
SQL Server仓储物流公司visual studio发货数据仓库设计
仓储物流是货物生产销售的重要环节。随着贸易自由化和电子商务的兴起,物流企业快速发展,为提高仓库管理效率,发掘更多的仓库供应商客户,合理配置资源并降低经营成本,经营者在制定经营决策时需要分析仓储物流过程的整个环节的数据,然而在业务系统中的数据是按照业务过程进行组织的,处于孤立分散的状态并不适用于数据的统计和分析。在仓储物流系统上建立数据仓库,按照用于决策分析的主题对不同系统中数据进行重新组织,为数据分析和数据挖掘提供有效的数据来源。
拓端
2023/04/24
3090
怎样在SQL Server数据库执行sql脚本?
注意:在操作前需要先把数据库的数据进行备份,以防数据出错,导致数据库损坏!(找到数据库,右键备份,选择备份输出的位置即可。)
管家婆软件
2022/11/21
18K0
怎样在SQL Server数据库执行sql脚本?
一般数据库增量数据处理和数据仓库增量数据处理的几种策略
通常在数据量较少的情况下,我们从一个数据源将全部数据加载到目标数据库的时候可以采取的策略可以是:先将目标数据库的数据全部清空掉,然后全部重新从数据源加载进来。这是一个最简单并且最直观的并且不容易出错的一种解决方案,但是在很多时候会带来性能上的问题。
用户8949263
2022/04/08
3.2K0
一般数据库增量数据处理和数据仓库增量数据处理的几种策略
【FinTech】机器学习是发展金融科技公司的最佳方式吗?
今天,机器学习在金融生态系统的许多阶段扮演着不可或缺的角色。 从审批贷款到管理资产,评估风险。 然而,只有少数技术娴熟的专业人员能准确了解ML如何进入日常金融生活。 现在,由于机器学习,欺诈检测变得容易。 最近的技术进步使金融机构能够探索机器学习技术在客户服务,个人理财和财富管理以及欺诈和风险管理等领域的应用。
陆勤_数据人网
2018/07/30
8680
【FinTech】机器学习是发展金融科技公司的最佳方式吗?
在Python中操纵json数据的最佳方式
在日常使用Python的过程中,我们经常会与json格式的数据打交道,尤其是那种嵌套结构复杂的json数据,从中抽取复杂结构下键值对数据的过程枯燥且费事。
朱卫军 AI Python
2022/04/03
4K0
在Python中操纵json数据的最佳方式
如何将生产环境的字段类型从INT修改为BIGINT
介绍 改变数据类型是一个看起来很简单的事情,但是如果表非常大或者有最小停机时间的要求,又该如何处理那?这里我提供一个思路来解决这个问题。 背景 在一个常规SQL Server heath检查中,使用sp_blitz,我们最大的生产表之一引发了令人担忧的警报。保存客户订单信息的表的ID列是一个INT datatype,很快就将达到最大值。 这个表大约有500GB,有超过9亿行。根据在该表上每天的平均插入数,我估计未来八个月后,在这张表上的插入将会溢出。这是一个订单输入表,由于客户的活动,需要24小时的插入。一
用户1217611
2018/03/29
5.1K0
如何将生产环境的字段类型从INT修改为BIGINT
ETL产品、ETL工具、E T L技术 三者啥关联?
1、产品—为了满足市场需要,而创建的用于运营的功能及服务”就是产品。产品是以使用为目的物品和服务的综合体。产品分类:服务、软件、硬件、流程性材料。其中这里提供的是软件。
用户8369250
2021/03/08
1.2K0
如何将生产环境的字段类型从INT修改为BIGINT
改变数据类型是一个看起来很简单的事情,但是如果表非常大或者有最小停机时间的要求,又该如何处理那?这里我提供一个思路来解决这个问题。
全栈程序员站长
2021/11/29
3K0
如何将生产环境的字段类型从INT修改为BIGINT
SQL练习之两个列值的交换
SELECT * FROM dbo.test2 现在我们将Province列值和Company列值互换,代码如下: UPDATE test2 SET Company=Province, Provin
郑小超.
2018/01/24
3.6K0
SQL练习之两个列值的交换

相似问题

在两个SQL Server 2008表之间复制海量数据的最佳方式

112

SQL Server在行之间交换数据问题

11

在SQL Server中处理数据的最佳方式?

20

在两个位置之间传输(小型) SQL Server数据库的最佳方式是什么?

26

在sql脚本中在两个XML文件之间交换数据?

12
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文