创建webapi项目

  创建四个webapi项目,两个处理业务,一个网关,一个验证中心。四个项目对应的端口如下,

ApiGateway:1999

IdentityServer:16690

Services.Api1:2108

Services.Api2:2343

添加Swagger支持

  在两个业务项目中分别引用Swashbuckle.AspNetCore,目前是最新版本是4.0.1。在项目属性面板,设置输出xml文档,swagger可以读取xml注释生成json文件,在swagger ui页面中显示。但是选择输出xml文档后,对于没有xml注释的类和方法会显示警告,可以在项目属性面板中【错误和警告】选项,取消显示警告中添加1591,这样就可以不显示缺少xml注释的警告了。对于强迫症的你暂时可以平复一下了,当然,真的强迫症的话,肯定会全部加上xml注释的。(¬_¬)瞄

  Startup.ConfigureServices

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  4.  
  5. services.AddSwaggerGen(options =>
  6. {
  7. //SwaggerDoc的第一个参数要与Configure中SwaggerEndPoint中的版本名称一致
  8. //既可以使用版本号,也可以使用自定义名称
  9. options.SwaggerDoc("ServiceApiTwo", new Info
  10. {
  11. Title = "Services.Api #two",
  12. Version = "v1",
  13. Description = "服务api #two",
  14. License = new License
  15. {
  16. Name = "APL2.0",
  17. Url = "https://opensource.org/licenses/Apache-2.0"
  18. },
  19. Contact = new Contact
  20. {
  21. Name = "原来是李",
  22. Url = "https://www.cnblogs.com/falltakeman"
  23. }
  24. });
  25. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
  26. var xmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, xmlFile);
  27. options.IncludeXmlComments(xmlPath);
  28.  
  29. });
  30. }

  Startup.Configure

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6.  
  7. app.UseSwagger(c=>
  8. {
  9. c.RouteTemplate = "{documentName}/swagger.json";
  10. });
  11. app.UseSwaggerUI(u =>
  12. {
  13. u.SwaggerEndpoint("/ServiceApiTwo/swagger.json", "ServiceApiTwo");
  14. u.DocumentTitle = "Service Api #2 文档";
  15. });
  16. }
  17.  
  18. app.UseMvc();
  19. }

  配置好启动项目看看。

  通过swagger发起请求,响应正常。

