https://www.nuget.org/packages/Swashbuckle.AspNetCore.SwaggerGen/html
1.添加核心NUGET包 Swashbuckle.AspNetCore:git
2.startup中配置:github
ConfigureServices中:web
//註冊swagger生成器,定義一個或多個swagger文檔 services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new Info { Version = "v1", Title = "測試 API", Description = "A simple example ASP.NET Core Web API", TermsOfService = "None", Contact = new Contact { Name = "ck", Email = "", Url = "http://www.cnblogs.com/chuankang/" }, License = new License { Name = "博客園", Url = "http://www.cnblogs.com/chuankang/" } }); // api描述文檔xml的生成地址和文件名,須要在項目的屬性中進行配置 var basePath = AppContext.BaseDirectory; var xmlPath = Path.Combine(basePath, "SwaggerDemo.xml"); if (File.Exists(xmlPath)) { c.IncludeXmlComments(xmlPath); } });
Configure中:數據庫
// 啓用中間件以生成JSON做爲JSON端點. app.UseSwagger(); // 啓用中間件以提供用戶界面(HTML、js、CSS等),特別是指定JSON端點。 app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); //頁面頭名稱 c.DocumentTitle = "平臺API"; //頁面API文檔格式 Full=所有展開, List=只展開列表, None=都不展開 c.DocExpansion(DocExpansion.List); });
注意:c.SwaggerDoc的第一個參數 要和 c.SwaggerEndpoint第一個參數 字符串swagger/後面的對應,本例用的是v1編程
3.api描述文檔xml的生成地址和文件名,須要在項目的屬性中進行配置,右鍵項目-> 屬性-> 生成 以下圖:json
加上1591忽略屬性類名必須加xml註釋api
4.在controller中action方法都要指定http請求Post(新增),Put(修改),Delete(刪除),Get(查詢)中的一個,否則會報錯:
http://localhost:55642/swagger/v1/swagger.json 瀏覽器F12控制檯查看錯誤緣由瀏覽器
5.啓動看效果:緩存
6.每次輸入/swagger太麻煩,能夠設置藉助vs進行跳轉,以下圖加上 "launchUrl": "swagger" :
7.若是controller繼承了本身定義的基類controller,要爲本身定義的方法加上NonActionFillter,由於swagger要爲每一個action添加http mehod
ConfigureServices中:
c.SwaggerDoc("v2", new Info { Version = "v2", Title = "API 版本2" });
Configure中: c.SwaggerEndpoint("/swagger/v2/swagger.json", "API V2");
在action上指定版本,不指定版本的action在全部版本中都顯示
swagger給咱們默認的路由是:http://localhost:49833/swagger/index.html
若是有不少個API項目怎麼區分呢?咱們能夠指定路由把swagger替換掉
那麼咱們如今應該請求的路由爲:http://localhost:49833/test/index.html
爲action指定Obsolete特性表示過期了,但並不表示不可使用
運行:
怎麼把這過期的接口不顯示在swagger頁面呢?
只須要在生成器中加入options.IgnoreObsoleteActions();屬性就好了
例以下面只獲取HttpGet請求的接口顯示在界面上
// ApiExplorerGetsOnlyConvention.cs public class ApiExplorerGetsOnlyConvention : IActionModelConvention { public void Apply(ActionModel action) { action.ApiExplorer.IsVisible = action.Attributes.OfType<HttpGetAttribute>().Any(); } } // Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddMvc(c => c.Conventions.Add(new ApiExplorerGetsOnlyConvention()) ); ... }
services.AddSwaggerGen(c => { ... c.TagActionsBy(api => api.HttpMethod); };
services.AddSwaggerGen(c => { ... c.OrderActionsBy((apiDesc) => $"{apiDesc.ActionDescriptor.RouteValues["controller"]}_{apiDesc.HttpMethod}"); };
安裝nuget Swashbuckle.AspNetCore.Annotations
啓用:
services.AddSwaggerGen(c =>
{
...
c.EnableAnnotations();
});
爲controller加註釋
爲action加註釋
[HttpPost] [SwaggerOperation( Summary = "Creates a new product", Description = "Requires admin privileges", OperationId = "CreateProduct", Tags = new[] { "Purchase", "Products" } )] public IActionResult Create([FromBody]Product product)
爲響應加驗證
[HttpPost] [SwaggerResponse(201, "The product was created", typeof(Product))] [SwaggerResponse(400, "The product data is invalid")] public IActionResult Create([FromBody]Product product)
ConfigureServices添加
public void ConfigureServices(IServiceCollection services) { #region swagger services.AddSwaggerGen(c => { //啓用註釋nuget包 c.EnableAnnotations(); c.SwaggerDoc("WebApiA", new Info { Title = "用戶API接口A", Version = "v1" }); //var basePath = PlatformServices.Default.Application.ApplicationBasePath; string basePath = AppContext.BaseDirectory;//Linux路徑區分大小寫,這裏用appcontext string xmlPath = Path.Combine(basePath, "WebApiA.xml"); //若是有xml註釋文檔就讀取,需在項目屬性生成xml if (File.Exists(xmlPath)) { c.IncludeXmlComments(xmlPath); } #region Token綁定到ConfigureServices //添加header驗證信息 //c.OperationFilter<SwaggerHeader>(); var security = new Dictionary<string, IEnumerable<string>> { { "Blog.Core", new string[] { } }, }; c.AddSecurityRequirement(security); //方案名稱「Blog.Core」可自定義,上下一致便可 c.AddSecurityDefinition("Blog.Core", new ApiKeyScheme { Description = "JWT受權(數據將在請求頭中進行傳輸) 直接在下框中輸入{token}\"", Name = "Authorization",//jwt默認的參數名稱 In = "header",//jwt默認存放Authorization信息的位置(請求頭中) Type = "apiKey" }); #endregion }); #endregion #region Token服務註冊 services.AddSingleton<IMemoryCache>(factory => { var cache = new MemoryCache(new MemoryCacheOptions()); return cache; }); services.AddAuthorization(options => { options.AddPolicy("Client", policy => policy.RequireRole("Client").Build()); options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build()); options.AddPolicy("AdminOrClient", policy => policy.RequireRole("Admin,Client").Build()); }); #endregion services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
啓動:
每次請求時,從Header報文中,獲取密鑰token,這裏根據token能夠進一步判斷相應的權限等
添加類
JwtHelper:
using Microsoft.IdentityModel.Tokens; using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using WebApiA.Models; namespace WebApiA.AuthHelper { /// <summary> /// JWT序列化和反序列化 /// </summary> public class JwtHelper { public static string SecretKey { get; set; } = "sdfsdfsrty45634kkhllghtdgdfss345t678fs"; /// <summary> /// 頒發JWT字符串 /// </summary> /// <param name="tokenModel"></param> /// <returns></returns> public static string IssueJWT(TokenModelJWT tokenModel) { var dateTime = DateTime.UtcNow; var claims = new Claim[] { new Claim(JwtRegisteredClaimNames.Jti,tokenModel.Uid.ToString()),//Id new Claim("Role", tokenModel.Role),//角色 new Claim(JwtRegisteredClaimNames.Iat,dateTime.ToString(),ClaimValueTypes.Integer64) }; //祕鑰 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtHelper.SecretKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var jwt = new JwtSecurityToken( issuer: "Blog.Core", claims: claims, //聲明集合 expires: dateTime.AddHours(2), signingCredentials: creds); var jwtHandler = new JwtSecurityTokenHandler(); var encodedJwt = jwtHandler.WriteToken(jwt); return encodedJwt; } /// <summary> /// 解析 /// </summary> /// <param name="jwtStr"></param> /// <returns></returns> public static TokenModelJWT SerializeJWT(string jwtStr) { var jwtHandler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr); object role = new object(); ; try { jwtToken.Payload.TryGetValue("Role", out role); } catch (Exception e) { Console.WriteLine(e); throw; } var tm = new TokenModelJWT { Uid = Convert.ToInt32(jwtToken.Id), Role = role != null ? role.ToString() : "", }; return tm; } } }
JwtTokenAuth:
/// <summary> /// 中間件 /// </summary> public class JwtTokenAuth { private readonly RequestDelegate _next; public JwtTokenAuth(RequestDelegate next) { _next = next; } public Task Invoke(HttpContext httpContext) { //檢測是否包含'Authorization'請求頭 if (!httpContext.Request.Headers.ContainsKey("Authorization")) { return _next(httpContext); } var tokenHeader = httpContext.Request.Headers["Authorization"].ToString(); TokenModelJWT tm = JwtHelper.SerializeJWT(tokenHeader);//序列化token,獲取受權 //受權 注意這個能夠添加多個角色聲明,請注意這是一個 list var claimList = new List<Claim>(); var claim = new Claim(ClaimTypes.Role, tm.Role); claimList.Add(claim); var identity = new ClaimsIdentity(claimList); var principal = new ClaimsPrincipal(identity); httpContext.User = principal; return _next(httpContext); } }
startup的Configure中加入
//將TokenAuth註冊中間件 app.UseMiddleware<JwtTokenAuth>();
接口加權限filter
啓動調用會報錯
是由於每次操做請求,都會通過TokenAuth 中的Invoke方法,方法中對Header信息進行過濾,由於如今Header中,並無相應的配置信息,看到這裏,你就想到了,這個特別像咱們常見的[HttpGet]等特性,沒錯!在.Net Core 中,處處均可以看到AOP編程,真的特別強大。
這個時候咱們就用到了最開始的那個權限按鈕
新建一個LoginController,來模擬一次登錄操做,簡單傳遞幾個參數,將用戶角色和緩存時間傳遞,而後生成Token,並生成到緩存中,爲以後作準備。
[Route("api/[controller]")] public class LoginController : Controller { /// <summary> /// 獲取JWT的重寫方法,推薦這種,注意在文件夾OverWrite下 /// </summary> /// <param name="id">id</param> /// <param name="sub">角色</param> /// <returns></returns> [HttpGet] [Route("Token2")] public JsonResult GetJWTStr(long id = 1, string sub = "Admin") { //這裏就是用戶登錄之後,經過數據庫去調取數據,分配權限的操做 TokenModelJWT tokenModel = new TokenModelJWT(); tokenModel.Uid = id; tokenModel.Role = sub; string jwtStr = JwtHelper.IssueJWT(tokenModel); return Json(jwtStr); } }
調用獲取tonken
複製到這裏驗證:
再次調用接口就能夠了
示例代碼:https://github.com/chuankang/DotNetCore/tree/master/OwnSpace/WebApiA
參考文檔:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/web-api-help-pages-using-swagger