- namespace WebApp.Enums
- {
- ///
- /// api版本枚举
- ///
- public enum ApiVersion
- {
- ///
- /// v1版本
- ///
- v1 = 1,
- ///
- /// v2版本
- ///
- v2 = 2,
- }
- }
- 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
- {
- ///
- /// SwaggerDoc配置
- /// 用法:在Program.cs文件中进行注册:builder.AddSwaggerGenExt();
- ///
- public static class SwaggerExtension
- {
- ///
- /// 扩展方法:Swagger文档
- ///
- ///
- 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
(); - #endregion
- });
- #endregion
- }
-
- ///
- /// 扩展方法:配置SwaggerUI
- /// 用法:在Program.cs文件中进行注册:app.UseSwaggerUIExt();
- ///
- ///
- public static void UseSwaggerUIExt(this WebApplication app)
- {
- //SwaggerBasicAuthMiddleware:是我自己扩展的一个中间件:目的是需要登陆才能到达Swagger的Index页面中,否则无法进入:可以根据需要去掉这个
- //需要安装:Swashbuckle.AspNetCore包
- //app.UseMiddleware
(); -
- 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 扩展功能
- ///
- /// 文件上传的扩展:实现在Swagger中上传文件的功能
- ///
- public class FileUploadFilter : IOperationFilter
- {
- ///
- /// 文件上传筛选:只有上传文件的方法才添加此功能
- ///
- ///
- ///
- 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"
- }
- }
- }
- }
- }
- }
- }
- };
- }
- }
- }
-
- ///
- /// 如何在ASP.Net Core的生产环境中保护swagger ui,也就是index.html页面。其实swagger是自带禁用的功能的,只需要设置开关即可。
- /// 但是有一些场景,是需要把这些接口进行开放或者导出成文档供第三方进行调用,这个时候却又不想让所有人访问。
- /// 这里介绍一种权限控制访问的方式,用来指定用户使用;
- ///
- public class SwaggerBasicAuthMiddleware
- {
- private readonly RequestDelegate next;
- ///
- /// 增加对swagger ui的验证
- ///
- ///
- public SwaggerBasicAuthMiddleware(RequestDelegate next)
- {
- this.next = next;
- }
- ///
- /// 登陆功能实现
- ///
- ///
- ///
- 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
- }
- {
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning"
- }
- },
- "AllowedHosts": "*",
- "Swagger": {
- "environmentVariables": "development" //:development :testing :production
- }
- }
- 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();
在接口控制器,或者方法上添加版本(组)标识:[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
- {
- ///
- /// 测试接口
- ///
- [ApiController]//[ApiController]能够推断参数的绑定源,就不需要[FromBody][FromForm][FromHeader][FromQuery][FromRoute]....来主动指定接收参数的形式
- [Route("api/[controller]/[action]")]
-
- public class HomeController : ControllerBase
- {
- private readonly ILogger
_logger; - ///
- /// 构造函数
- ///
- ///
- public HomeController(ILogger
logger ) - {
- _logger = logger;
- }
-
-
- ///
- /// 查询案列1
- ///
- /// 编号
- ///
- [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");
- }
-
- ///
- /// 查询案列2:路由的伪静态
- ///
- ///
- ///
- [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);
- }
-
-
- ///
- /// 客户端登陆
- ///
- /// 客户端名称
- /// 客户端密码
- ///
返回jwtToken - [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("");
- }
- }
-
- ///
- /// 获取Token
- ///
- ///
- ///
- [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);
- }
-
- ///
- /// 文件上传
- ///
- ///
- ///
- [HttpPost]
- public JsonResult UploadFile(IFormCollection from)
- {
- return new JsonResult(new
- {
- Success = true,
- Message = "上传成功",
- FileName = from.Files.FirstOrDefault()?.FileName
-
- }) ;
- }
-
-
- ///
- /// 标记了[NonAction]特性,则不被视为控制器的操作方法
- ///
- ///
- ///
- [HttpPost(Name = "{id}")]
- [NonAction]
- public string PostTest(int id)
- {
- return id.ToString();
- }
- }
- }




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