首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将SwashBuckle.AspNetCore.Swagger设置为使用授权?

如何将SwashBuckle.AspNetCore.Swagger设置为使用授权?
EN

Stack Overflow用户
提问于 2017-08-21 07:36:59
回答 3查看 15.3K关注 0票数 14

我已经使用Swashbuckle.AspNetCore.Swagger记录了我的应用程序接口,并且我想使用swagger ui测试一些具有Authorize属性的资源。

api接口

代码语言:javascript
复制
 using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using System.Linq;

    namespace Api.Controllers
    {
        [Route("[controller]")]
        [Authorize]
        public class IdentityController : ControllerBase
        {
            [HttpGet]
            public IActionResult Get()
            {
                return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
            }
        }
    }

响应码是未经授权的401,那么我如何使用swagger来授权呢?

我有一个使用IdentityServer4的授权服务器设置。

授权服务器- startup.cs

代码语言:javascript
复制
services.AddIdentityServer()
        .AddTemporarySigningCredential()
        .AddInMemoryPersistedGrants()
        .AddInMemoryIdentityResources(Config.GetIdentityResources())
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients())
        .AddAspNetIdentity<ApplicationUser>();

授权服务器- config.cs

代码语言:javascript
复制
    public class Config
{
    // scopes define the resources in your system
    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
        };
    }

    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource("api1", "My API")
        };
    }
   ...
   ...
}

api - startup.cs

代码语言:javascript
复制
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory,
        ECommerceDbContext context)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            Authority = "http://localhost:5000/",
            RequireHttpsMetadata = false,
            AutomaticAuthenticate = true,
            ApiName = "api1"
        });


        // Enable middleware to serve generated Swagger as a JSON endpoint.
        app.UseSwagger();

        // Enable middleware to serve swagger-ui (HTML, JS, CSS etc.), specifying the Swagger JSON endpoint.
        app.UseSwaggerUI(c =>
        {
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
        });

        DbInitialiser.Init(context);

        app.UseMvc();
    }

我想要一个授权按钮,重定向到登录屏幕,然后授予访问api资源的用户有权限。有没有可能使用asp.net Core1.1Swagger中间件来做到这一点?或者,我是否需要编写一些从IdentityServer4授权服务器获取令牌的javascript?我刚接触身份验证和授权,请多多指教

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-31 05:38:12

我通过在IdentityServer4授权服务器项目中添加一个新的客户机解决了这个问题。

config.cs

代码语言:javascript
复制
 // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            // client credentials client
            return new List<Client>
            {
                new Client
                {
                    ClientId="swaggerui",
                    ClientName = "Swagger UI",
                    AllowedGrantTypes=GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser=true,
                    RedirectUris = { "http://localhost:49831/swagger/o2c.html" },
                    PostLogoutRedirectUris={ "http://localhost:49831/swagger/" },
                    AllowedScopes = {"api1"}
                },
    ...
    ...
    ...
   }
}

我在API中创建了一个swagger OperationFilter,这样需要授权的方法旁边就会出现一个红色的感叹号图标。

代码语言:javascript
复制
internal class AuthorizeCheckOperationFilter : IOperationFilter
    {
        public void Apply(Operation operation, OperationFilterContext context)
        {
            // Check for authorize attribute
            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>>>();
                operation.Security.Add(new Dictionary<string, IEnumerable<string>>
            {
                { "oauth2", new [] { "api1" } }
            });
            }
        }
    }

为此,我在swagger中添加了oauth2安全定义和操作过滤器,从而配置了授权

startup.cs

代码语言:javascript
复制
 services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info
                {
                    Version = "v1",
                    Title = "ECommerce API",
                    Description = "",
                    TermsOfService = "None",
                    Contact = new Contact { Name = "", Email = "", Url = "" },
                    License = new License { Name = "", Url = "" }
                });

                //Set the comments path for the swagger json and ui.
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                var xmlPath = Path.Combine(basePath, "WebApi.xml");
                c.IncludeXmlComments(xmlPath);

                c.OperationFilter<AuthorizeCheckOperationFilter>();

                c.AddSecurityDefinition("oauth2", new OAuth2Scheme
                {
                    Type = "oauth2",
                    Flow = "implicit",
                    AuthorizationUrl = "http://localhost:5000/connect/authorize",
                    TokenUrl = "http://localhost:5000/connect/token",
                    Scopes = new Dictionary<string, string>()
                    {
                        { "api1", "My API" }
                    }
                });
            });
