.Net6 Api Swagger配置

news2024/9/30 17:33:01

1、定义个Swagger版本(组)的枚举

namespace WebApp.Enums
{
    /// <summary>
    /// api版本枚举
    /// </summary>
    public enum ApiVersion
    {
        /// <summary>
        /// v1版本
        /// </summary>
        v1 = 1,
        /// <summary>
        /// v2版本
        /// </summary>
        v2 = 2,
    }
}

2、添加SwaggerExtentsion扩展类,配置注册Swagger

using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Net.Http.Headers;
using System.Net;
using System.Reflection;
using System.Text;
using WebApp.Enums;

namespace WebApp.Common.Swagger
{
    /// <summary>
    /// SwaggerDoc配置
    /// 用法:在Program.cs文件中进行注册:builder.AddSwaggerGenExt();
    /// </summary>
    public static class SwaggerExtension
    {
        /// <summary>
        /// 扩展方法:Swagger文档
        /// </summary>
        /// <param name="services"></param>
        public static void AddSwaggerGenExt(this IServiceCollection services)
        {
            #region 添加Swagger
            //获取的是当前执行的方法所在的程序文件的名称:即项目名称,例如我的项目名称叫webapp 
            var AssemblyName = Assembly.GetExecutingAssembly().GetName().Name;
            services.AddSwaggerGen(options =>
            {
                #region 配置版本
                //options.SwaggerDoc("v1", new OpenApiInfo { Title = "售楼API", Version = "v1" });
                typeof(ApiVersion).GetEnumNames().ToList().ForEach(version =>
                {
                    options.SwaggerDoc(version, new OpenApiInfo()
                    {
                        Version = version,
                        Title = "凤凰网管理系统",
                        Description = $"凤凰网接口服务    版本: {version}",
                        Contact = new OpenApiContact
                        {
                            Name = "潇湘夜雨",
                            Email = "123@qq.com"
                        }
                    });
                });

                #endregion
                #region 配置注释文档

                // 获取当前项目的 XML文档文件路径:比如我的项目名称叫WebApp,那么它默认的 XML文档文件路径就是当前项目下的 WebApp.xml
                var xmlFile = $"{AssemblyName}.xml";
                var xmlFileFullPath = Path.Combine(AppContext.BaseDirectory, xmlFile);

                //var domainXmlPath = Path.Combine(AppContext.BaseDirectory, "Bgy.Domain.xml");      // 获取Bgy.Domain.xml文件路径
                //var viewmodelXmlPath = Path.Combine(AppContext.BaseDirectory, "Bgy.ViewModel.xml");// 获取Bgy.ViewModel.xml文件路径

                options.IncludeXmlComments(xmlFileFullPath, true); // 添加控制器层注释,true表示显示控制器注释

                //options.IncludeXmlComments(domainXmlPath);       // 添加Domain层注释
                //options.IncludeXmlComments(viewmodelXmlPath);    // 添加ViewModel层注释

                //对action的名称进行排序。
                options.OrderActionsBy(o => o.RelativePath);

                #endregion

                #region 配置授权认证信息

                //添加一个必须的全局安全信息,
                //第一个参数是方案唯一名称:和AddSecurityDefinition方法指定的方案名称标识一致即可:BearerAuth
                //第二个参数是方案的描述:可以是BasicAuthScheme、ApiKeyScheme的实例或OAuth2Scheme
                options.AddSecurityDefinition("BearerAuth", new OpenApiSecurityScheme()
                {
                    Description = "在下框中输入请求头中需要添加Jwt授权Token:Bearer Token",
                    Name = "Authorization",
                    In = ParameterLocation.Header, //配置jwt默认加在Authorization信息的位置:这里配置的是将jwt信息放在请求头Header中            
                    Type = SecuritySchemeType.Http,//使用Authorize头部                  
                    Scheme = "bearer", //内容为以 bearer开头
                    BearerFormat = "JWT",
                    //Reference= new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" }
                });

                //注册全局认证(所有的接口都可以使用认证)
                options.AddSecurityRequirement(new OpenApiSecurityRequirement()
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "BearerAuth" //方案名称标识
                            }
                        },
                        new string[] {} //不设权限
                    }
                });

                #endregion

