ASP Net Core 2.2 仅向需要授权的方法添加储物柜图标 - Swagger UI
ASP Net Core 2.2 add locker icon only to methods that require authorization - Swagger UI
版本:
- ASP 网络核心网络 API - 2.2
- Swashbuckle.AspNetCore - 4.0.1
我现在有什么?
我在我的 Web API 项目中实现了 swagger。我在需要它的方法上使用带有 [Authorize]
属性的 JWT 授权。
所以我想要一种简单的方法来发送需要授权的请求。在我的 ConfigureServices
class 中,我添加了以下逻辑。
services.AddSwaggerGen(c =>
{
// Other swagger options
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
In = "header",
Description = "Please enter into field the word 'Bearer' following by space and your JWT token",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", Enumerable.Empty<string>() },
});
// Other swagger options
});
它的作用如下:
它大摇大摆地添加了一个新按钮——授权。
问题是,它还在每个方法旁边添加了一个 "open" 储物柜图标。尽管如此,其中一些需要授权。
当我使用授权按钮成功授权时(它基本上为每个请求添加了 header 授权),我在所有这些请求上都收到了一个 "closed" 储物柜。
我知道这可能是指示将通过请求发送授权令牌的功能。我想要一种方法来显示哪些方法需要授权,哪些不需要。
我想要什么?
例如,用于匿名方法的 "open" 储物柜和用于具有 [Authorize]
属性的方法的 "closed" 储物柜。
它可能是一个额外的图标,在这个旁边或者修改这个的行为,没问题。我怎样才能做到这一点?
可能的解决方案?
我相信一个可能的解决方案是制作一个 OperationFilter 并遍历所有方法并将 "something" 仅附加到那些具有 [Authorize]
属性的方法。这是最好的解决方案吗?如果是这样,您将如何实施?
距离问这个已经一个多月了。我是这样做的。
我从 Startup.cs
中删除了以下代码:
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
In = "header",
Description = "Please enter into field the word 'Bearer' following by space and your JWT token",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", Enumerable.Empty<string>() },
});
并且我添加了以下内容:
c.OperationFilter<AddAuthHeaderOperationFilter>();
当然还有 AddAuthHeaderOperationFilter.cs
:
public class AddAuthHeaderOperationFilter : IOperationFilter
{
private readonly IHttpContextAccessor httpContextAccessor;
public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public void Apply(Operation operation, OperationFilterContext context)
{
var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterDescriptor.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 = "JWT access token",
Required = true,
Type = "string",
//Default = $"Bearer {token}"
});
operation.Responses.Add("401", new Response { Description = "Unauthorized" });
operation.Responses.Add("403", new Response { Description = "Forbidden" });
operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
//Add JWT bearer type
operation.Security.Add(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
}
}
}
简而言之,此 OperationFilter class 仅将储物柜图标添加到需要授权的方法。储物柜总是打开的。所以不是完美的解决方案,但目前还可以。
外观如下:
注意:所以如果你想测试API,你先得到一个令牌,然后在需要的地方填写。
对于 Swashbuckle 5.0.0 及更高版本的 AddAuthHeaderOperationFilter,@G.Dimov 的回答更改为以下内容(进行了一些额外的样式编辑):
public class AddAuthHeaderOperationFilter : IOperationFilter
{
private readonly IHttpContextAccessor httpContextAccessor;
public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public void Apply(Operation operation, OperationFilterContext context)
{
var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterDescriptor.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 = "JWT access token",
Required = true,
Type = "string"
});
operation.Responses.Add("401", new Response { Description = "Unauthorized" });
operation.Responses.Add("403", new Response { Description = "Forbidden" });
operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
//Add JWT bearer type
operation.Security.Add(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
}
}
}
编辑
Swagger UI 拒绝发送授权 header 如果它被定义为参数。所以可能更好的选择是在 SwaggerGen 服务配置中创建一个安全定义(通常在 Startup.ConfigureServices 中):
public void ConfigureServices(IServiceCollection services)
{
// Service configuration
services.AddSwaggerGen(c =>
{
// Configure Swagger
// "Bearer" is the name for this definition. Any other name could be used
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "Use bearer token to authorize",
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT"
});
}
}
然后添加对操作定义的引用的安全要求:
public class AddAuthorizationHeaderOperationHeader : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;
var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);
var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);
if (!isAuthorized || allowAnonymous)
{
return;
}
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Security = new List<OpenApiSecurityRequirement>();
//Add JWT bearer type
operation.Security.Add(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
// Definition name.
// Should exactly match the one given in the service configuration
Id = "Bearer"
}
}, new string[0]
}
}
);
}
}
请按照以下步骤使用正确的挂锁实施 Swagger-
步数-1
添加一个class并继承这个class与IOperationFilter
接口。
之后,实现IOperationFilter
接口的Apply
方法定义。
要实现 Apply
方法,您需要两个类型为 OpenApiOperation
和 OpenApiOperation
的参数。
public class AddSwaggerService : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;
var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);
var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);
if (!isAuthorized || allowAnonymous)
{
return;
}
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Security = new List<OpenApiSecurityRequirement>();
var security = new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
}, new List<string>()
}
};
//add security in here
operation.Security.Add(security);
}
步骤 - 2
在Startup.cs
中的ConfigureServices
方法中添加swagger Generation Service
。在此服务中,您需要添加我们在步骤 1 中实施的以下行。
c.OperationFilter<AddSwaggerService>();
public void ConfigureServices(IServiceCollection services)
{
//.........other Services.........
//.........other Services.........
//.........other Services.........
services.AddSwaggerGen(c =>
c.SwaggerDoc(AppConstantKeys.APIName, new OpenApiInfo { Title = "title", Version = "APIVersion" });
c.OperationFilter<AddSwaggerService>();
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description ="SwaggerShortDescription",
Name = "HeaderName",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
});
});
//.........other Services.........
//.........other Services.........
//.........other Services.........
}
第三步
在中间件管道中添加招摇。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerUIName");
c.DocumentTitle = "SwaggerUITitle";
c.DocExpansion(DocExpansion.None);
c.RoutePrefix = string.Empty;
});
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
}
步骤- 4
构建并 运行.
版本:
- ASP 网络核心网络 API - 2.2
- Swashbuckle.AspNetCore - 4.0.1
我现在有什么?
我在我的 Web API 项目中实现了 swagger。我在需要它的方法上使用带有 [Authorize]
属性的 JWT 授权。
所以我想要一种简单的方法来发送需要授权的请求。在我的 ConfigureServices
class 中,我添加了以下逻辑。
services.AddSwaggerGen(c =>
{
// Other swagger options
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
In = "header",
Description = "Please enter into field the word 'Bearer' following by space and your JWT token",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", Enumerable.Empty<string>() },
});
// Other swagger options
});
它的作用如下:
它大摇大摆地添加了一个新按钮——授权。
问题是,它还在每个方法旁边添加了一个 "open" 储物柜图标。尽管如此,其中一些需要授权。
当我使用授权按钮成功授权时(它基本上为每个请求添加了 header 授权),我在所有这些请求上都收到了一个 "closed" 储物柜。
我知道这可能是指示将通过请求发送授权令牌的功能。我想要一种方法来显示哪些方法需要授权,哪些不需要。
我想要什么?
例如,用于匿名方法的 "open" 储物柜和用于具有 [Authorize]
属性的方法的 "closed" 储物柜。
它可能是一个额外的图标,在这个旁边或者修改这个的行为,没问题。我怎样才能做到这一点?
可能的解决方案?
我相信一个可能的解决方案是制作一个 OperationFilter 并遍历所有方法并将 "something" 仅附加到那些具有 [Authorize]
属性的方法。这是最好的解决方案吗?如果是这样,您将如何实施?
距离问这个已经一个多月了。我是这样做的。
我从 Startup.cs
中删除了以下代码:
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
In = "header",
Description = "Please enter into field the word 'Bearer' following by space and your JWT token",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", Enumerable.Empty<string>() },
});
并且我添加了以下内容:
c.OperationFilter<AddAuthHeaderOperationFilter>();
当然还有 AddAuthHeaderOperationFilter.cs
:
public class AddAuthHeaderOperationFilter : IOperationFilter
{
private readonly IHttpContextAccessor httpContextAccessor;
public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public void Apply(Operation operation, OperationFilterContext context)
{
var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterDescriptor.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 = "JWT access token",
Required = true,
Type = "string",
//Default = $"Bearer {token}"
});
operation.Responses.Add("401", new Response { Description = "Unauthorized" });
operation.Responses.Add("403", new Response { Description = "Forbidden" });
operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
//Add JWT bearer type
operation.Security.Add(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
}
}
}
简而言之,此 OperationFilter class 仅将储物柜图标添加到需要授权的方法。储物柜总是打开的。所以不是完美的解决方案,但目前还可以。
外观如下:
注意:所以如果你想测试API,你先得到一个令牌,然后在需要的地方填写。
对于 Swashbuckle 5.0.0 及更高版本的 AddAuthHeaderOperationFilter,@G.Dimov 的回答更改为以下内容(进行了一些额外的样式编辑):
public class AddAuthHeaderOperationFilter : IOperationFilter
{
private readonly IHttpContextAccessor httpContextAccessor;
public AddAuthHeaderOperationFilter(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public void Apply(Operation operation, OperationFilterContext context)
{
var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterDescriptor.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 = "JWT access token",
Required = true,
Type = "string"
});
operation.Responses.Add("401", new Response { Description = "Unauthorized" });
operation.Responses.Add("403", new Response { Description = "Forbidden" });
operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
//Add JWT bearer type
operation.Security.Add(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
}
}
}
编辑
Swagger UI 拒绝发送授权 header 如果它被定义为参数。所以可能更好的选择是在 SwaggerGen 服务配置中创建一个安全定义(通常在 Startup.ConfigureServices 中):
public void ConfigureServices(IServiceCollection services)
{
// Service configuration
services.AddSwaggerGen(c =>
{
// Configure Swagger
// "Bearer" is the name for this definition. Any other name could be used
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "Use bearer token to authorize",
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT"
});
}
}
然后添加对操作定义的引用的安全要求:
public class AddAuthorizationHeaderOperationHeader : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;
var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);
var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);
if (!isAuthorized || allowAnonymous)
{
return;
}
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Security = new List<OpenApiSecurityRequirement>();
//Add JWT bearer type
operation.Security.Add(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
// Definition name.
// Should exactly match the one given in the service configuration
Id = "Bearer"
}
}, new string[0]
}
}
);
}
}
请按照以下步骤使用正确的挂锁实施 Swagger-
步数-1
添加一个class并继承这个class与IOperationFilter
接口。
之后,实现IOperationFilter
接口的Apply
方法定义。
要实现 Apply
方法,您需要两个类型为 OpenApiOperation
和 OpenApiOperation
的参数。
public class AddSwaggerService : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var actionMetadata = context.ApiDescription.ActionDescriptor.EndpointMetadata;
var isAuthorized = actionMetadata.Any(metadataItem => metadataItem is AuthorizeAttribute);
var allowAnonymous = actionMetadata.Any(metadataItem => metadataItem is AllowAnonymousAttribute);
if (!isAuthorized || allowAnonymous)
{
return;
}
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Security = new List<OpenApiSecurityRequirement>();
var security = new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
}, new List<string>()
}
};
//add security in here
operation.Security.Add(security);
}
步骤 - 2
在Startup.cs
中的ConfigureServices
方法中添加swagger Generation Service
。在此服务中,您需要添加我们在步骤 1 中实施的以下行。
c.OperationFilter<AddSwaggerService>();
public void ConfigureServices(IServiceCollection services)
{
//.........other Services.........
//.........other Services.........
//.........other Services.........
services.AddSwaggerGen(c =>
c.SwaggerDoc(AppConstantKeys.APIName, new OpenApiInfo { Title = "title", Version = "APIVersion" });
c.OperationFilter<AddSwaggerService>();
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description ="SwaggerShortDescription",
Name = "HeaderName",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
});
});
//.........other Services.........
//.........other Services.........
//.........other Services.........
}
第三步 在中间件管道中添加招摇。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "SwaggerUIName");
c.DocumentTitle = "SwaggerUITitle";
c.DocExpansion(DocExpansion.None);
c.RoutePrefix = string.Empty;
});
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
//.........other middlewares.........
}
步骤- 4
构建并 运行.