您的位置:首页 > 编程语言 > ASP

ASP.NET Core Swagger接入使用IdentityServer4 的 WebApi

2019-05-10 23:26 1346 查看

写在前面

是这样的,我们现在接口使用了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

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

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

项目结构:

4、我们运行看看

先启动Identityserver项目

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

我们点一下上面的按钮:

哇,我们跳到了这里:

输入:alice/alice,点登录:

哇哇:

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

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

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

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

总结

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

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

参考

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

https://github.com/IdentityServer/IdentityServer4

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