                #region 在Swagger中扩展文件上传按钮
                options.OperationFilter<FileUploadFilter>();
                #endregion
            });
            #endregion
        }

        /// <summary>
        /// 扩展方法:配置SwaggerUI
        /// 用法:在Program.cs文件中进行注册:app.UseSwaggerUIExt();
        /// </summary>
        /// <param name="app"></param>
        public static void UseSwaggerUIExt(this WebApplication app)
        {
            //SwaggerBasicAuthMiddleware:是我自己扩展的一个中间件:目的是需要登陆才能到达Swagger的Index页面中,否则无法进入:可以根据需要去掉这个
            //需要安装:Swashbuckle.AspNetCore包
            //app.UseMiddleware<SwaggerBasicAuthMiddleware>();

            if (app.Environment.IsDevelopment())
            {
                //app.UseSwagger();
                //app.UseSwaggerUI();
            }

            var enviroment = app.Configuration["Swagger:environmentVariables"];
            switch (enviroment)
            {
                case "development":
                    app.UseSwagger();//启用Swagger中间件

                    app.UseSwaggerUI(options =>  //配置版本
                    {
                        typeof(ApiVersion).GetEnumNames().ToList().ForEach(version =>
                        {
                            options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version);
                        });

                    });

                    break;
                case "testing":
                    app.UseSwagger();
                    app.UseSwaggerUI(options =>
                    {
                        typeof(ApiVersion).GetEnumNames().ToList().ForEach(version =>
                        {
                            options.SwaggerEndpoint($"/swagger/{version}/swagger.json", version);
                        });
                    });
                    break;
                case "production":
                    break;

            }
        }
    }

    #region 扩展功能
    /// <summary>
    /// 文件上传的扩展:实现在Swagger中上传文件的功能
    /// </summary>
    public class FileUploadFilter : IOperationFilter
    {
        /// <summary>
        /// 文件上传筛选:只有上传文件的方法才添加此功能
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="context"></param>
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            const string FileUploadContentType = "multipart/form-data";
            if (operation.RequestBody == null || !operation.RequestBody.Content.Any(x => x.Key.Equals(FileUploadContentType, StringComparison.InvariantCultureIgnoreCase)))
            {
                return;
            }
            if (context.ApiDescription.ParameterDescriptions[0].Type == typeof(IFormCollection))
            {
                operation.RequestBody = new OpenApiRequestBody
                {
                    Description = "文件上传",
                    Content = new Dictionary<string, OpenApiMediaType>
                    {
                        {
                            FileUploadContentType,new OpenApiMediaType
                            {
                                Schema=new OpenApiSchema
                                {
                                    Type="object",
                                    Required=new HashSet<string>{ "file"},
                                    Properties=new Dictionary<string, OpenApiSchema>
                                    {
                                        {
                                            "file",new OpenApiSchema
                                            {
                                                Type="string",
                                                Format="binary"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                };
            }
        }
    }

    /// <summary>
    /// 如何在ASP.Net Core的生产环境中保护swagger ui,也就是index.html页面。其实swagger是自带禁用的功能的,只需要设置开关即可。
    /// 但是有一些场景,是需要把这些接口进行开放或者导出成文档供第三方进行调用,这个时候却又不想让所有人访问。
    /// 这里介绍一种权限控制访问的方式,用来指定用户使用;
    /// </summary>
    public class SwaggerBasicAuthMiddleware
    {
        private readonly RequestDelegate next;
        /// <summary>
        /// 增加对swagger ui的验证
        /// </summary>
        /// <param name="next"></param>
        public SwaggerBasicAuthMiddleware(RequestDelegate next)
        {
            this.next = next;
        }
        /// <summary>
        /// 登陆功能实现
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task InvokeAsync(HttpContext context)
        {
            if (context.Request.Path.StartsWithSegments("/swagger"))
            {
                string authHeader = context.Request.Headers["Authorization"];
                if (authHeader != null && authHeader.StartsWith("Basic "))
                {
                    // Get the credentials from request header
                    var header = AuthenticationHeaderValue.Parse(authHeader);
                    var inBytes = Convert.FromBase64String(header.Parameter);
                    var credentials = Encoding.UTF8.GetString(inBytes).Split(':');
                    var username = credentials[0];
                    var password = credentials[1];

                    //用户身份认证
                    if (username.Equals("admin") && password.Equals("123456"))
                    {
                        await next.Invoke(context).ConfigureAwait(false);
                        return;
                    }
                }
                context.Response.Headers["WWW-Authenticate"] = "Basic";
                context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            }
            else
            {
                await next.Invoke(context).ConfigureAwait(false);
            }
        }
    }
    #endregion
}

3、appsettings.json配置文件

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Swagger": {
    "environmentVariables": "development" //:development  :testing  :production
  }
}

4、在Program.cs中注册SwaggerDoc及启用SwaggerUI

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using WebApp.Common.Swagger;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();


#region JWT鉴权授权
var audience = "Audience";
var issuer = "Issuer";
var securityKey = "SIGfMA0FCSqGSIb3DFEBAQUAA4GNADCBiQKBgQDI2a2EJ7d872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI593nNDAPfnJsas96mSA9Q/mD8RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB";
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)  //默认授权机制名称;                                      
         .AddJwtBearer(options =>
         {
             options.TokenValidationParameters = new TokenValidationParameters
             {
                 ValidateIssuer = true,//是否验证Issuer
                 ValidateAudience = true,//是否验证Audience
                 ValidateLifetime = true,//是否验证失效时间
                 ValidateIssuerSigningKey = true,//是否验证SecurityKey
                 ValidAudience = audience,//Audience
                 ValidIssuer = issuer,//Issuer,这两项和前面签发jwt的设置一致  表示谁签发的Token
                 IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey))//拿到SecurityKey
             };
         });
