.NET Core 使用Swagger并启用API文档的JWT授权


一、概述

刚参加工作时,写个API接口,还要写API文档,再使用PostMan测试接口,写文档的时间比写接口还要折腾。后来接触Swagger,API文档的工作得到了很大的改善,不但可以自动构建交互式API说明文档,还能直接调试API接口。今天记录下Core项目下使用Swagger,最新版的Swagger已经完美支持Open Api规范及JWT Token授权访问等。使用Swagger的好处总结如下:

  • 使用 Swagger 生成精美的API接口文档
  • 使用 Swagger 调试JWT授权接口
  • 使用 Swagger 生成各个类库中视图模型的描述

二、配置Swagger服务

1、引用Nuget包

新建一个.NET Core 3.1 Web Api 项目,打开Nuget安装管理器,搜索Swashbuckle.AspNetCore,安装即可

2、配置服务

我们打开Startup.cs文件,来对Swagger配置进行一些必要的配置,在ConfigureServices方法我们添加一下Swagger配置:

public void ConfigureServices(IServiceCollection services)
{

  services.AddControllers();
  services.AddSwaggerGen(c =>
  {
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });
  });
}

然后我们在Configure方法里添加swagger中间件:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
  if (env.IsDevelopment())
  {
    app.UseDeveloperExceptionPage();
    app.UseSwagger();
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Core.Api v1"));
  }

  app.UseHttpsRedirection();

  app.UseRouting();

  app.UseAuthorization();

  app.UseEndpoints(endpoints =>
  {
  endpoints.MapControllers();
  });
}

这样swagger基本配置就完成了,看下效果

3、忽略注释警告

F5运行项目后发现有很多警告:

原因是是swagger把一些 action 方法都通过xml文件配置了,如果没有加入相应的注释就会警告。如果不想每一个方法都加注释,可以如下配置:选择项目,右键属性,选择生成菜单,加入;1591

4、为接口添加注释

右键项目名称=>属性=>生成,勾选“输出”下面的“xml文档文件”,系统会默认生成一个xml。

此时项目中会生成一个 Core.Api.xml文件,修改该文件属性,选择较新则复制。然后修改下startup.cs中的ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
{
  services.AddControllers();
  services.AddSwaggerGen(c =>
  {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });
        // 为 Swagger JSON and UI设置xml文档注释路径
        //获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径)
        var basePath = AppContext.BaseDirectory;
        var xmls = Directory.GetFiles(basePath, "*.xml");
        foreach (var aXml in xmls)
        {
            c.IncludeXmlComments(aXml);
        }
   });
}

然后action方法上加入注释:

/// <summary>
/// 获取数据
/// </summary>
/// <returns></returns>
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
     var rng = new Random();
     return Enumerable.Range(1, 5).Select(index => new WeatherForecast
     {
           Date = DateTime.Now.AddDays(index),
           TemperatureC = rng.Next(-20, 55),
           Summary = Summaries[rng.Next(Summaries.Length)]
      })
      .ToArray();
}

看下效果:

5、为Model 添加注释

新建一个model,加入字段注释

public class StudentModel
{
  /// <summary>
  /// 标识
  /// </summary>
  public int ID { get; set; }
  /// <summary>
  /// 姓名
  /// </summary>
  public string Name { get; set; }
}

为model所在的项目也要配置xml,类似于上述第三步

//注入model 的xml 
var xmlModelPath = Path.Combine(basePath, "xx.Model.xml");//这个就是Model层的xml文件名 c.IncludeXmlComments(xmlModelPath);

控制器中引用:

/// <summary>
/// 插入学生信息
/// </summary>
/// <param name="studentModel">model实体类参数</param>
/// <returns></returns>
[HttpPost]
public bool Insert([FromQuery] StudentModel studentModel)
{
  return true;
}

效果如下:

6、隐藏接口

如果不想显示某些接口,直接在controller 上,或者action 上,增加特性可隐藏接口

[ApiExplorerSettings(IgnoreApi = true)]

7、Swagger启用API文档的JWT授权

目前很多网站都使用了JWT(JSON WEB TOKEN)来作为账户系统的认证授权,JWT以它的简单、高效、分布式优势很快成为了网站的流行验证方式。接下来我们为Swagger添加JWT授权认证,依旧打开Startup.cs文件,修改上面ConfigureServices方法中的代码:

