• .Net6 Api Swagger配置


    1、定义个Swagger版本(组)的枚举

    1. namespace WebApp.Enums
    2. {
    3. ///
    4. /// api版本枚举
    5. ///
    6. public enum ApiVersion
    7. {
    8. ///
    9. /// v1版本
    10. ///
    11. v1 = 1,
    12. ///
    13. /// v2版本
    14. ///
    15. v2 = 2,
    16. }
    17. }

    2、添加SwaggerExtentsion扩展类,配置注册Swagger

    1. using Microsoft.OpenApi.Models;
    2. using Swashbuckle.AspNetCore.SwaggerGen;
    3. using System.Net.Http.Headers;
    4. using System.Net;
    5. using System.Reflection;
    6. using System.Text;
    7. using WebApp.Enums;
    8. namespace WebApp.Common.Swagger
    9. {
    10. ///
    11. /// SwaggerDoc配置
    12. /// 用法:在Program.cs文件中进行注册:builder.AddSwaggerGenExt();
    13. ///
    14. public static class SwaggerExtension
    15. {
    16. ///
    17. /// 扩展方法:Swagger文档
    18. ///
    19. ///
    20. public static void AddSwaggerGenExt(this IServiceCollection services)
    21. {
    22. #region 添加Swagger
    23. //获取的是当前执行的方法所在的程序文件的名称:即项目名称,例如我的项目名称叫webapp
    24. var AssemblyName = Assembly.GetExecutingAssembly().GetName().Name;
    25. services.AddSwaggerGen(options =>
    26. {
    27. #region 配置版本
    28. //options.SwaggerDoc("v1", new OpenApiInfo { Title = "售楼API", Version = "v1" });
    29. typeof(ApiVersion).GetEnumNames().ToList().ForEach(version =>
    30. {
    31. options.SwaggerDoc(version, new OpenApiInfo()
    32. {
    33. Version = version,
    34. Title = "凤凰网管理系统",
    35. Description = $"凤凰网接口服务 版本: {version}",
    36. Contact = new OpenApiContact
    37. {
    38. Name = "潇湘夜雨",
    39. Email = "123@qq.com"
    40. }
    41. });
    42. });
    43. #endregion
    44. #region 配置注释文档
    45. // 获取当前项目的 XML文档文件路径:比如我的项目名称叫WebApp,那么它默认的 XML文档文件路径就是当前项目下的 WebApp.xml
    46. var xmlFile = $"{AssemblyName}.xml";
    47. var xmlFileFullPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    48. //var domainXmlPath = Path.Combine(AppContext.BaseDirectory, "Bgy.Domain.xml"); // 获取Bgy.Domain.xml文件路径
    49. //var viewmodelXmlPath = Path.Combine(AppContext.BaseDirectory, "Bgy.ViewModel.xml");// 获取Bgy.ViewModel.xml文件路径
    50. options.IncludeXmlComments(xmlFileFullPath, true); // 添加控制器层注释,true表示显示控制器注释
    51. //options.IncludeXmlComments(domainXmlPath); // 添加Domain层注释
    52. //options.IncludeXmlComments(viewmodelXmlPath); // 添加ViewModel层注释
    53. //对action的名称进行排序。
    54. options.OrderActionsBy(o => o.RelativePath);
    55. #endregion
    56. #region 配置授权认证信息
    57. //添加一个必须的全局安全信息,
    58. //第一个参数是方案唯一名称:和AddSecurityDefinition方法指定的方案名称标识一致即可:BearerAuth
    59. //第二个参数是方案的描述:可以是BasicAuthScheme、ApiKeyScheme的实例或OAuth2Scheme
    60. options.AddSecurityDefinition("BearerAuth", new OpenApiSecurityScheme()
    61. {
    62. Description = "在下框中输入请求头中需要添加Jwt授权Token:Bearer Token",
    63. Name = "Authorization",
    64. In = ParameterLocation.Header, //配置jwt默认加在Authorization信息的位置:这里配置的是将jwt信息放在请求头Header中
    65. Type = SecuritySchemeType.Http,//使用Authorize头部
    66. Scheme = "bearer", //内容为以 bearer开头
    67. BearerFormat = "JWT",
    68. //Reference= new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" }
    69. });
    70. //注册全局认证(所有的接口都可以使用认证)
    71. options.AddSecurityRequirement(new OpenApiSecurityRequirement()
    72. {
    73. {
    74. new OpenApiSecurityScheme
    75. {
    76. Reference = new OpenApiReference
    77. {
    78. Type = ReferenceType.SecurityScheme,
    79. Id = "BearerAuth" //方案名称标识
    80. }
    81. },
    82. new string[] {} //不设权限
    83. }
    84. });
    85. #endregion
    86. #region 在Swagger中扩展文件上传按钮
    87. options.OperationFilter();
    88. #endregion
    89. });
    90. #endregion
    91. }
    92. ///
    93. /// 扩展方法:配置SwaggerUI
    94. /// 用法:在Program.cs文件中进行注册:app.UseSwaggerUIExt();
    95. ///
    96. ///
    97. public static void UseSwaggerUIExt(this WebApplication app)
    98. {
    99. //SwaggerBasicAuthMiddleware:是我自己扩展的一个中间件:目的是需要登陆才能到达Swagger的Index页面中,否则无法进入:可以根据需要去掉这个
    100. //需要安装:Swashbuckle.AspNetCore包
    101. //app.UseMiddleware();
    102. if (app.Environment.IsDevelopment())
    103. {
    104. //app.UseSwagger();
    105. //app.UseSwaggerUI();
    106. }
    107. var enviroment = app.Configuration["Swagger:environmentVariables"];
    108. switch (enviroment)
    109. {
    110. case "development":
    111. app.UseSwagger();//启用Swagger中间件
    112. app.UseSwaggerUI(options => //配置版本
    113. {
    114. typeof(ApiVersion).GetEnumNames().ToList().ForEach(version =>
    115. {
    116. options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version);
    117. });
    118. });
    119. break;
    120. case "testing":
    121. app.UseSwagger();
    122. app.UseSwaggerUI(options =>
    123. {
    124. typeof(ApiVersion).GetEnumNames().ToList().ForEach(version =>
    125. {
    126. options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version);
    127. });
    128. });
    129. break;
    130. case "production":
    131. break;
    132. }
    133. }
    134. }
    135. #region 扩展功能
    136. ///
    137. /// 文件上传的扩展:实现在Swagger中上传文件的功能
    138. ///
    139. public class FileUploadFilter : IOperationFilter
    140. {
    141. ///
    142. /// 文件上传筛选:只有上传文件的方法才添加此功能
    143. ///
    144. ///
    145. ///
    146. public void Apply(OpenApiOperation operation, OperationFilterContext context)
    147. {
    148. const string FileUploadContentType = "multipart/form-data";
    149. if (operation.RequestBody == null || !operation.RequestBody.Content.Any(x => x.Key.Equals(FileUploadContentType, StringComparison.InvariantCultureIgnoreCase)))
    150. {
    151. return;
    152. }
    153. if (context.ApiDescription.ParameterDescriptions[0].Type == typeof(IFormCollection))
    154. {
    155. operation.RequestBody = new OpenApiRequestBody
    156. {
    157. Description = "文件上传",
    158. Content = new Dictionary<string, OpenApiMediaType>
    159. {
    160. {
    161. FileUploadContentType,new OpenApiMediaType
    162. {
    163. Schema=new OpenApiSchema
    164. {
    165. Type="object",
    166. Required=new HashSet<string>{ "file"},
    167. Properties=new Dictionary<string, OpenApiSchema>
    168. {
    169. {
    170. "file",new OpenApiSchema
    171. {
    172. Type="string",
    173. Format="binary"
    174. }
    175. }
    176. }
    177. }
    178. }
    179. }
    180. }
    181. };
    182. }
    183. }
    184. }
    185. ///
    186. /// 如何在ASP.Net Core的生产环境中保护swagger ui,也就是index.html页面。其实swagger是自带禁用的功能的,只需要设置开关即可。
    187. /// 但是有一些场景,是需要把这些接口进行开放或者导出成文档供第三方进行调用,这个时候却又不想让所有人访问。
    188. /// 这里介绍一种权限控制访问的方式,用来指定用户使用;
    189. ///
    190. public class SwaggerBasicAuthMiddleware
    191. {
    192. private readonly RequestDelegate next;
    193. ///
    194. /// 增加对swagger ui的验证
    195. ///
    196. ///
    197. public SwaggerBasicAuthMiddleware(RequestDelegate next)
    198. {
    199. this.next = next;
    200. }
    201. ///
    202. /// 登陆功能实现
    203. ///
    204. ///
    205. ///
    206. public async Task InvokeAsync(HttpContext context)
    207. {
    208. if (context.Request.Path.StartsWithSegments("/swagger"))
    209. {
    210. string authHeader = context.Request.Headers["Authorization"];
    211. if (authHeader != null && authHeader.StartsWith("Basic "))
    212. {
    213. // Get the credentials from request header
    214. var header = AuthenticationHeaderValue.Parse(authHeader);
    215. var inBytes = Convert.FromBase64String(header.Parameter);
    216. var credentials = Encoding.UTF8.GetString(inBytes).Split(':');
    217. var username = credentials[0];
    218. var password = credentials[1];
    219. //用户身份认证
    220. if (username.Equals("admin") && password.Equals("123456"))
    221. {
    222. await next.Invoke(context).ConfigureAwait(false);
    223. return;
    224. }
    225. }
    226. context.Response.Headers["WWW-Authenticate"] = "Basic";
    227. context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
    228. }
    229. else
    230. {
    231. await next.Invoke(context).ConfigureAwait(false);
    232. }
    233. }
    234. }
    235. #endregion
    236. }

    3、appsettings.json配置文件

    1. {
    2. "Logging": {
    3. "LogLevel": {
    4. "Default": "Information",
    5. "Microsoft.AspNetCore": "Warning"
    6. }
    7. },
    8. "AllowedHosts": "*",
    9. "Swagger": {
    10. "environmentVariables": "development" //:development :testing :production
    11. }
    12. }

    4、在Program.cs中注册SwaggerDoc及启用SwaggerUI

    1. using Microsoft.AspNetCore.Authentication.JwtBearer;
    2. using Microsoft.IdentityModel.Tokens;
    3. using System.Text;
    4. using WebApp.Common.Swagger;
    5. var builder = WebApplication.CreateBuilder(args);
    6. builder.Services.AddControllers();
    7. builder.Services.AddEndpointsApiExplorer();
    8. #region JWT鉴权授权
    9. var audience = "Audience";
    10. var issuer = "Issuer";
    11. var securityKey = "SIGfMA0FCSqGSIb3DFEBAQUAA4GNADCBiQKBgQDI2a2EJ7d872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI593nNDAPfnJsas96mSA9Q/mD8RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB";
    12. builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) //默认授权机制名称;
    13. .AddJwtBearer(options =>
    14. {
    15. options.TokenValidationParameters = new TokenValidationParameters
    16. {
    17. ValidateIssuer = true,//是否验证Issuer
    18. ValidateAudience = true,//是否验证Audience
    19. ValidateLifetime = true,//是否验证失效时间
    20. ValidateIssuerSigningKey = true,//是否验证SecurityKey
    21. ValidAudience = audience,//Audience
    22. ValidIssuer = issuer,//Issuer,这两项和前面签发jwt的设置一致 表示谁签发的Token
    23. IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey))//拿到SecurityKey
    24. };
    25. });
    26. #endregion
    27. builder.Services.AddSwaggerGenExt();//SwaggerGen
    28. var app = builder.Build();
    29. app.UseSwaggerUIExt(); //SwaggerUI
    30. app.UseAuthentication();
    31. app.UseAuthorization();
    32. app.MapControllers();
    33. app.Run();

    5、Api接口中使用

    在接口控制器,或者方法上添加版本(组)标识:[ApiExplorerSettings(GroupName = "v1")]

    1. using Microsoft.AspNetCore.Authorization;
    2. using Microsoft.AspNetCore.Mvc;
    3. using Microsoft.IdentityModel.Tokens;
    4. using System.IdentityModel.Tokens.Jwt;
    5. using System.Security.Claims;
    6. using System.Security.Cryptography;
    7. using System.Text;
    8. using WebApp.Enums;
    9. namespace WebApp.Controllers
    10. {
    11. ///
    12. /// 测试接口
    13. ///
    14. [ApiController]//[ApiController]能够推断参数的绑定源,就不需要[FromBody][FromForm][FromHeader][FromQuery][FromRoute]....来主动指定接收参数的形式
    15. [Route("api/[controller]/[action]")]
    16. public class HomeController : ControllerBase
    17. {
    18. private readonly ILogger _logger;
    19. ///
    20. /// 构造函数
    21. ///
    22. ///
    23. public HomeController(ILogger logger)
    24. {
    25. _logger = logger;
    26. }
    27. ///
    28. /// 查询案列1
    29. ///
    30. /// 编号
    31. ///
    32. [HttpGet("Abc")] //url地址是:api/WeatherForecast/Get/Abc
    33. [ApiExplorerSettings(GroupName = "v1")]
    34. [Authorize]
    35. public IActionResult Get(int id)
    36. {
    37. return Ok(id);
    38. //返回值:IActionResult
    39. //return NotFound(); 404
    40. //return Redirect("/Home/Index");
    41. //var content = "Hello, World!";
    42. //return Content(content, "text/plain");
    43. //var data = new { Name = "John", Age = 30 };
    44. //return Json(data);
    45. //var filePath = "/path/to/file.pdf";
    46. //return File(filePath, "application/pdf", "filename.pdf");
    47. //byte[] videoBytes = System.IO.File.ReadAllBytes(containerPath);
    48. //return File(videoBytes, "video/mp4");
    49. }
    50. ///
    51. /// 查询案列2:路由的伪静态
    52. ///
    53. ///
    54. ///
    55. [HttpGet("Abc/{name}")] //url地址是:api/WeatherForecast/Get/Abc/lily :lily是name值, 同时name值是必填的,{name}必须要与action的参数名称一致。这就是路由的伪静态形式
    56. [ApiExplorerSettings(GroupName = nameof(ApiVersion.v1))]
    57. [Authorize]
    58. public IActionResult Get(string name)
    59. {
    60. return Ok(name);
    61. }
    62. ///
    63. /// 客户端登陆
    64. ///
    65. /// 客户端名称
    66. /// 客户端密码
    67. /// 返回jwtToken
    68. [HttpGet]
    69. [ApiExplorerSettings(GroupName = nameof(ApiVersion.v2))]
    70. [Route("api/login")]
    71. public IActionResult Login(string clientid, string password)
    72. {
    73. //这里肯定是需要去连接数据库做数据校验
    74. if (clientid == "admin" && password == "123456")//应该数据库
    75. {
    76. string token = GetJwtToken(clientid);
    77. return Ok(new { token });
    78. }
    79. else
    80. {
    81. return Ok("");
    82. }
    83. }
    84. ///
    85. /// 获取Token
    86. ///
    87. ///
    88. ///
    89. [NonAction]
    90. public string GetJwtToken(string UserName)
    91. {
    92. var issuer = "Issuer";
    93. var audience = "Audience";
    94. var securityKey = "SIGfMA0FCSqGSIb3DFEBAQUAA4GNADCBiQKBgQDI2a2EJ7d872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI593nNDAPfnJsas96mSA9Q/mD8RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB";
    95. Claim[] claims = new[]
    96. {
    97. new Claim(ClaimTypes.Name, UserName)
    98. };
    99. SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(securityKey));
    100. SigningCredentials creds = new(key, SecurityAlgorithms.HmacSha256);
    101. var token = new JwtSecurityToken(
    102. issuer: issuer,
    103. audience: audience,
    104. claims: claims,
    105. expires: DateTime.Now.AddMinutes(1),//5分钟有效期
    106. signingCredentials: creds);
    107. return new JwtSecurityTokenHandler().WriteToken(token);
    108. }
    109. ///
    110. /// 文件上传
    111. ///
    112. ///
    113. ///
    114. [HttpPost]
    115. public JsonResult UploadFile(IFormCollection from)
    116. {
    117. return new JsonResult(new
    118. {
    119. Success = true,
    120. Message = "上传成功",
    121. FileName = from.Files.FirstOrDefault()?.FileName
    122. }) ;
    123. }
    124. ///
    125. /// 标记了[NonAction]特性,则不被视为控制器的操作方法
    126. ///
    127. ///
    128. ///
    129. [HttpPost(Name = "{id}")]
    130. [NonAction]
    131. public string PostTest(int id)
    132. {
    133. return id.ToString();
    134. }
    135. }
    136. }

    6、项目配置生成XML文件

    7、效果图

    7、注意点:

    如果只是单纯只返回token的时候,记得在控制器右上角的Authorize里  先写Bearer+空格+你的token 

  • 相关阅读:
    IntelliJ IDEA - 将指定文件打成jar包
    c++&qt day11
    端到端自动驾驶系列(一):自动驾驶综述解析
    Oracle Primavera Unifier uDesigner 资产管理器(Asset Manager )
    React 学习笔记目录
    腾讯mini项目-【指标监控服务重构-会议记录】2023-08-04
    Redis 的过期键 | Navicat 技术干货
    20道你必须要背会的微服务面试题,面试一定会被问到
    bash for循环
    【Kotlin精简】第7章 泛型
  • 原文地址:https://blog.csdn.net/Fanbin168/article/details/134513789