配置网关项目

  使用目前比较流行的开源网关服务Ocelot,APIGateway项目添加引用Ocelot、Ocelot.Provider.Consul、Ocelot.Provider.Polly、Ocelot.Cache.CacheManager,目前用到的版本是13.5.2。要在网关中统一查看各个服务的swagger文档,还需引用Swash.AspNetCore。Consul的配置先不说了。

  在项目根路径下添加OcelotConfig.json配置文件。处理正常的路由转发外,要在网关swagger页面访问业务api,还需要配置swagger路由转发。

  1. {
  2. "GlobalConfiguration": {
  3. //外部访问路径
  4. "BaseUrl": "http://localhost:1999",
  5. //限速配置
  6. "RateLimitOptions": {
  7. //白名单
  8. "ClientWhitelist": [],
  9. "EnableRateLimiting": true,
  10. //限制时间段,例如1s,5m,1h,1d
  11. "Period": "1s",
  12. //等待重试等待的时间间隔(秒)
  13. "PeriodTimespan": ,
  14. //限制
  15. "Limit": ,
  16. //自定义消息
  17. "QuotaExceededMessage": "单位时间内请求次数超过限制。",
  18. "HttpStatusCode":
  19. },
  20. //服务发现配置
  21. "ServiceDiscoveryProvider": {
  22. "Host": "localhost",
  23. "Port": ,
  24. "Type": "PollConsul",
  25. "PollingInterval":
  26. },
  27. //熔断配置
  28. "QoSOptions": {
  29. "ExceptionsAllowedBeforeBreaking": ,
  30. "DurationOfBreak": ,
  31. //超时值(毫秒)
  32. "TimeoutValue":
  33. }
  34. },
  35. "ReRoutes": [
  36. // Api#one项目配置
  37. {
  38. "UpstreamPathTemplate": "/gateway/one/{url}", //上游路径模板
  39. "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ], //上游HTTP请求方法
  40. "DownstreamPathTemplate": "/api/{url}", //下游路径模板
  41. "DownstreamScheme": "http", //下游协议 https/http
  42. "ServiceName": "ServiceApiOne", //服务名称(结合服务发现使用)
  43. "UseServiceDiscovery": true, //启用服务发现
  44. "LoadBalancer": "RoundRobin", //负载均衡算法:RoundRobin-轮询;LeastConnection-最少连接数(最空闲的服务器);NoLoadBalancer-总是发送往第一个请求或者服务发现
  45. //下游主机与端口,允许配置多个
  46. "DownstreamHostAndPorts": [
  47. //{
  48. // "Host": "ip",
  49. // "Port": 80
  50. //},
  51. {
  52. "Host": "localhost",
  53. "Port":
  54. }
  55. ],
  56. //熔断配置,在请求下游服务时使用断路
  57. "QoSOptions": {
  58. "ExceptionsAllowedBeforeBreaking": ,
  59. "DurationOfBreak": ,
  60. "TimeoutValue":
  61. },
  62. //权限配置
  63. //"AuthenticationOptions": {
  64. // "AuthenticationProviderKey": "Bearer",
  65. // "AllowedScopes": []
  66. //}
  67. },
  68. // Api#two项目配置
  69. {
  70. "UpstreamPathTemplate": "/gateway/two/{url}",
  71. "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
  72. "DownstreamPathTemplate": "/api/{url}",
  73. "DownstreamScheme": "http",
  74. "ServiceName": "ServiceApiTwo",
  75. "UseServiceDiscovery": true,
  76. "LoadBalancer": "RoundRobin",
  77. "DownstreamHostAndPorts": [
  78. //{
  79. // "Host": "ip",
  80. // "Port": 80
  81. //},
  82. {
  83. "Host": "localhost",
  84. "Port":
  85. }
  86. ],
  87. "QoSOptions": {
  88. "ExceptionsAllowedBeforeBreaking": ,
  89. "DurationOfBreak": ,
  90. "TimeoutValue":
  91. },
  92. //"AuthenticationOptions": {
  93. // "AuthenticationProviderKey": "Bearer",
  94. // "AllowedScopes": []
  95. //}
  96. },
  97. //swagger api2配置
  98. {
  99. "UpstreamPathTemplate": "/ServiceApiTwo/swagger.json",
  100. "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
  101. "DownstreamPathTemplate": "/ServiceApiTwo/swagger.json",
  102. "DownstreamScheme": "http",
  103. "DownstreamHostAndPorts": [
  104. {
  105. "Host": "localhost",
  106. "Port":
  107. }
  108. ]
  109. },
  110. //swagger api1多版本配置v1.0
  111. {
  112. "UpstreamPathTemplate": "/ServiceApiOne/1.0/swagger.json",
  113. "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
  114. "DownstreamPathTemplate": "/ServiceApiOne/1.0/swagger.json",
  115. "DownstreamScheme": "http",
  116. "DownstreamHostAndPorts": [
  117. {
  118. "Host": "localhost",
  119. "Port":
  120. }
  121. ]
  122. },
  123. //swagger api1多版本配置v2.0
  124. {
  125. "UpstreamPathTemplate": "/ServiceApiOne/2.0/swagger.json",
  126. "UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
  127. "DownstreamPathTemplate": "/ServiceApiOne/2.0/swagger.json",
  128. "DownstreamScheme": "http",
  129. "DownstreamHostAndPorts": [
  130. {
  131. "Host": "localhost",
  132. "Port":
  133. }
  134. ]
  135. }
  136. ]
  137. }

  Startup.ConfigureServices注册swagger和Ocelot网关服务,ConfigureServices中的swagger配置和业务api中一样,

  1. services.AddOcelot(Configuration)
  2. .AddConsul()
  3. .AddCacheManager(c => c.WithDictionaryHandle())
  4. .AddPolly();
  5.  
  6. services.AddSwaggerGen(options =>
  7. {
  8. options.SwaggerDoc(Configuration["Swagger:Name"], new Info
  9. {
  10. Title = Configuration["Swagger:Title"],
  11. Version = Configuration["Swagger:Version"],
  12. Description = Configuration["Swagger:Description"],
  13. License = new License
  14. {
  15. Name = Configuration["Swagger:License:Name"],
  16. Url = Configuration["Swagger:License:Url"]
  17. },
  18. Contact = new Contact
  19. {
  20. Name = Configuration["Swagger:Contact:Name"],
  21. Email = Configuration["Swagger:Contact:Email"],
  22. Url = Configuration["Swagger:Contact:Url"]
  23. }
  24. });
  25. });

  Startup.Configure中,我是使用了配置文件,将业务api的swagger节点写在了配置文件中。

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6. // 配置文件中的SwaggerName为业务api中是SwaggerEndPoint名称,有版本号的带上版本号
  7. var apis = Configuration["SwaggerApis:SwaggerName"].Split(';').ToList();
  8. app.UseSwagger();
  9. app.UseSwaggerUI(options=>
  10. {
  11. //显示注册到网关的api接口
  12. apis.ForEach(key =>
  13. {
  14. options.SwaggerEndpoint($"/{key}/swagger.json", key);
  15. });
  16. options.DocumentTitle = "api网关";
  17. });
  18.  
  19. }
  20. else
  21. {
  22. app.UseExceptionHandler("/Home/Error");
  23. }
  24.  
  25. app.UseStaticFiles();
  26. app.UseCookiePolicy();
  27.  
  28. app.UseMvc(routes =>
  29. {
  30. routes.MapRoute(
  31. name: "default",
  32. template: "{controller=Home}/{action=Index}/{id?}");
  33. });
  34.  
  35. app.UseOcelot().Wait(); // 使用Ocelot网关中间件
  36.  
  37. }

  修改ApiGateway项目Program.cs将配置文件添加进来。

  1. public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
  2. WebHost.CreateDefaultBuilder(args)
  3. .ConfigureAppConfiguration((hostingContext,config)=>
  4. {
  5. var env = hostingContext.HostingEnvironment;
  6. //根据环境变量加载不同的json配置
  7. config.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
  8. .AddJsonFile("OcelotConfig.json")//网关配置
  9. .AddEnvironmentVariables();//环境变量
  10. })
  11. .ConfigureLogging((hostingContext,logging)=>
  12. {
  13. logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
  14.  
  15. logging.AddConsole();
  16. //添加调试日志
  17. logging.AddDebug();
  18. })
  19. .UseStartup<Startup>();

  网关配置了,swagger也配置了,启动业务api和网关服务看看效果。

  两个业务api的swagger文档都可以正常查看。发请求看一下,结果响应404,仔细看一下,请求的服务地址是网关服务的地址,而不是业务api的地址,难道是Ocelot网关路由配置错了?使用Postman发一个GET请求看看,localhost:1999/gateway/two/values,网关转发到localhost:2343/api/values,响应正常。

  看swashbuckle文档这一段,将业务api中Configure加上这一段后再次通过网关发起请求,结果出现TypeError。既然出错了,打开浏览器调试工具看一下就明白了,Failed to load http://localhost:2343/api/ApiTwo: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:1999' is therefore not allowed access.

  网关请求业务api跨域了,要让业务api允许来自网关的请求,需要设置业务api跨域请求政策。加上下面的配置后,网关请求正常了。

  修改Startup.Configure

  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  2. {
  3. if (env.IsDevelopment())
  4. {
  5. app.UseDeveloperExceptionPage();
  6.  
  7. app.UseSwagger(c=>
  8. {
  9. //处理网关通过swagger访问
  10. c.PreSerializeFilters.Add((swaggerDoc, httpReq) => swaggerDoc.Host = httpReq.Host.Value);
  11. c.RouteTemplate = "{documentName}/swagger.json";
  12. });
  13. app.UseSwaggerUI(u =>
  14. {
  15. u.SwaggerEndpoint("/ServiceApiTwo/swagger.json", "ServiceApiTwo");
  16. u.DocumentTitle = "Service Api #2 文档";
  17. });
  18. }
  19.  
  20. // 允许网关访问
  21. app.UseCors(options =>
  22. {
  23. options.WithOrigins("http://localhost:1999")
  24. .AllowAnyHeader()
  25. .AllowAnyMethod();
  26. });
  27. app.UseMvc();
  28. }