#endregion


builder.Services.AddSwaggerGenExt();//SwaggerGen

var app = builder.Build();

app.UseSwaggerUIExt(); //SwaggerUI

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

app.Run();

5、Api接口中使用

在接口控制器,或者方法上添加版本(组)标识:[ApiExplorerSettings(GroupName = "v1")]

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using WebApp.Enums;

namespace WebApp.Controllers
{
    /// <summary>
    /// 测试接口
    /// </summary>
    [ApiController]//[ApiController]能够推断参数的绑定源,就不需要[FromBody][FromForm][FromHeader][FromQuery][FromRoute]....来主动指定接收参数的形式
    [Route("api/[controller]/[action]")]
  
    public class HomeController : ControllerBase
    {
        private readonly ILogger<HomeController> _logger;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger"></param>
        public HomeController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }


        /// <summary>
        /// 查询案列1
        /// </summary>
        /// <param name="id">编号</param>
        /// <returns></returns>
        [HttpGet("Abc")] //url地址是:api/WeatherForecast/Get/Abc
        [ApiExplorerSettings(GroupName = "v1")]
        [Authorize]
        public IActionResult Get(int id)
        {
            return Ok(id);

            //返回值:IActionResult

            //return NotFound(); 404

            //return Redirect("/Home/Index");

            //var content = "Hello, World!";
            //return Content(content, "text/plain");

            //var data = new { Name = "John", Age = 30 };
            //return Json(data);

            //var filePath = "/path/to/file.pdf";
            //return File(filePath, "application/pdf", "filename.pdf");

            //byte[] videoBytes = System.IO.File.ReadAllBytes(containerPath);
            //return File(videoBytes, "video/mp4");
        }

