平常做项目使用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
{
/// <summary>
/// swagger请求头
/// </summary>
public class HttpHeaderOperationFilter : IOperationFilter
{
/// <summary>
///
/// </summary>
/// <param name="operation"></param>
/// <param name="context"></param>
public void Apply(Operation operation, OperationFilterContext context)
{
#region 新方法
if (operation.Parameters == null)
{
operation.Parameters = new List<IParameter>();
}
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
/// <summary>
///
/// </summary>
/// <param name="services"></param>
// 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<IControllerActivator, ServiceBasedControllerActivator>());
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<MvcOptions>(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<HttpHeaderOperationFilter>();
c.DocumentFilter<HiddenApiFilter>();
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<EFCoreDBContext>(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
{
/// <summary>
/// 权限
/// </summary>
public class BasicAuth : ActionFilterAttribute
{
/// <summary>
///
/// </summary>
/// <param name="context"></param>
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]
/// <summary>
/// 添加
/// </summary>
/// <param name="model"></param>
/// <returns>主键id</returns>
[BasicAuth]
[ModelValidationAttribute]
[ApiExplorerSettings(GroupName = "v1")]
[HttpPost, Route("Create")]
public async Task<ResultDto<long>> 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