使用IdentityServer4保护webapi

  先前已经创建IdentityServer项目,添加引用IdentityServer4.AspNetIdentity(2.5.0)、IdentityServer4.EntityFramework(2.5.0)。新建一个类IdentityServerConfig,里面定义四个方法GetApiResources、GetIdentityResources、GetClients、GetTestUsers,具体代码就不贴了,看一下Startup。生产环境的话,当然要用数据库,这里不讨论IdentityServer4的使用。

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  4.  
  5. services.AddIdentityServer()
  6. .AddDeveloperSigningCredential()
  7. .AddInMemoryPersistedGrants()
  8. .AddTestUsers(IdentityServerConfig.GetTestUsers())
  9. .AddInMemoryIdentityResources(IdentityServerConfig.GetIdentityResources())
  10. .AddInMemoryApiResources(IdentityServerConfig.GetApiResources())
  11. .AddInMemoryClients(IdentityServerConfig.GetClients(Configuration));
  12. }
  13.  
  14. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  15. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  16. {
  17. if (env.IsDevelopment())
  18. {
  19. app.UseDeveloperExceptionPage();
  20. }
  21.  
  22. app.UseIdentityServer();
  23.  
  24. app.UseMvc();
  25. }

  将网关和两个api项目对应的ApiResources和Clients分别为api-gateway、service-api-one、service-api-two,两个api客户端AllowedScope为自己,网关的AllowedScope为自己和两个api客户端。在需要保护的三个项目中添加引用IdentityServer4.AccessTokenValidation(2.7.0),修改Startup的ConfigureServices,添加如下代码。

  1. //使用IdentityServer4
  2. services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
  3. .AddIdentityServerAuthentication(options =>
  4. {
  5. options.ApiName = "service-api-two";
  6. options.Authority = "http://localhost:16690"; // IdentityServer验证服务
  7. options.RequireHttpsMetadata = false;
  8. options.EnableCaching = true;
  9. });

  Startup.Configure中添加app.UseAuthentication();

  要在swagger中访问需要验证的api,需要在swagger配置中添加安全验证。

  1. services.AddSwaggerGen(options =>
  2. {
  3. //SwaggerDoc的第一个参数要与Configure中SwaggerEndPoint中的版本名称一致
  4. //既可以使用版本号,也可以使用自定义名称
  5. options.SwaggerDoc("ServiceApiTwo", new Info
  6. {
  7. Title = "Services.Api #two",
  8. Version = "v1",
  9. Description = "服务api #two",
  10. License = new License
  11. {
  12. Name = "MIT",
  13. Url = "https://mit-license.org/"
  14. },
  15. Contact = new Contact
  16. {
  17. Name = "原来是李",
  18. Url = "http://www.cnblogs.com/falltakeman"
  19. }
  20. });
  21. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
  22. var xmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, xmlFile);
  23. options.IncludeXmlComments(xmlPath);
  24. // swagger访问需要验证的api
  25. options.AddSecurityDefinition("Bearer", new ApiKeyScheme
  26. {
  27. In = "header",
  28. Name = "Authorization",
  29. Type = "apiKey",
  30. Description = "Bearer {token}"
  31. });
  32. options.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
  33. {
  34. {
  35. "Bearer",
  36. Enumerable.Empty<string>()
  37. }
  38. });
  39. });

  在api控制器中,在需要保护的api上添加[Authorize]特性,没有授权的情况下访问受限api会报401错误。

  使用postman获取token,在swagger中填写token,再次发起请求,响应正常。

  在ApiGateway的Startup.ConfigureServices添加Authentication,在Services.AddSwaggerGen添加相应代码,启动项目在app.UseOcelot().Wait()抛出异常:Scheme already exists: BearerIdentityServerAuthenticationJwt. 最终使用了下面的方式。在ApiGateway项目中通过swagger也可以访问业务api了。

  1. Action<IdentityServerAuthenticationOptions> isaOpt = option =>
  2. {
  3. option.Authority = Configuration["IdentityService:Uri"];
  4. option.RequireHttpsMetadata = Convert.ToBoolean(Configuration["IdentityService:UseHttps"]);
  5. option.ApiName = Configuration["IdentityService:ApiName"];
  6. option.ApiSecret = Configuration["IdentityService:ApiSecret"];
  7. option.SupportedTokens = SupportedTokens.Both;
  8. };
  9. services.AddAuthentication().AddIdentityServerAuthentication(Configuration["IdentityService:DefaultScheme"], isaOpt);

  但是配置中的IdentityService:DefaultScheme不可以是"Bearer",试验配置的是"IdentityBearer",不知为何不可以是"Bearer",不知道有没有懂这个的可以指点一二。