        /// <summary>
        /// 查询案列2:路由的伪静态
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet("Abc/{name}")] //url地址是:api/WeatherForecast/Get/Abc/lily   :lily是name值, 同时name值是必填的,{name}必须要与action的参数名称一致。这就是路由的伪静态形式
        [ApiExplorerSettings(GroupName = nameof(ApiVersion.v1))]
        [Authorize]
        public IActionResult Get(string name)
        {
            return Ok(name);
        }


        /// <summary>
        /// 客户端登陆
        /// </summary>
        /// <param name="clientid">客户端名称</param>
        /// <param name="password">客户端密码</param>
        /// <returns>返回jwtToken</returns>
        [HttpGet]
        [ApiExplorerSettings(GroupName = nameof(ApiVersion.v2))]
        [Route("api/login")]
        public IActionResult Login(string clientid, string password)
        {
            //这里肯定是需要去连接数据库做数据校验
            if (clientid == "admin" && password == "123456")//应该数据库
            {
                string token = GetJwtToken(clientid);
                return Ok(new { token });
            }
            else
            {
                return Ok("");
            }
        }

        /// <summary>
        /// 获取Token
        /// </summary>
        /// <param name="UserName"></param>
        /// <returns></returns>
        [NonAction]
        public string GetJwtToken(string UserName)
        {
            var issuer = "Issuer";
            var audience = "Audience";

            var securityKey = "SIGfMA0FCSqGSIb3DFEBAQUAA4GNADCBiQKBgQDI2a2EJ7d872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI593nNDAPfnJsas96mSA9Q/mD8RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB";

            Claim[] claims = new[]
            {
               new Claim(ClaimTypes.Name, UserName)
            };
            SymmetricSecurityKey key = new(Encoding.UTF8.GetBytes(securityKey));
            SigningCredentials creds = new(key, SecurityAlgorithms.HmacSha256);

            var token = new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(1),//5分钟有效期
                signingCredentials: creds);
            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        /// <summary>
        /// 文件上传
        /// </summary>
        /// <param name="from"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult UploadFile(IFormCollection from)
        {
            return new JsonResult(new
            {
                Success = true,
                Message = "上传成功",
                FileName = from.Files.FirstOrDefault()?.FileName

            }) ;     
        }


        /// <summary>
        /// 标记了[NonAction]特性,则不被视为控制器的操作方法
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpPost(Name = "{id}")]
        [NonAction]
        public string PostTest(int id)
        {
            return id.ToString();
        }
    }
}

6、项目配置生成XML文件

7、效果图

7、注意点:

如果只是单纯只返回token的时候,记得在控制器右上角的Authorize里  先写Bearer+空格+你的token 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1241976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Axios 拦截器 请求拦截器 响应拦截器

请求拦截器 相当于一个关卡&#xff0c;如果满足条件就放行请求&#xff0c;不满足就拦截 响应拦截器 在处理结果之前&#xff0c;先对结果进行预处理&#xff0c;比如&#xff1a;对数据进行一下格式化的处理 全局请求拦截器 axios.interceptors.request.use(config > { /…

电脑开机显示器没反应?5个方法轻松解决!

“各位朋友们&#xff0c;我想问问&#xff0c;电脑开机显示器没反应是为啥呢&#xff1f;有什么方法可以解决这个问题吗&#xff1f;感谢感谢&#xff01;” 在使用电脑时&#xff0c;用户可能会遇到各种各样的情况。电脑开机显示器没反应也是一个比较常见的电脑问题。遇到这种…

Springboot+vue的新冠病毒密接者跟踪系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的新冠病毒密接者跟踪系统(有报告)。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的新冠病毒密接者跟踪系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;v…

JSP EL表达式获取list/Map集合与java Bean对象

上文 JSP EL表达式基本使用 中 我们对EL表达式做了一个基本的了解 也做了基础的字符串数据使用 那么 我们可以来看一下我们的集合 首先 list 这个比较简单 我们直接这样写代码 <% page import"java.util.ArrayList" %> <% page import"java.util.Lis…

两种常见EMC整改流程!|深圳比创达电子EMC

如何定位EMC整改计划可以分为两点&#xff1a; 1、根据以往的整改经验来进行判断&#xff1b; 2、比较测试&#xff0c;测试结束后根据测试仪器提供的数据进行问题分析。 下面介绍两种常见的EMC整改流程。 1、RE超标整改流程 首先要测量超标(临界)点&#xff0c;作为参考值…

注册并实名认证华为开发者账号

首先 我们访问 https://www.harmonyos.com/ 访问鸿蒙官方网站 右上角 我们点击 登录 然后 我们选择注册 然后 注册方式 有邮箱和手机号的注册 这边 看大家需要 如果像我不怎么登邮箱这种 建议还是选择手机号注册 这里 居住地区 应该就是默认中国吧 然后 手机号 验证码 密码…

入选《数据结构与算法领域内容帮榜》第44名

入选《数据结构与算法领域内容帮榜》第44名

Spring-jdbcTemplate-配置数据库连接池

1、jdbc.properties jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql:///studb jdbc.userroot jdbc.pwd123456 2、beans.xml <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans&…

安卓毕业设计基于安卓android微信小程序的家校通系统

运行环境 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序运行软件&#xff1a;微信开发者 项目介绍 基于微信小程序的家校通系统的设计基…