public void ConfigureServices(IServiceCollection services)
{

  services.AddControllers();
  services.AddSwaggerGen(c =>
  {
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });

    #region 加载xml
    // 为 Swagger JSON and UI设置xml文档注释路径
    //获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径)
    var basePath = AppContext.BaseDirectory;
    var xmls = Directory.GetFiles(basePath, "*.xml");
    foreach (var aXml in xmls)
    {
      c.IncludeXmlComments(aXml);
    }
    #endregion

    #region jwt认证
    // 开启加权小锁
    c.OperationFilter<AddResponseHeadersFilter>();
    c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
    // 在header中添加token,传递到后台
    c.OperationFilter<SecurityRequirementsOperationFilter>();
    // Jwt Bearer 认证
    c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
      Name = "Authorization",//jwt默认的参数名称
      In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
      Type = SecuritySchemeType.ApiKey,
      Description = "Authorization:Bearer {your JWT token},注意两者之间是一个空格",
    });
    #endregion
  });
}

预览一下授权设置,发现右侧多了一个Authorize绿色的带锁按钮,这个按钮点开后就可以设置我们的JWT Token信息了,格式是:Bearer 你的Token字符串,注意Bearer于Token之间有个空格。设置好Token后,你请求任意的API接口时,Swagger会自动附带Token到请求的Header中。

既然swagger中支持了jwt认证,那么我们在startup.cs中启用jwt认证:如下

     public void ConfigureServices(IServiceCollection services)
        {

            services.AddControllers();
            #region 开启jwt认证
            var symmetricKeyAsBase64 = "!@#123";
            var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey = new SymmetricSecurityKey(keyByteArray);
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(o =>
            {
                o.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = signingKey,
                    ValidateIssuer = true,
                    ValidIssuer = "asd",//发行人
                    ValidateAudience = true,
                    ValidAudience = "fdf",//订阅人
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero,//这个是缓冲过期时间,也就是说,即使我们配置了过期时间,这里也要考虑进去,过期时间+缓冲
                    RequireExpirationTime = true,
                };

            });
            #endregion
            #region 配置swagger文档
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });

                #region 加载xml
                // 为 Swagger JSON and UI设置xml文档注释路径
                //获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径)
                var basePath = AppContext.BaseDirectory;
                var xmls = Directory.GetFiles(basePath, "*.xml");
                foreach (var aXml in xmls)
                {
                    c.IncludeXmlComments(aXml);
                }
                #endregion

                #region jwt认证
                // 开启加权小锁
                c.OperationFilter<AddResponseHeadersFilter>();
                c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
                // 在header中添加token,传递到后台
                c.OperationFilter<SecurityRequirementsOperationFilter>();
                // Jwt Bearer 认证
                c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                {
                    Name = "Authorization",//jwt默认的参数名称
                    In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                    Type = SecuritySchemeType.ApiKey,
                    Description = "Authorization:Bearer {your JWT token},注意两者之间是一个空格",
                });
                #endregion
            });
            #endregion
        }

更详细关于jwt认证的这里就不细讲了

8、默认直接访问swagger

有时候打开webapi项目,希望直接打开swagger文档,有两种方法:

  • 方法一:设置launchSettings.json文件中的launchUrl属性,指定为swagger,如下:

  • 方法二我们可以通过RoutePrefix 属性设置。
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "Core.Api v1");
    c.RoutePrefix = ""; //路径配置,设置为空,表示直接在根域名访问swagger文件
});

建议使用方法二。

三、Swagger异常汇总

1、问题一

如果出现如上图那样的错误,请打开swagger/v1/swagger.json查看具体原因。 常见的原因是action上没有加入HTTP请求协议,比如[HttpPost]

2、问题二

这是因为接口json文档定义和调用不是一个,请仔细对比下定义和调用的swagger名称是否一致。比如定义的时候名称为“v1”:

 c.SwaggerDoc("v1", new OpenApiInfo { Title = "Core.Api", Version = "v1" });

调用的时候也要保证一致:

app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Core.Api v1")); 

3、问题三

上图错误是路由重载导致的,请确保不要存在多个一样的路由。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM