Uwierzytelnianie JWT i Swagger z .Net core 3.0


10

Zajmuję się tworzeniem interfejsu API sieci Web z .Net core 3.0 i chcę zintegrować go z SwashBuckle.Swagger. Działa dobrze, ale po dodaniu uwierzytelnienia JWT nie działa zgodnie z oczekiwaniami. Aby to zrobić, dodałem poniższy kod:

  services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "My Web API", Version = "v1" });
            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey
            });

        });

Po dodaniu AddSecurityDefinitionfunkcji widzę przycisk Autoryzuj, a kiedy go klikam, widzę poniższy formularz: wprowadź opis zdjęcia tutaj

Następnie piszę: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjhPo zrobieniu tego spodziewam się zobaczyć authorization: Bearer WhatEverApiKeyIsfgdgdgdg845734987fgdhgiher635kjhw nagłówku żądania, kiedy wysyłam żądanie do interfejsu API sieci Web od Swagger. Ale autoryzacja nie jest dodawana do nagłówka żądania. Używam SwashBuckle.Swagger (5.0.0-rc3). Należy pamiętać, że istnieje wiele próbek, które działają dobrze na .net core 2.0, ale funkcje swashger Swashbuckle zmieniły się w najnowszej wersji, więc nie mogę używać tych próbek.



Na podany link nie ma odpowiedzi. Rdzeń .net 3.0 jest nieco inny.
Mehrdad Babaki

Odpowiedź polega na dodaniu .AddSecurityRequirement(globalnie) lub .Security(na poziomie operacyjnym) - jak wyjaśniono w odpowiedziach na powiązane pytanie. AddSecurityDefinitionsam nie wystarczy.
Helen

Dodałem, ale nic się nie zmieniło. Myślę, że dlatego nie został wybrany jako odpowiedź.
Mehrdad Babaki

Odpowiedziałem niedawno na inne pytanie, spójrz tutaj: stackoverflow.com/a/57872872/3952573
Pavlos

Odpowiedzi:


33

Po kilku badaniach w końcu znalazłem tutaj odpowiedź

Przed obejrzeniem tej strony wiedziałem, że powinienem użyć AddSecurityRequirementpóźniej z AddSecurityDefinitionpowodu wielu próbek, ale problem polegał na zmianie parametrów funkcji w .NET Core 3.0.

Nawiasem mówiąc, ostateczna odpowiedź jest następująca:

services.AddSwaggerGen(c =>
{
  c.SwaggerDoc("v1", new OpenApiInfo { 
    Title = "My API", 
    Version = "v1" 
  });
  c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
    In = ParameterLocation.Header, 
    Description = "Please insert JWT with Bearer into field",
    Name = "Authorization",
    Type = SecuritySchemeType.ApiKey 
  });
  c.AddSecurityRequirement(new OpenApiSecurityRequirement {
   { 
     new OpenApiSecurityScheme 
     { 
       Reference = new OpenApiReference 
       { 
         Type = ReferenceType.SecurityScheme,
         Id = "Bearer" 
       } 
      },
      new string[] { } 
    } 
  });
});

Wielkie dzięki, u mnie wszystko w porządku
Anas Al-Qudah

2
To zadziałało. Wskazówka: nie zapomnij napisać „Nosiciel” przed właściwym tokenem. I trochę denerwujące jest to, że swagger zawsze mówi autoryzowany, bez względu na to, co piszesz w polu tekstowym ... Dzięki!
CodeHacker

Działa to na net core 3 i swagger
ericpap

Kto ratuje życie, ratuje świat. Uratowałeś mi życie ;-) dzięki
Vahid Farahmandian

6

Jeśli używasz Swagger 3.0, ma on wbudowaną obsługę uwierzytelniania JWT.

Musisz użyć ParameterLocation.Header, SecuritySchemeType.Http, nośnika i JWT w OpenApiSecurityScheme, jak pokazano poniżej.

Po tym nie będziesz musiał określać tokena w formacie nośnika {token} . Podaj tylko token, a schemat bezpieczeństwa zastosuje go automatycznie w nagłówku.

