J'ai des points de terminaison dans l'API - /user/login
, /products
.
Dans Swagger UI, je poste email
et password
sur /user/login
et, en réponse, je reçois une chaîne token
.
Ensuite, je peux copier le jeton de la réponse et l'utiliser comme valeur d'en-tête Authorization
dans les demandes adressées à toutes les URL si elles sont présentes et à /products
à titre d'exemple.
Devrais-je créer une entrée de texte manuellement quelque part sur la page de l'interface utilisateur Swagger, puis placer le jeton à cet endroit et injecter les requêtes d'une manière ou d'une autre ou existe-t-il des outils pour mieux le gérer?
Vous pouvez ajouter un paramètre d'en-tête à votre demande et Swagger-UI l'affichera sous la forme d'une zone de texte modifiable:
swagger: "2.0"
info:
version: 1.0.0
title: TaxBlaster
Host: taxblaster.com
basePath: /api
schemes:
- http
paths:
/taxFilings/{id}:
get:
parameters:
- name: id
in: path
description: ID of the requested TaxFiling
required: true
type: string
- name: auth
in: header
description: an authorization header
required: true
type: string
responses:
200:
description: Successful response, with a representation of the Tax Filing.
schema:
$ref: "#/definitions/TaxFilingObject"
404:
description: The requested tax filing was not found.
definitions:
TaxFilingObject:
type: object
description: An individual Tax Filing record.
properties:
filingID:
type: string
year:
type: string
period:
type: integer
currency:
type: string
taxpayer:
type: object
Vous pouvez également ajouter une définition de sécurité de type apiKey
:
swagger: "2.0"
info:
version: 1.0.0
title: TaxBlaster
Host: taxblaster.com
basePath: /api
schemes:
- http
securityDefinitions:
api_key:
type: apiKey
name: api_key
in: header
description: Requests should pass an api_key header.
security:
- api_key: []
paths:
/taxFilings/{id}:
get:
parameters:
- name: id
in: path
description: ID of the requested TaxFiling
required: true
type: string
responses:
200:
description: Successful response, with a representation of the Tax Filing.
schema:
$ref: "#/definitions/TaxFilingObject"
404:
description: The requested tax filing was not found.
definitions:
TaxFilingObject:
type: object
description: An individual Tax Filing record.
properties:
filingID:
type: string
year:
type: string
period:
type: integer
currency:
type: string
taxpayer:
type: object
L'objet securityDefinitions
définit les schémas de sécurité.
L'objet security
(appelé "exigences de sécurité" dans Swagger – OpenAPI) applique un schéma de sécurité à un contexte donné. Dans notre cas, nous l'appliquons à l'intégralité de l'API en déclarant que l'exigence de sécurité est un niveau supérieur. Nous pouvons éventuellement le remplacer dans des éléments de chemin et/ou des méthodes individuels.
Ce serait le moyen privilégié de spécifier votre schéma de sécurité. et il remplace le paramètre d'en-tête du premier exemple. Malheureusement, Swagger-UI ne propose pas de zone de texte pour contrôler ce paramètre, du moins lors de mes tests jusqu'à présent.
Dans ASP.net WebApi, le moyen le plus simple de passer un en-tête sur l'interface utilisateur Swagger consiste à implémenter la méthode Apply(...)
sur l'interface IOperationFilter.
Ajoutez ceci à votre projet:
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "MyHeaderField",
@in = "header",
type = "string",
description = "My header field",
required = true
});
}
}
Dans SwaggerConfig.cs, enregistrez le filtre ci-dessus à l'aide de c.OperationFilter<>()
:
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "YourProjectName");
c.IgnoreObsoleteActions();
c.UseFullTypeNameInSchemaIds();
c.DescribeAllEnumsAsStrings();
c.IncludeXmlComments(GetXmlCommentsPath());
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
c.OperationFilter<AddRequiredHeaderParameter>(); // Add this here
})
.EnableSwaggerUi(c =>
{
c.DocExpansion(DocExpansion.List);
});
}
Dans ASP.NET Core 2 Web API
, en utilisant Swashbuckle.AspNetCore package 2.1.0, implémentez un IDocumentFilter:
SwaggerSecurityRequirementsDocumentFilter.cs
using System.Collections.Generic;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace api.infrastructure.filters
{
public class SwaggerSecurityRequirementsDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument document, DocumentFilterContext context)
{
document.Security = new List<IDictionary<string, IEnumerable<string>>>()
{
new Dictionary<string, IEnumerable<string>>()
{
{ "Bearer", new string[]{ } },
{ "Basic", new string[]{ } },
}
};
}
}
}
Dans Startup.cs, configurez une définition de sécurité et enregistrez le filtre personnalisé:
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
// c.SwaggerDoc(.....
c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
{
Description = "Authorization header using the Bearer scheme",
Name = "Authorization",
In = "header"
});
c.DocumentFilter<SwaggerSecurityRequirementsDocumentFilter>();
});
}
Dans l’interface utilisateur Swagger, cliquez sur le bouton Autoriser et définissez la valeur du jeton.
Résultat:
curl -X GET "http://localhost:5000/api/tenants" -H "accept: text/plain" -H "Authorization: Bearer ABCD123456"
Il est également possible d'utiliser l'attribut [FromHeader] pour les paramètres de méthodes Web (ou les propriétés d'une classe Model) qui doivent être envoyés dans des en-têtes personnalisés. Quelque chose comme ça:
[HttpGet]
public ActionResult Products([FromHeader(Name = "User-Identity")]string userIdentity)
Au moins, cela fonctionne bien pour ASP.NET Core 2.1 et Swashbuckle.AspNetCore 2.5.0.
Voici une réponse plus simple pour le combo ASP.NET Core Web Api/Swashbuckle, qui ne nécessite pas l’enregistrement de filtres personnalisés. La troisième fois est un charme, vous savez :).
L'ajout du code ci-dessous à votre configuration Swagger fera apparaître le bouton Autoriser, vous permettant de saisir un jeton de support à envoyer pour toutes les demandes. N'oubliez pas d'entrer ce jeton sous la forme Bearer <your token here>
lorsque vous y êtes invité.
Notez que le code ci-dessous enverra le jeton pour toutes les demandes et opérations, qui peuvent ou non correspondre à vos souhaits.
services.AddSwaggerGen(c =>
{
//...
c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = "header",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
//...
}
Via ce fil .
Pour ceux qui utilisent NSwag et ont besoin d'un en-tête personnalisé:
app.UseSwaggerUi3(typeof(Startup).GetTypeInfo().Assembly, settings =>
{
settings.GeneratorSettings.IsAspNetCore = true;
settings.GeneratorSettings.OperationProcessors.Add(new OperationSecurityScopeProcessor("custom-auth"));
settings.GeneratorSettings.DocumentProcessors.Add(
new SecurityDefinitionAppender("custom-auth", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.ApiKey,
Name = "header-name",
Description = "header description",
In = SwaggerSecurityApiKeyLocation.Header
}));
});
}
Swagger UI inclura alors un bouton Autoriser .
AVERTISSEMENT: cette solution est pas en utilisant l'en-tête.
Si quelqu'un recherche une manière paresseuse-paresseuse (également dans WebApi), je suggérerais:
public YourResult Authorize([FromBody]BasicAuthCredentials credentials)
Vous ne recevez pas d'en-tête, mais au moins vous avez une alternative facile. Vous pouvez toujours vérifier si l'objet est null et utiliser le mécanisme d'en-tête.
Je me suis retrouvé ici parce que j'essayais d'ajouter conditionnellement des paramètres d'en-tête dans l'interface utilisateur Swagger, en fonction de mon propre attribut [Authentication]
que j'avais ajouté à ma méthode API. Suite à l’allusion que @Corcus a énumérée dans un commentaire, j’ai pu déduire ma solution et, espérons-le, aider les autres.
À l'aide de Reflection, il vérifie si la méthode imbriquée dans apiDescription
a l'attribut souhaité (MyApiKeyAuthenticationAttribute, dans mon cas). Si c'est le cas, je peux ajouter les paramètres d'en-tête souhaités.
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) {
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
var attributes = ((System.Web.Http.Controllers.ReflectedHttpActionDescriptor)
((apiDescription.ActionDescriptor).ActionBinding.ActionDescriptor)).MethodInfo
.GetCustomAttributes(false);
if(attributes != null && attributes.Any()) {
if(attributes.Where(x => x.GetType()
== typeof(MyApiKeyAuthenticationAttribute)).Any()) {
operation.parameters.Add(new Parameter {
name = "MyApiKey",
@in = "header",
type = "string",
description = "My API Key",
required = true
});
operation.parameters.Add(new Parameter {
name = "EID",
@in = "header",
type = "string",
description = "Employee ID",
required = true
});
}
}
}
Exemple Golang/go-swagger: https://github.com/go-swagger/go-swagger/issues/1416
// swagger:parameters opid
type XRequestIdHeader struct {
// in: header
// required: true
XRequestId string `json:"X-Request-Id"`
}
...
// swagger:operation POST /endpoint/ opid
// Parameters:
// - $ref: #/parameters/XRequestIDHeader