the end...

AspNetCore网关集成Swagger访问使用IdentityServer保护的webapi项目的更多相关文章

  1. 网关集成Swagger出现404错误

    原因是忘了在需要生成api的类上加入注解  @EnableSwagger2Doc

  2. .netcore简单集成swagger

    为什么要集成Swagger 在前后端分离比较普遍的当下,当后端开发完接口后,还需把接口的信息.参数说明.返回参数等信息编写好提供给调用者.对于对外开放接口需提供说明文档是必不可少的.但是对于内部开发, ...

  3. 【大道至简】NetCore3.1快速开发框架一:集成Swagger

    在上一章节中,我们创建了基本的框架结构:https://www.cnblogs.com/fuyu-blog/p/12217647.html 下面我们测试接口和集成Swagger接口文档 一.接口测试 ...

  4. 微服务之十四如何在 Ocelot 网关中配置多实例 Swagger 访问

    一.介绍 当我们开发基于微服务的应用程序的时候,有一个环节总是跳不过去的,那就是要创建 WebApi,然后,我们的应用程序基于 WebApi 接口去访问.在没有 Swagger 以前,我们开发好了 W ...

  5. 【从零开始搭建自己的.NET Core Api框架】(一)创建项目并集成swagger:1.1 创建

    系列目录 一.  创建项目并集成swagger 1.1 创建 1.2 完善 二. 搭建项目整体架构 三. 集成轻量级ORM框架——SqlSugar 3.1 搭建环境 3.2 实战篇:利用SqlSuga ...

  6. Asp.Net Core集成Swagger

    工作中一个公司会有很多个项目,项目之间的交互经常需要编写 API 来实现,但是编写文档是一件繁琐耗时的工作,并且随着 API 的迭代,每次都需要去更新维护接口文档,很多时候由于忘记或者人员交替的愿意造 ...

  7. ASP.NET Core3.1使用IdentityServer4中间件系列随笔(二):创建API项目,配置IdentityServer保护API资源

    配套源码:https://gitee.com/jardeng/IdentitySolution 接上一篇<ASP.NET Core3.1使用IdentityServer4中间件系列随笔(一):搭 ...

  8. asp.net core 集成swagger ui

    什么是Swagger? 说swagger 之前,我们先说一下OpenApi 规范. OpenApi 是一种和语言无关的用于描述RESTAPIs 接口功能的一种规范,对RESTAPIs 接口的描述包括: ...

  9. EF 数据库连接字符串-集成安全性访问 SQL Server

    使用 Windows 集成安全性访问 SQL Server 如果您的应用程序运行在基于 Windows 的 Intranet 上,则也许可以将 Windows 集成身份验证用于数据库访问.集成安全性使 ...

