写在前面
是这样的,我们现在接口使用了Ocelot做网关,Ocelot里面集成了基于IdentityServer4的开发的授权中心用于对Api资源的保护。问题来了,我们的Api用了
SwaggerUI <https://swagger.io/>
做接口的自文档,那就蛋疼了,你接入了IdentityServer4的Api,用SwaggerUI调试、调用接口的话,妥妥的401,未授权啊。那有小伙伴就会说了,你SwaggerUI的Api不经过网关不就ok了?诶,好办法。但是:
 * 我不想改变Url规则啊,我是/api
开头的Url都是经过网关的,如果不经过网关要加端口或者改变Url规则,会给其他部门的同事带来麻烦(多个Url规则容易混淆); 
 * 
另外是,因为生产环境是接入了IdentityServer4,我想测试环境从一开始就需要调用方熟悉的接入,避免平时用没有经过授权中心的Url调试,一到生产就出问题。
ok,废话讲得有点多,我们就直奔主题。
下面我们需要创建两个示例项目:
1、IdentityServer4的授权中心;
2、使用SwaggerUI做自文档的WebApi项目;
本文源码地址:
https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example
 
<https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example>
构建基于IdentityServer4授权中心
1、新建空白解决方案,并添加一个空的WebApi项目,IdentityServer
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,跑起来了
使用SwaggerUI做自文档的WebApi项目
1、添加WebApi项目,SwaggerUIApi
现在项目结构这样:
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:
我们调用一下接口:
杠杠的200:
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,未授权了;
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
 
<https://github.com/IdentityServer/IdentityServer4/tree/master/samples/Quickstarts/3_ImplicitFlowAuthentication/src/IdentityServer>
下载这个两个文件夹,丢到IdentityServer项目下面:
项目结构:
4、我们运行看看
先启动Identityserver项目
运行SwaggerUI可以看到,这两个地方了个小锁头,表示已启用安全保护:
我们点一下上面的按钮:
哇,我们跳到了这里:
输入:alice/alice,点登录:
哇哇:
当然是Yes啦,然后这边变成这样了:
这是已获得授权状态,我们再次调用看看:
这里我们看到已经调用成功,仔细看请求,与前面简短的请求不同的是,现在请求里面带了access_token了,
这才是我们折腾这么久得来的宝贝。
总结
写得有点匆忙,希望大家能看得懂[捂脸];
源码地址:
https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example
 
<https://github.com/gebiWangshushu/cnblogs-demos/tree/master/SwggerUI.IdentityServer4.Example>
参考
https://github.com/domaindrivendev/Swashbuckle.AspNetCore 
<https://github.com/domaindrivendev/Swashbuckle.AspNetCore>
https://github.com/IdentityServer/IdentityServer4 
<https://github.com/IdentityServer/IdentityServer4>
热门工具 换一换