Nginx 413 Request Entity Too Large

当出现上图时候 更改nginx config 文件 在http{}或者server{}或者location{}中增加client_max_body_size 100m; 然后重启nginx 服务就好了

【深度学习】六大聚类算法快速了解

在机器学习中&#xff0c;无监督学习一直是我们追求的方向&#xff0c;而其中的聚类算法更是发现隐藏数据结构与知识的有效手段。目前如谷歌新闻等很多应用都将聚类算法作为主要的实现手段&#xff0c;它们能利用大量的未标注数据构建强大的主题聚类。本文从最基础的 K 均值聚类…

JAVA小游戏“飞翔的小鸟”

第一步是创建项目 项目名自拟 第二步创建个包名 来规范class 再创建一个包 来存储照片 如下&#xff1a; 代码如下&#xff1a; package game; import java.awt.*; import javax.swing.*; import javax.imageio.ImageIO;public class Bird {Image image;int x,y;int width…

STM32 CAN通信自定义数据包多帧连发乱序问题

场景&#xff1a; can标准帧中每一帧只能传输8字节&#xff0c;而应用中传输一包的内容往往超过8字节&#xff0c;因此需要把一个包拆成多个帧发送&#xff0c;接收端才把收到的多帧重新组装成一个完整的包 问题描述 在一问一答的两块板间通信&#xff0c;多帧连发是能够按照…

优思学院|2024年质量管理的大趋势

2023年我们已经顺利度过了整年的大部分时间&#xff0c;2024年质量管理的趋势和问题在全球范围内都已经引起了关注&#xff0c;或者仍然是企业导航的首要任务。 1. 通货膨胀与质量管理 2023年&#xff0c;全球范围内通货膨胀和严峻的经济状况成为企业最关心的问题之一。尽管物…

electron27-react-mateos:基于electron+react18仿matePad桌面系统

基于Electron27React18ArcoDesign搭建桌面版OS管理系统。 electron-react-mateos 基于最新前端跨端技术栈electron27.xreact18arco-designzustand4sortablejs构建的一款仿制matePad界面多层级路由管理OS系统。 ElectronReactOS支持桌面多路由配置&#xff0c;新开窗口弹窗开启路…

单片机调试技巧--修改bin文件实现断点

fromelf --text -a -c --outputall.dis F103_Moduel\F103_Moduel.axffromelf --bin --outputtest.bin F103_Moduel\F103_Moduel.axf 在启动文件中&#xff0c;修改UsageFault_Handler UsageFault_Handler\PROC; get current contextTST lr, #0x04 ; if(!EXC_RETURN[2])ITE…

学习量化交易如何入门?

Python 量化入门很简单&#xff0c;只需 3 步就能快速上手! 题主在程序方向没有相关经验&#xff0c;今天就从量化行业的通用语言-Python 着手&#xff0c;教大家如何快速入门。 一、准备工作 在开始 Python 编程之前&#xff0c;首先需要确保你的计算机上安装了合适的 Pytho…

【每日一题】1410. HTML实体解析器-2023.11.23

题目&#xff1a; 1410. HTML 实体解析器 「HTML 实体解析器」 是一种特殊的解析器&#xff0c;它将 HTML 代码作为输入&#xff0c;并用字符本身替换掉所有这些特殊的字符实体。 HTML 里这些特殊字符和它们对应的字符实体包括&#xff1a; 双引号&#xff1a;字符实体为 &…

【Docker】从零开始:8.Docker命令:Commit提交命令

【Docker】从零开始&#xff1a;8.Docker命令:Commit命令 基本概念镜像镜像分层什么是镜像分层为什么 Docker 镜像要采用这种分层结构 本章要点commit 命令命令格式docker commit 操作参数实例演示1.下载一个新的ubuntu镜像2.运行容器3.查看并安装vim4.退出容器5提交自己的镜像…

23. 深度学习 - 多维向量自动求导

Hi, 你好。我是茶桁。 前面几节课中&#xff0c;我们从最初的理解神经网络&#xff0c;到讲解函数&#xff0c;多层神经网络&#xff0c;拓朴排序以及自动求导。 可以说&#xff0c;最难的部分已经过去了&#xff0c;这节课到了我们来收尾的阶段&#xff0c;没错&#xff0c;生…