随机推荐

  1. 指针的运算符&、*

    int y=0; int* yptr=&y; •互相反作用 •*&yptr -> * (&yptr) -> * (yptr的地址)-> 得到那个地址上的变量 ...

  2. mysql 唯一键

    唯一键特点: 1.唯一键在一张表中可以有多个. 2.唯一键允许字段数据为NULL,NULL可以有多个(NULL不参与比较) //一个表中允许存在多个唯一键,唯一键允许为空,在不为空的情况下,不允许重复 ...

  3. 解决Shell脚本$'\r': command not found问题

    造成这个问题的原因是Windows下的空行,我们只需要把文件转成unix就好 Centos下,执行yum install dos2unix,然后dos2unix [file],再执行shell命令就好 ...

  4. MySQL索引和SQL调优手册

    MySQL索引 MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等.为了避免混乱,本文将只关注于BTree ...

  5. 【2019.11.27】SDN课程阅读作业(2)

    过去20年中可编程网络的发展可以分为几个阶段?每个阶段的贡献是什么? Making computer networks more programmable enables innovation in ...

  6. Linux离线安装Docker

    1.从官方下载Docker安装包并上传至虚拟机 https://download.docker.com/linux/static/stable/x86_64/ 2.解压安装包 tar -xvf doc ...

  7. python opencv PyQt5

    import cv2 import numpy as np import sys from PyQt5.QtGui import * from PyQt5.QtCore import * from P ...

  8. word 转 pdf,c#代码

    通过使用 C# 控制 office 软件 com 组件转 pdf 1 word 转 pdf 方案二:可以使用 netoffice 进行转换 参考文档:https://netoffice.io/docu ...

  9. 026_如何在MAC下输入主要国家货币符号?

    由于出国旅游啥的经常会记录一些东西,不避免的会遇到各种货币符号 一. 人民币: ¥(sogo输入法切换到中文模式,然后"shift键 + 4"即可) 美元: $(sogo输入法切换 ...

  10. Python3基础 函数 无return、return 空或None 的效果相同

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...