票数 11
EN

Stack Overflow用户

发布于 2018-10-25 19:09:07

正如詹姆斯在对接受的答案的评论中提到的,检查Authorize属性的方式现在略有不同,答案中的AuthorizeCheckOperationFilter需要稍微调整,这可能不是100%做到这一点的最好方法,但是我在下面的代码中没有遇到任何问题。

代码语言:javascript
复制
internal class AuthorizeCheckOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, OperationFilterContext context)
    {
        context.ApiDescription.TryGetMethodInfo(out var methodInfo);

        if (methodInfo == null)
             return;

        var hasAuthorizeAttribute = false;

        if (methodInfo.MemberType == MemberTypes.Method)
        {
            // NOTE: Check the controller itself has Authorize attribute
            hasAuthorizeAttribute = methodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();

            // NOTE: Controller has Authorize attribute, so check the endpoint itself.
            //       Take into account the allow anonymous attribute
            if (hasAuthorizeAttribute)
                hasAuthorizeAttribute = !methodInfo.GetCustomAttributes(true).OfType<AllowAnonymousAttribute>().Any();
            else
                hasAuthorizeAttribute = methodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();
        }

        if (!hasAuthorizeAttribute)
            return;

        operation.Responses.Add(StatusCodes.Status401Unauthorized.ToString(), new Response { Description = "Unauthorized" });
        operation.Responses.Add(StatusCodes.Status403Forbidden.ToString(), new Response { Description = "Forbidden" });

        // NOTE: This adds the "Padlock" icon to the endpoint in swagger, 
        //       we can also pass through the names of the policies in the string[]
        //       which will indicate which permission you require.
        operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
        operation.Security.Add(new Dictionary<string, IEnumerable<string>>
        {
            { "Bearer", new string[] { } }
        });
    }
}
票数 9
EN

Stack Overflow用户

发布于 2020-05-20 03:31:51

对于.Net核心和Swashbuckle.AspNetCore 5.4.1,以下是@Dan响应的工作更新:

创建一个IOperationalFilter类:

代码语言:javascript
复制
internal class AuthorizeCheckOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        context.ApiDescription.TryGetMethodInfo(out var methodInfo);

        if (methodInfo == null)
            return;

        var hasAuthorizeAttribute = false;

        if (methodInfo.MemberType == MemberTypes.Method)
        {
            // NOTE: Check the controller itself has Authorize attribute
            hasAuthorizeAttribute = methodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();

            // NOTE: Controller has Authorize attribute, so check the endpoint itself.
            //       Take into account the allow anonymous attribute
            if (hasAuthorizeAttribute)
                hasAuthorizeAttribute = !methodInfo.GetCustomAttributes(true).OfType<AllowAnonymousAttribute>().Any();
            else
                hasAuthorizeAttribute = methodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();
        }

        if (!hasAuthorizeAttribute)
            return;

        if (!operation.Responses.Any(r => r.Key == StatusCodes.Status401Unauthorized.ToString()))
            operation.Responses.Add(StatusCodes.Status401Unauthorized.ToString(), new OpenApiResponse { Description = "Unauthorized" });
        if (!operation.Responses.Any(r => r.Key == StatusCodes.Status403Forbidden.ToString()))
            operation.Responses.Add(StatusCodes.Status403Forbidden.ToString(), new OpenApiResponse { Description = "Forbidden" });

        // NOTE: This adds the "Padlock" icon to the endpoint in swagger, 
        //       we can also pass through the names of the policies in the string[]
        //       which will indicate which permission you require.
        operation.Security = new List<OpenApiSecurityRequirement>
        {
            new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        },
                        Scheme = "oauth2",
                        Name = "Bearer",
                        In = ParameterLocation.Header
                    },
                    new List<string>()
                }
            }
        };
    }
}

连接启动中的筛选器和安全定义:

代码语言:javascript
复制
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddSwaggerGen(c =>
    {
        c.OperationFilter<AuthorizeCheckOperationFilter>();
        c.EnableAnnotations();
        c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
        {
            Scheme = "Bearer",
            In = ParameterLocation.Header,
            Name = "Authorization",
            Type = SecuritySchemeType.ApiKey,
            Description = @"JWT Authorization header using the Bearer scheme. \r\n\r\n 
              Enter 'Bearer' [space] and then your token in the text input below.
              \r\n\r\nExample: 'Bearer 12345abcdef'"
        });
    });
    ...
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45787711

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档