本文共 9067 字,大约阅读时间需要 30 分钟。
平常做项目使用mvc+webapi,采取前后端分离的方式,后台提供API接口给前端开发人员。这个过程中遇到一个问题后台开发人员怎么提供接口说明文档给前端开发人员。为了解决这个问题,项目中引用swagger(我比较喜欢戏称为“丝袜哥”)。
列出所有API控制器和控制器描述
那么既然是api,肯定涉及到安全验证问题,那么怎么在测试文档增加添加Token安全验证呢;
下面我们来看看
1、定义swagger请求头
using Microsoft.AspNetCore.Authorization;using Swashbuckle.AspNetCore.Swagger;using Swashbuckle.AspNetCore.SwaggerGen;using System.Collections.Generic;using System.Linq;using System.Reflection;namespace CompanyName.ProjectName.HttpApi.Host.Code{ ////// swagger请求头 /// public class HttpHeaderOperationFilter : IOperationFilter { ////// /// /// /// public void Apply(Operation operation, OperationFilterContext context) { #region 新方法 if (operation.Parameters == null) { operation.Parameters = new List(); } if (context.ApiDescription.TryGetMethodInfo(out MethodInfo methodInfo)) { if (methodInfo.CustomAttributes.All(t => t.AttributeType != typeof(AllowAnonymousAttribute)) && !(methodInfo.ReflectedType.CustomAttributes.Any(t => t.AttributeType == typeof(AuthorizeAttribute)))) { operation.Parameters.Add(new NonBodyParameter { Name = "Authorization", In = "header", Type = "string", Required = true, Description = "请输入Token,格式为bearer XXX" }); } } #endregion 新方法 } }}
2、在ConfigureServices方法添加OperationFilter
////// /// /// // This method gets called by the runtime. Use this method to add services to the container. public IServiceProvider ConfigureServices(IServiceCollection services) { services.Replace(ServiceDescriptor.Transient()); services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore; options.SerializerSettings.Converters.Add( new Newtonsoft.Json.Converters.IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" } ); //小写 options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); options.SerializerSettings.ContractResolver = new DefaultContractResolver(); // // options.SerializerSettings.DateFormatString = "yyyy-MM-dd"; }); // services.AddMvc().AddXmlSerializerFormatters(); // services.AddMvc().AddXmlDataContractSerializerFormatters(); services.AddLogging(); services.AddCors(options => options.AddPolicy("AllowSameDomain", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader() )); services.Configure (options => { options.Filters.Add(new CorsAuthorizationFilterFactory("AllowSameDomain")); }); #region Swagger services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Version = "v1", Title = "接口文档", Description = "接口文档-基础", TermsOfService = "https://example.com/terms", Contact = new Contact { Name = "XXX1111", Email = "XXX1111@qq.com", Url = "https://example.com/terms" } , License = new License { Name = "Use under LICX", Url = "https://example.com/license", } }); c.SwaggerDoc("v2", new Info { Version = "v2", Title = "接口文档", Description = "接口文档-基础", TermsOfService = "https://example.com/terms", Contact = new Contact { Name = "XXX2222", Email = "XXX2222@qq.com", Url = "https://example.com/terms" } , License = new License { Name = "Use under LICX", Url = "https://example.com/license", } }); c.OperationFilter (); c.DocumentFilter (); var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"CompanyName.ProjectName.ICommonServer.xml")); }); #endregion Swagger #region MiniProfiler if (bool.Parse(Configuration["IsUseMiniProfiler"])) { //https://www.cnblogs.com/lwqlun/p/10222505.html services.AddMiniProfiler(options => options.RouteBasePath = "/profiler" ).AddEntityFramework(); } #endregion MiniProfiler services.AddDbContext (options => options.UseMySql(Configuration["Data:MyCat:ConnectionString"])); var container = AutofacExt.InitAutofac(services, Assembly.GetExecutingAssembly()); return new AutofacServiceProvider(container); }
3、定义一个ActionFilterAttribute
using CompanyName.ProjectName.Core;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Filters;using Newtonsoft.Json;using System.Security.Principal;namespace CompanyName.ProjectName.HttpApi.Host{ ////// 权限 /// public class BasicAuth : ActionFilterAttribute { ////// /// /// public override void OnActionExecuting(ActionExecutingContext context) { if (context.HttpContext.Request != null && context.HttpContext.Request.Headers != null && context.HttpContext.Request.Headers["Authorization"].Count > 0) { var token = context.HttpContext.Request.Headers["Authorization"]; if (string.IsNullOrWhiteSpace(token)) { ResultDto meta = ResultDto.Err("Unauthorized"); JsonResult json = new JsonResult(new { Meta = meta } ); JsonSerializerSettings jsetting = new JsonSerializerSettings(); jsetting.NullValueHandling = NullValueHandling.Ignore; jsetting.Converters.Add( new Newtonsoft.Json.Converters.IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" } ); json.SerializerSettings = jsetting; json.ContentType = "application/json; charset=utf-8"; context.Result = json; } else { GenericIdentity ci = new GenericIdentity(token); ci.Label = "conan1111111"; context.HttpContext.User = new GenericPrincipal(ci, null); } } else { ResultDto meta = ResultDto.Err("Unauthorized"); JsonResult json = new JsonResult(new { Meta = meta } ); JsonSerializerSettings jsetting = new JsonSerializerSettings(); jsetting.NullValueHandling = NullValueHandling.Ignore; jsetting.Converters.Add( new Newtonsoft.Json.Converters.IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" } ); json.SerializerSettings = jsetting; json.ContentType = "application/json; charset=utf-8"; context.Result = json; } base.OnActionExecuting(context); } }}
4、最后在需要的地方使用 [BasicAuth]
////// 添加 /// /// ///主键id [BasicAuth] [ModelValidationAttribute] [ApiExplorerSettings(GroupName = "v1")] [HttpPost, Route("Create")] public async Task> CreateAsync([FromBody]CreateWebConfigDto model) { return await _webConfigApp.CreateAsync(model, new Core.CurrentUser()); }
我们就可以看到Authorization - 请输入Token,格式为bearer XXX
源码地址:
https://github.com/conanl5566/Sampleproject/tree/master/src/03%20Host/CompanyName.ProjectName.HttpApi.Host