zoukankan      html  css  js  c++  java
  • 【Core Swagger】.NET Core中使用swagger

     一.入门

     https://www.nuget.org/packages/Swashbuckle.AspNetCore.SwaggerGen/

    1.添加核心NUGET包 Swashbuckle.AspNetCore

    2.startup中配置:

    ConfigureServices中:

               //注册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的生成地址和文件名,需要在项目的属性中进行配置,右键项目-> 属性-> 生成 如下图:

    加上1591忽略属性类名必须加xml注释

     

    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

     二.设置多个API版本

    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();属性就行了

     五.忽略某个Api,不在ui页面中显示

     六.仅获取某个Http请求的action

    例如下面只获取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())
        );
    
        ...
    }

     七.对action根据Http请求进行分组

    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)

     十.Token验证

    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;
            }
        }
    }
    View Code

     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);
            }
        }
    View Code

    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

                      https://github.com/domaindrivendev/Swashbuckle.AspNetCore

    隐藏相关接口 

    对于不想暴漏给Swagger展示的接口,我们可以给相关Controller或Action头加上:[ApiExplorerSettings(IgnoreApi = true)]

    未雨绸缪、富有耐心、律己严厉和不偏不倚
  • 相关阅读:
    notepad++ 安装
    Git 安装
    C 字符串常量 数据类型
    vue路由传参query和params的区别
    mysql 在 centos 上安装,做成服务,且开机启动 步骤
    全网最详细Apache Kylin1.5安装(单节点)和测试案例 ---> 现在看来 kylin 需要 安装到Hadoop Master 节点上
    Kylin build cube step 2 报错(Kylin 安装在slave 节点上)
    Kylin build cube step 2 报错
    Kylin 环境 搭建 成功
    Kylin 环境 搭建 报错
  • 原文地址:https://www.cnblogs.com/chuankang/p/8783761.html
Copyright © 2011-2022 走看看