// Bearer token authentication
OpenApiSecurityScheme securityDefinition = new OpenApiSecurityScheme()
{
    Name = "Bearer",
    BearerFormat = "JWT",
    Scheme = "bearer",
    Description = "Specify the authorization token.",
    In = ParameterLocation.Header,
    Type = SecuritySchemeType.Http,
};
c.AddSecurityDefinition("jwt_auth", securityDefinition);

// Make sure swagger UI requires a Bearer token specified
OpenApiSecurityScheme securityScheme = new OpenApiSecurityScheme()
{
    Reference = new OpenApiReference()
    {
        Id = "jwt_auth",
        Type = ReferenceType.SecurityScheme
    }
};
OpenApiSecurityRequirement securityRequirements = new OpenApiSecurityRequirement()
{
    {securityScheme, new string[] { }},
};
c.AddSecurityRequirement(securityRequirements);

wprowadź opis zdjęcia tutaj


Dziękuję Ci! Po wielu postach, które dla mnie nie działały, ta metoda zadziałała !!
Matt Casto

2

Jeśli nie chcesz ręcznie dodawać tokena i chcesz, aby zakresy były wybierane wraz z przekazaniem clientId do serwera tożsamości, możesz dodać coś takiego.

Użyłem niejawnego przepływu, ale możesz skonfigurować dowolny przepływ za pomocą następującego mechanizmu:

options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme()
{
  Flows = new OpenApiOAuthFlows
  {
    Implicit = new OpenApiOAuthFlow
    {                            
      AuthorizationUrl = new Uri("http://localhost"),
      TokenUrl = new Uri("http://localhost"),
      Scopes = new Dictionary<string, string>
      {
        { "Foundation API", "FoundationApi" }
      }
    }
  },
  In = ParameterLocation.Header,                    
  Name = "Authorization",
  Type = SecuritySchemeType.OAuth2                    
});

Wynik będzie taki:

wprowadź opis zdjęcia tutaj


1

Oto zaktualizowane rozwiązanie dla Swashbuckle.AspNetCore 5.3.2, zintegrowane z IdentityServer4, z interfejsem API zabezpieczonym za pomocą tokena elementu nośnego.

W ConfigureServices()metodzie:

        services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
            options.AddSecurityDefinition("Bearer", SecuritySchemes.BearerScheme(Configuration));
            options.AddSecurityRequirement(new OpenApiSecurityRequirement()
            {
                { SecuritySchemes.OAuthScheme, new List<string>() }
            });
        });

W Configure()metodzie:

        app.UseSwaggerUI(options =>
        {
            options.SwaggerEndpoint("/My.Api/swagger/v1/swagger.json", "My API V1");
            options.OAuthClientId(Clients.TestClient);
            options.OAuthAppName("My Api - Swagger");
            options.OAuthClientSecret(Configuration["TestClientSecret"]);
        });

internal static class SecuritySchemes
{
    public static OpenApiSecurityScheme BearerScheme(IConfiguration config) => new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Description = "Standard authorisation using the Bearer scheme. Example: \"bearer {token}\"",
        In = ParameterLocation.Header,
        Name = "Authorization",
        Scheme = "Bearer",
        OpenIdConnectUrl = new System.Uri($"{config["TokenServerUrl"]}.well-known/openid-configuration"),
        BearerFormat = "JWT",
        Flows = new OpenApiOAuthFlows
        {
            Password = new OpenApiOAuthFlow
            {
                AuthorizationUrl = new System.Uri($"{config["TokenServerUrl"]}connect/authorize"),
                Scopes = new Dictionary<string, string>
                    {
                        { Scopes.Api, "My Api" }
                    },
                TokenUrl = new System.Uri($"{config["TokenServerUrl"]}connect/token")
            }
        }
    };

    public static OpenApiSecurityScheme OAuthScheme => new OpenApiSecurityScheme
    {
        Reference = new OpenApiReference
        {
            Type = ReferenceType.SecurityScheme,
            Id = "Bearer"
        },
        Scheme = "oauth2",
        Name = "Bearer",
        In = ParameterLocation.Header,

    };
}

To jest ratowanie życia. Działa również w przypadku niejawnego przepływu, w którym zmieniłem hasło na niejawne w ustawieniach przepływu. Dziękuję bardzo!
Larsbj

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.