美文网首页菜鸟学编程
ASP.NET Core Swagger接入使用Identity

ASP.NET Core Swagger接入使用Identity

作者: 菜鸟飞不动 | 来源:发表于2019-05-11 00:07 被阅读18次

    写在前面

    是这样的,我们现在接口使用了Ocelot做网关,Ocelot里面集成了基于IdentityServer4的开发的授权中心用于对Api资源的保护。问题来了,我们的Api用了SwaggerUI做接口的自文档,那就蛋疼了,你接入了IdentityServer4的Api,用SwaggerUI调试、调用接口的话,妥妥的401,未授权啊。那有小伙伴就会说了,你SwaggerUI的Api不经过网关不就ok了?诶,好办法。但是:

    1. 我不想改变Url规则啊,我是/api开头的Url都是经过网关的,如果不经过网关要加端口或者改变Url规则,会给其他部门的同事带来麻烦(多个Url规则容易混淆);
    2. 另外是,因为生产环境是接入了IdentityServer4,我想测试环境从一开始就需要调用方熟悉的接入,避免平时用没有经过授权中心的Url调试,一到生产就出问题。

    ok,废话讲得有点多,我们就直奔主题。

    下面我们需要创建两个示例项目:

    1、IdentityServer4的授权中心;

    2、使用SwaggerUI做自文档的WebApi项目;

    本文源码地址:https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example

    构建基于IdentityServer4授权中心

    1、新建空白解决方案,并添加一个空的WebApi项目,IdentityServer

    1557495509700

    2、引用包。

    Install-Package IdentityServer4
    

    3、添加配置类:Config.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    namespace IdentityServer
    {
        public class Startup
        {
            public IHostingEnvironment Environment { get; }
    
            public Startup(IHostingEnvironment environment)
            {
                Environment = environment;
            }
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
                var builder = services.AddIdentityServer()
                        .AddInMemoryIdentityResources(Config.GetIdentityResources())
                        .AddInMemoryApiResources(Config.GetApis())
                        .AddInMemoryClients(Config.GetClients())
                        .AddTestUsers(Config.GetUsers());
    
                if (Environment.IsDevelopment())
                {
                    builder.AddDeveloperSigningCredential();
                }
                else
                {
                    throw new Exception("need to configure key material");
                }
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseIdentityServer();
                app.UseIdentityServer();
                app.UseMvcWithDefaultRoute();
            }
        }
    }
    
    

    4、修改Startup.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    namespace IdentityServer
    {
        public class Startup
        {
            public IHostingEnvironment Environment { get; }
    
            public Startup(IHostingEnvironment environment)
            {
                Environment = environment;
            }
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
                var builder = services.AddIdentityServer()
                        .AddInMemoryIdentityResources(Config.GetIdentityResources())
                        .AddInMemoryApiResources(Config.GetApis())
                        .AddInMemoryClients(Config.GetClients())
                        .AddTestUsers(Config.GetUsers());
    
                if (Environment.IsDevelopment())
                {
                    builder.AddDeveloperSigningCredential();
                }
                else
                {
                    throw new Exception("need to configure key material");
                }
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseIdentityServer();
                app.UseIdentityServer();
                app.UseMvcWithDefaultRoute();
            }
        }
    }
    
    

    ok,跑起来了

    1557497033760

    使用SwaggerUI做自文档的WebApi项目

    1、添加WebApi项目,SwaggerUIApi

    现在项目结构这样:

    1557497204567

    2、先添加SwaggerUI,先不接入IdentityServer

    修改Startup.cs

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using Swashbuckle.AspNetCore.Swagger;
    
    namespace SwggerUIApi
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
                services.AddSwaggerGen(c =>
                {
                    c.SwaggerDoc("v1", new Info
                    {
                        Version = "v1",
                        Title = "ToDo API",
                        Description = "A simple example ASP.NET Core Web API",
                        TermsOfService = "None",
                        Contact = new Contact
                        {
                            Name = "Shayne Boyer",
                            Email = string.Empty,
                            Url = "https://twitter.com/spboyer"
                        },
                        License = new License
                        {
                            Name = "Use under LICX",
                            Url = "https://example.com/license"
                        }
                    });
                    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                    c.IncludeXmlComments(xmlPath);
                });
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                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");
                });
                app.UseMvc();
            }
        }
    }
    
    

    得到这样的SwaggerUI:

    1557497953754

    我们调用一下接口:

    杠杠的200:

    1557497995457

    3、接口项目我们接入IdentityServer4

    修改:Startup.cs ,ConfigureServices方法,

      .AddIdentityServerAuthentication(options =>
               {
                  options.Authority = "http://localhost:5000"; // IdentityServer服务器地址
                  options.ApiName = "swagger_api"; // 用于针对进行身份验证的API资源的名称
                  options.RequireHttpsMetadata = false; // 指定是否为HTTPS
              });
    

    修改:Startup.cs ,Configure方法

    app.UseAuthentication();
    

    Ok,可以看到我们接入进去了,401,未授权了;

    1557498423814

    3、接入IdentityServer

    1、添加授权响应操作的过滤器,AuthResponsesOperationFilter.cs

    using Microsoft.AspNetCore.Authorization;
    using Swashbuckle.AspNetCore.Swagger;
    using Swashbuckle.AspNetCore.SwaggerGen;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace SwggerUIApi
    {
        public class AuthResponsesOperationFilter : IOperationFilter
        {
            public void Apply(Operation operation, OperationFilterContext context)
            {
                //获取是否添加登录特性
                var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true)
                 .Union(context.MethodInfo.GetCustomAttributes(true))
                 .OfType<AuthorizeAttribute>().Any();
    
                if (authAttributes)
                {
                    operation.Responses.Add("401", new Response { Description = "暂无访问权限" });
                    operation.Responses.Add("403", new Response { Description = "禁止访问" });
                    operation.Security = new List<IDictionary<string, IEnumerable<string>>>
                    {
                        new Dictionary<string, IEnumerable<string>> {{"oauth2", new[] { "swagger_api" } }}
                    };
                }
            }
        }
    }
    
    

    2、修改Startup.cs ,ConfigureServices方法的,services.AddSwaggerGen()

    配置成这样:

         services.AddSwaggerGen(c =>
                {
                    c.SwaggerDoc("v1", new Info
                    {
                        Version = "v1",
                        Title = "ToDo API",
                        Description = "A simple example ASP.NET Core Web API",
                        TermsOfService = "None",
                        Contact = new Contact
                        {
                            Name = "Shayne Boyer",
                            Email = string.Empty,
                            Url = "https://twitter.com/spboyer"
                        },
                        License = new License
                        {
                            Name = "Use under LICX",
                            Url = "https://example.com/license"
                        }
                    });
                    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                    c.IncludeXmlComments(xmlPath);
    
                    //接入identityserver
                    c.AddSecurityDefinition("oauth2", new OAuth2Scheme
                    {
                        Flow = "implicit", // 只需通过浏览器获取令牌(适用于swagger)
                        AuthorizationUrl = "http://localhost:5000/connect/authorize",//获取登录授权接口
                        Scopes = new Dictionary<string, string> {
                            { "swagger_api_scopde", "swagger_api access" }//指定客户端请求的api作用域。 如果为空,则客户端无法访问
                        }
                    });
                    c.OperationFilter<AuthResponsesOperationFilter>();
                });
    

    3、我们还需给授权中心添加一个登陆界面

    去: https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts/3_ImplicitFlowAuthentication/src/IdentityServer

    下载这个两个文件夹,丢到IdentityServer项目下面:

    1557500638819 项目结构: 1557500675473

    4、我们运行看看

    先启动Identityserver项目

    运行SwaggerUI可以看到,这两个地方了个小锁头,表示已启用安全保护:

    1557500788279

    我们点一下上面的按钮:

    1557500876183

    哇,我们跳到了这里:

    1557501003686

    输入:alice/alice,点登录:

    哇哇:

    1557501070248

    当然是Yes啦,然后这边变成这样了:

    1557501113274

    这是已获得授权状态,我们再次调用看看:

    1557501152535

    这里我们看到已经调用成功,仔细看请求,与前面简短的请求不同的是,现在请求里面带了access_token了,

    这才是我们折腾这么久得来的宝贝。

    总结

    写得有点匆忙,希望大家能看得懂[捂脸];

    源码地址:https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example

    参考

    https://github.com/domaindrivendev/Swashbuckle.AspNetCore

    https://github.com/IdentityServer/IdentityServer4

    https://www.cnblogs.com/xiaxiaolu/p/10847248.html

    好书推荐、视频分享,公众号"读书ReadBook"与您一起进步

    相关文章

      网友评论

        本文标题:ASP.NET Core Swagger接入使用Identity

        本文链接:https://www.haomeiwen.com/subject/kzktaqtx.html