Wie sende ich benutzerdefinierte Header mit Anfragen in der Swagger-Benutzeroberfläche?

78

Ich habe einige Endpunkte in der API - /user/login, /products.

In der Swagger-Benutzeroberfläche poste ich emailund passwordan /user/loginund als Antwort erhalte ich eine tokenZeichenfolge.

Dann kann ich das Token aus der Antwort kopieren und möchte es als AuthorizationHeader-Wert in Anforderungen an alle URLs verwenden, sofern vorhanden, und /productsals Beispiel.

Sollte ich irgendwo auf der Swagger-UI-Seite manuell eine Texteingabe erstellen, dann das Token dort ablegen und die Anforderungen irgendwie einfügen, oder gibt es Tools, um es besser zu verwalten?

Sergei Basharov
quelle

Antworten:

54

Sie können Ihrer Anfrage einen Header-Parameter hinzufügen, und Swagger-UI zeigt ihn als bearbeitbares Textfeld an:

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

Swagger-UI mit Textfeld auth param

Sie können auch eine Sicherheitsdefinition mit dem Typ hinzufügen 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

Das securityDefinitionsObjekt definiert Sicherheitsschemata.

Das securityObjekt (in Swagger-OpenAPI als "Sicherheitsanforderungen" bezeichnet) wendet ein Sicherheitsschema auf einen bestimmten Kontext an. In unserem Fall wenden wir es auf die gesamte API an, indem wir die Sicherheitsanforderung als oberste Ebene deklarieren. Wir können es optional innerhalb einzelner Pfadelemente und / oder Methoden überschreiben.

Dies ist die bevorzugte Methode zur Angabe Ihres Sicherheitsschemas. und es ersetzt den Header-Parameter aus dem ersten Beispiel. Leider bietet Swagger-UI kein Textfeld zur Steuerung dieses Parameters, zumindest in meinen bisherigen Tests.

Ted Epstein
quelle
1
Ich definiere die Parameter im Python-Modul, das Endpunkte definiert, mithilfe von Modellen, mit denen ich RequestParsedann auch Eingabefelder in die Swagger-Dokumentation einfüge. Wie und wo soll diese Textdatei `- name: auth` hinzufügen?
Chang Zhao
61

In ASP.net WebApi besteht die einfachste Möglichkeit, einen Header auf der Swagger-Benutzeroberfläche zu übergeben, darin, die Apply(...)Methode auf der IOperationFilter- Schnittstelle zu implementieren .

Fügen Sie dies Ihrem Projekt hinzu:

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
        });
    }
}

Registrieren Sie in SwaggerConfig.cs den Filter von oben mit 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);
        });
}
ShaTin
quelle
1
Hallo, danke, dass du das geteilt hast, es ist genau das, was ich brauchte. Gibt es eine Möglichkeit, es für bestimmte API-Methoden zu deaktivieren? Zum Beispiel würde der Benutzer Login nicht benötigt, dass dieser Header als Rückgabe des Auth-Tokens übergeben wird. Dies fügt allen API-Methoden-Swagger-Dokumenten das 'MyHeaderField' hinzu.
Neil Hodges
@NeilHodges hast du das herausgefunden? Ich suche es sogar.
gee'K'iran
2
@ gee'K'iran Sie können die Funktionalität selektiv anwenden, indem Sie die Operations- und apiDescription-Parameter überprüfen und auswählen, ob der Header hinzugefügt werden soll oder nicht.
Corcus
@Corcus Verstanden. Vielen Dank.
gee'K'iran
20

In ASP.NET Core 2 Web API, mit Swashbuckle.AspNetCore Paket 2.1.0, implementieren eine 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[]{ } },
                }
            };
        }
    }
}

Konfigurieren Sie in Startup.cs eine Sicherheitsdefinition und registrieren Sie den benutzerdefinierten Filter:

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>();
    });
}

Klicken Sie in der Swagger-Benutzeroberfläche auf die Schaltfläche Autorisieren und legen Sie den Wert für das Token fest.

Fenster zum Einstellen des Wertes

Ergebnis:

curl -X GET "http://localhost:5000/api/tenants" -H "accept: text/plain" -H "Authorization: Bearer ABCD123456"
gpaoli
quelle
Um welche Prahlerversion handelt es sich? Hier in Swagger 2.4.0 kann die Schaltfläche Autorisieren nicht gefunden werden.
Don G.
9

Es ist auch möglich, das Attribut [FromHeader] für Webmethodenparameter (oder Eigenschaften in einer Modellklasse) zu verwenden, die in benutzerdefinierten Headern gesendet werden sollen. Etwas wie das:

[HttpGet]
public ActionResult Products([FromHeader(Name = "User-Identity")]string userIdentity)

Zumindest funktioniert es gut für ASP.NET Core 2.1 und Swashbuckle.AspNetCore 2.5.0.

Victor Sharovatov
quelle
1
Dies funktioniert nur mit MVC und nicht mit der Web-Api-Lösung (zumindest denke ich, da dies bei meiner Web-Api-Lösung fehlgeschlagen ist)
bleh10
@ bleh10 irgendwelche Details, warum es für Ihre Lösung fehlschlägt? Für mein Web-API-Projekt funktioniert es einwandfrei.
Victor Sharovatov
Ich bin mir nicht sicher warum, es zwang mich, die MVC-Bibliothek hinzuzufügen, und als ich VS verwirrte, überprüfe ich morgen erneut, da ich heute nicht bei der Arbeit bin und den Fehler hinzufügen werde, mit dem ich konfrontiert war!
Bleh10
Ich stehe korrigiert da, ich habe es gerade noch einmal versucht und es hat funktioniert, das einzige Problem ist, dass ich jetzt "System.Web.Http" hinzufügen muss. vor HttpGET und route und FromBody, was irgendwie nervig ist, aber die beste Lösung bisher! Bearbeiten: Eine noch bessere Lösung (nicht sicher, warum ich vorher nicht daran gedacht habe), damit ich nicht alle meine Controller erneut bearbeite, ist das Hinzufügen von Microsoft.AspNetCore.Mvc. vor FromHeader und jetzt funktioniert alles!
Bleh10
1
Zum Hinzufügen von "System.Web.Http". vor HttpGET und route und FromBody - Sie können die Anweisung "using" für diesen Namespace verwenden, um diesen doppelten Code zu vermeiden. Fügen Sie also einfach using System.Web.Http;am Anfang der Datei hinzu, wo Ihr Controller definiert ist.
Victor Sharovatov
3

Hier ist eine einfachere Antwort für die Kombination aus ASP.NET Core Web Api und Swashbuckle, für die Sie keine benutzerdefinierten Filter registrieren müssen. Das dritte Mal ist ein Zauber, den Sie kennen :).

Wenn Sie den folgenden Code zu Ihrer Swagger-Konfiguration hinzufügen, wird die Schaltfläche Autorisieren angezeigt, mit der Sie ein Inhaber-Token eingeben können, das für alle Anforderungen gesendet werden soll. Vergessen Sie nicht, dieses Token wie auf Bearer <your token here>Anfrage einzugeben .

Beachten Sie, dass der folgende Code das Token für alle Anforderungen und Vorgänge sendet, die möglicherweise Ihren Wünschen entsprechen oder nicht.


    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[] { } }
        });

        //...
    }

Über diesen Thread .

Vlad Iliescu
quelle
2

Ich bin hier gelandet, weil ich versucht habe, Header-Parameter in der Swagger-Benutzeroberfläche bedingt hinzuzufügen, basierend auf meinem eigenen [Authentication]Attribut, das ich meiner API-Methode hinzugefügt habe. Nach dem Hinweis, dass @Corcus in einem Kommentar aufgeführt ist, konnte ich meine Lösung ableiten und hoffe, dass sie anderen hilft.

Mit Reflection wird überprüft, ob die in verschachtelte Methode apiDescriptiondas gewünschte Attribut aufweist (in meinem Fall MyApiKeyAuthenticationAttribute). In diesem Fall kann ich meine gewünschten Header-Parameter anhängen.

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
            });
        }
    }


}
Zwischen den Wochenenden
quelle
Für diejenigen, die es mit API-Schlüssel versuchen .Net Core 2.1 c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> { { "ApiKeyAuth", new string[0] } }); stackoverflow.com/questions/49908577/…
SA.
1

Für diejenigen, die NSwag verwenden und einen benutzerdefinierten Header benötigen:

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
                }));
        });            
    }

Die Swagger-Benutzeroberfläche enthält dann eine Autorisierungsschaltfläche .

Ofiris
quelle
0

HAFTUNGSAUSSCHLUSS: Diese Lösung verwendet keinen Header.

Wenn jemand faul-faul sucht (auch in WebApi), würde ich vorschlagen:

public YourResult Authorize([FromBody]BasicAuthCredentials credentials)

Sie kommen nicht vom Header, aber zumindest haben Sie eine einfache Alternative. Sie können das Objekt jederzeit auf Null prüfen und auf den Header-Mechanismus zurückgreifen.

Cesar
quelle
0

Golang / go-swagger-Beispiel: 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
Qiang Li
quelle