• 【笔记】ASP.NET Core 2.2 Web API —— 学习笔记


    当年刚接触 ASP.NET Core 2.2 时,留下的学习笔记。现在把它挪到 CSDN,也是对过去学习 ASP.NET Core 痕迹进行记录。

    VS 2019 + ASP.NET Core 2.2 + sqlSugarCore (ORM)

    1. 仓储模式 + 服务 + 抽象接口

    1.1 新建asp.net core 2.2 WebApi项目

    nmmking.Core.Api
    nmmking.Core.Common
    nmmking.Core.IRepository
    nmmking.Core.IServices
    nmmking.Core.Model
    nmmking.Core.Repository
    nmmking.Core.Services
    nmmking.Core.Test

    2.nmmking.Core.Model 使用 Sqlsuger Code first

    2.1用 nuget 安装 sqlSugarCore ,新建 model 类

    1. namespace nmmking.Core.Model.Models
    2. {
    3. public class User
    4. {
    5. [SugarColumn(IsNullable =false,IsPrimaryKey =true,IsIdentity =true)]
    6. public int Id { get; set; }
    7. [SugarColumn(Length =50)]
    8. public string Name { get; set; }
    9. [SugarColumn(Length =50,IsNullable =true)]
    10. public string Password { get; set; }
    11. }
    12. }

    2.2 新建IDbContext接口

    1. namespace nmmking.Core.Model
    2. {
    3. public interface IDbContext
    4. {
    5. ///
    6. /// 操作数据库对象
    7. ///
    8. SqlSugarClient db { get; }
    9. ///
    10. /// 创建数据表
    11. ///
    12. /// 是否备份
    13. /// string类型映射的长度
    14. /// 要创建的数据表
    15. void CreateTable(bool Backup = false, int StringDefaultLength = 50, params Type[] types);
    16. ///
    17. /// 创建表
    18. ///
    19. /// 是否备份
    20. /// string类型映射的长度
    21. //public void CreateAllTable(bool Backup = false, int StringDefaultLength = 50);
    22. }
    23. }

    2.3 新建MyContext类

    1. public class MyContext: IDbContext
    2. {
    3. public SqlSugarClient db
    4. {
    5. get
    6. {
    7. return new SqlSugarClient(new ConnectionConfig()
    8. {
    9. ConnectionString = "server=.;database=nmmkingCoreDb;uid=sa;pwd=123456;",
    10. DbType = DbType.SqlServer,//数据库类型
    11. IsAutoCloseConnection = true,//自动释放数据务,如果存在事务,在事务结束后释放
    12. InitKeyType = InitKeyType.Attribute,//从实体特性中读取主键自增列信息
    13. });
    14. }
    15. }
    16. //public static SqlSugarClient GetInstance()
    17. //{
    18. // db = new SqlSugarClient(new ConnectionConfig()
    19. // {
    20. // ConnectionString = "server=.;database=StudentDb;uid=sa;pwd=123456;",
    21. // DbType = DbType.SqlServer,//设置数据库类型
    22. // IsAutoCloseConnection = true,//自动释放数据库,如果存在事务,在事务结束之后释放。
    23. // InitKeyType = InitKeyType.Attribute//从实体特性中读取主键自增列信息
    24. // });
    25. // //db.Aop.OnLogExecuting = (sql, pars) =>
    26. // //{
    27. // // Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject
    28. // // (pars.ToDictionary(it => it.ParameterName, it => it.Value)));
    29. // // Console.WriteLine();
    30. // //};
    31. // return db;
    32. //}
    33. public void CreateTable(bool Backup = false, int StringDefaultLength = 50, params Type[] types)
    34. {
    35. //设置varchar的默认长度
    36. db.CodeFirst.SetStringDefaultLength(StringDefaultLength);
    37. db.DbMaintenance.CreateDatabase();
    38. //创建表
    39. if (Backup)
    40. {
    41. db.CodeFirst.BackupTable().InitTables(types);
    42. }
    43. else
    44. {
    45. db.CodeFirst.InitTables(types);
    46. }
    47. }
    48. public SimpleClient<User> userDb { get { return new SimpleClient(db); } }
    49. //public SqlSugarClient db => throw new NotImplementedException();
    50. }

    2.4 使用

    1. namespace nmmking.Core.Test
    2. {
    3. class Program
    4. {
    5. static void Main(string[] args)
    6. {
    7. MyContext context = new MyContext();
    8. context.CreateTable(false, 50, typeof(User));
    9. //AppDbContext context = new AppDbContext();
    10. //context.CreateTable(false, 50, typeof(Students), typeof(Schools));
    11. Console.WriteLine("Hello World!");
    12. }
    13. }
    14. }

    3. 仓储层

    3.1 IBaseRepository

    1. namespace nmmking.Core.IRepository
    2. {
    3. public interface IBaseRepository<T> where T:class
    4. {
    5. Task QueryById(object id, bool IsUseCache = false); //根据id查询
    6. Task> GetEntities(Expressionbool>> whereLambda); //根据查询条件查询
    7. Task<bool> Add(T entity);
    8. Task<bool> DeleteById(object Id);
    9. Task<bool> Update(T entity);
    10. }
    11. }

    3.2 BaseRepository

    1. namespace nmmking.Core.Repository
    2. {
    3. public class BaseRepository<T> : IBaseRepository<T> where T : class, new()
    4. {
    5. private readonly IDbContext _dbContext;
    6. public BaseRepository(IDbContext dbContext)
    7. {
    8. this._dbContext = dbContext;
    9. }
    10. // 增加单条数据
    11. public async Task<bool> Add(T entity)
    12. {
    13. return await _dbContext.db.Insertable(entity).ExecuteCommandAsync() > 0;
    14. }
    15. // 根据id删除单条数据
    16. public async Task<bool> DeleteById(object id)
    17. {
    18. return await _dbContext.db.Deleteable(id).ExecuteCommandHasChangeAsync();
    19. }
    20. // 查询数据列表
    21. public async Task<List<T>> GetEntities(Expressionbool>> whereExpression)
    22. {
    23. return await _dbContext.db.Queryable().WhereIF(whereExpression != null, whereExpression).ToListAsync();
    24. }
    25. // 根据Id查询一条数据
    26. public async Task QueryById(object id, bool IsUseCache =false)
    27. {
    28. return await _dbContext.db.Queryable().WithCacheIF(IsUseCache).In(id).SingleAsync();
    29. }
    30. // 更新实体数据
    31. public Task<bool> Update(T entity)
    32. {
    33. var i = await Task.Run(() => dbcontext.Updateable(model).ExecuteCommand());
    34. return i > 0;
    35. }
    36. }
    37. }

    4.读取 appsettings.json 文件

    4.1 nuget 安装 Microsoft.Extensions.Configuration.Binder,Microsoft.Extensions.Configuration.Json。

    4.2 新建 Appsettings 类

    1. namespace nmmking.Core.Common.Helper
    2. {
    3. ///
    4. /// appsettings.json操作类
    5. ///
    6. public class Appsettings
    7. {
    8. static IConfiguration Configuration { get; set; }
    9. static string contentPath { get; set; }
    10. static Appsettings()
    11. {
    12. //如果你把配置文件 是 根据环境变量来分开了,可以这样写
    13. //Path = $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json";
    14. Configuration = new ConfigurationBuilder()
    15. .Add(new JsonConfigurationSource { Path = "appsettings.json", ReloadOnChange = true })//请注意要把当前appsetting.json 文件->右键->属性->复制到输出目录->始终复制
    16. .Build();
    17. }
    18. ///
    19. /// 封装要操作的字符
    20. ///
    21. /// 节点配置
    22. ///
    23. public static string app(params string[] sections)
    24. {
    25. try
    26. {
    27. if (sections.Any())
    28. {
    29. return Configuration[string.Join(":", sections)];
    30. }
    31. }
    32. catch (Exception) { }
    33. return "";
    34. }
    35. ///
    36. /// 递归获取配置信息数组
    37. ///
    38. ///
    39. ///
    40. ///
    41. public static List<T> app<T>(params string[] sections)
    42. {
    43. List list = new List();
    44. // 引用 Microsoft.Extensions.Configuration.Binder 包
    45. Configuration.Bind(string.Join(":", sections), list);
    46. return list;
    47. }
    48. }
    49. }

    4.3 使用

    1. string iss = Appsettings.app(new string[] { "Audience", "Issuer" });
    2. string aud = Appsettings.app(new string[] { "Audience", "Audience" });

    5.使用Cors跨域

    5.1 允许所有域名访问接口
    在Startup.cs文件的ConfigureServices方法添加:

    1. public void ConfigureServices(IServiceCollection services)
    2. {
    3. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    4. services.AddCors(c =>
    5. {
    6. c.AddPolicy("LimitRequests", policy =>
    7. {
    8. policy
    9. .AllowAnyOrigin()
    10. .AllowAnyHeader()
    11. .AllowAnyMethod();
    12. });
    13. });
    14. services.AddTransient(typeof(IBaseRepository<>), typeof(BaseRepository<>));
    15. services.AddTransient();
    16. services.AddTransient();
    17. }
    在Startup.cs文件的 Configure 方法 添加:
    1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    2. {
    3. if (env.IsDevelopment())
    4. {
    5. app.UseDeveloperExceptionPage();
    6. }
    7. app.UseCors("LimitRequests");
    8. app.UseMvc();
    9. }

    运行:http://localhost:61576/api/values

    测试一下,打开百度地址:https://www.baidu.com/,按F12,在Console输入:

    1. $.get("http://localhost:61576/api/values",function(data,status){
    2. console.log(data);
    3. });

    5.2 限制域的访问

    1. services.AddCors(c =>
    2. {
    3. c.AddPolicy("LimitRequests", policy =>
    4. {
    5. policy
    6. //.AllowAnyOrigin()
    7. .WithOrigins(new string[]{ "http://localhost:8881" })
    8. //.WithOrigins(Appsettings.app(new string[] { "Startup", "Cors", "IPs" }).Split(','))
    9. .AllowAnyHeader()
    10. .AllowAnyMethod();
    11. });
    12. });
    1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    2. {
    3. if (env.IsDevelopment())
    4. {
    5. app.UseDeveloperExceptionPage();
    6. }
    7. app.UseCors("LimitRequests");
    8. app.UseMvc();
    9. }

    5.3 跨域访问

    下载 nginx ,http://nginx.org/en/download.html,配置 nginx。

    新建 index.html

    1. If you click on me, I will disappear.

    出现跨域问题

    修改访问地址

    1. services.AddCors(c =>
    2. {
    3. c.AddPolicy("LimitRequests", policy =>
    4. {
    5. policy
    6. //.AllowAnyOrigin()
    7. .WithOrigins(new string[]{ "http://localhost:8889" })
    8. //.WithOrigins(Appsettings.app(new string[] { "Startup", "Cors", "IPs" }).Split(','))
    9. .AllowAnyHeader()
    10. .AllowAnyMethod();
    11. });
    12. });
    刷新一下index.html,弹出界面,访问成功

    6.使用Log4Net日志处理

    安装

    注册服务

    1. public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    2. WebHost.CreateDefaultBuilder(args)
    3. .UseStartup()
    4. .ConfigureLogging((hostingContext, builder) =>
    5. {
    6. //过滤掉系统默认的一些日志
    7. builder.AddFilter("System", LogLevel.Error);
    8. builder.AddFilter("Microsoft", LogLevel.Error);
    9. //builder.AddFilter();
    10. //可配置文件
    11. var path = Path.Combine(Directory.GetCurrentDirectory(),
    12. "Log4net.config");
    13. builder.AddLog4Net(path);
    14. });

    配置文件,下面文件配置了error和info两种级别的日志

    1. "1.0" encoding="utf-8"?>
    2. <log4net>
    3. <appender name="ErrorLog" type="log4net.Appender.RollingFileAppender">
    4. <file value="Log/"/>
    5. <appendToFile value="true" />
    6. <rollingStyle value="Date" />
    7. <datePattern value=""GlobalExceptionLogs_"yyyyMMdd".log"" />
    8. <StaticLogFileName value="false"/>
    9. <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    10. <layout type="log4net.Layout.PatternLayout">
    11. <conversionPattern value="%date| %-5level %newline%message%newline--------------------------------%newline" />
    12. layout>
    13. <filter type="log4net.Filter.LevelRangeFilter">
    14. <levelMin value="ERROR" />
    15. <levelMax value="FATAL" />
    16. filter>
    17. appender>
    18. <appender name="InfoLog" type="log4net.Appender.RollingFileAppender">
    19. <file value="Log/"/>
    20. <appendToFile value="true" />
    21. <rollingStyle value="Date" />
    22. <StaticLogFileName value="false"/>
    23. <datePattern value=""GlobalInfoLogs_"yyyyMMdd".log"" />
    24. <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
    25. <layout type="log4net.Layout.PatternLayout">
    26. <conversionPattern value="%date| %-5level %newline%message%newline--------------------------------%newline" />
    27. layout>
    28. <filter type="log4net.Filter.LevelRangeFilter">
    29. <levelMin value="DEBUG" />
    30. <levelMax value="WARN" />
    31. filter>
    32. appender>
    33. <root>
    34. <level value="ALL" />
    35. <appender-ref ref="ErrorLog" />
    36. <appender-ref ref="InfoLog" />
    37. root>
    38. log4net>

    使用

    1. [Produces("application/json")]
    2. [Route("api/Values")]
    3. [AllowAnonymous]
    4. public class ValuesController : ControllerBase
    5. {
    6. private readonly IUserService _userService;
    7. private readonly ILogger _logger;
    8. public ValuesController(IUserService userService,ILogger logger)
    9. {
    10. this._userService = userService;
    11. this._logger = logger;
    12. }
    13. // GET api/values
    14. [HttpGet]
    15. public ActionResultstring>> Get()
    16. {
    17. _logger.LogError("this is an error");
    18. return new string[] { "value1", "value2" };
    19. }
    20. }

    7.JWT基于策略的授权

    安装 Microsoft.IdentityModel.Tokens 和 System.IdentityModel.Tokens.Jwt

    新建Jwt操作类

    1. public class JwtHelper
    2. {
    3. ///
    4. /// 颁发JWT字符串
    5. ///
    6. ///
    7. ///
    8. public static string IssueJWT(TokenModelJWT tokenModel)
    9. {
    10. var dateTime = DateTime.UtcNow;
    11. string iss = Appsettings.app(new string[] { "Audience", "Issuer" });
    12. string aud = Appsettings.app(new string[] { "Audience", "Audience" });
    13. string secret = Appsettings.app(new string[] { "Audience", "Secret" });
    14. //var claims = new Claim[] //old
    15. var claims = new List
    16. {
    17. //下边为Claim的默认配置
    18. new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ToString()),
    19. new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
    20. new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,
    21. //这个就是过期时间,目前是过期100秒,可自定义,注意JWT有自己的缓冲过期时间
    22. new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(100)).ToUnixTimeSeconds()}"),
    23. new Claim(JwtRegisteredClaimNames.Iss,iss),
    24. new Claim(JwtRegisteredClaimNames.Aud,aud),
    25. //new Claim(ClaimTypes.Role,tokenModel.Role),//为了解决一个用户多个角色(比如:Admin,System),用下边的方法
    26. };
    27. // 可以将一个用户的多个角色全部赋予;
    28. // 作者:DX 提供技术支持;
    29. claims.AddRange(tokenModel.Role.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
    30. //秘钥 (SymmetricSecurityKey 对安全性的要求,密钥的长度太短会报出异常)
    31. var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
    32. var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    33. var jwt = new JwtSecurityToken(
    34. issuer: iss,
    35. claims: claims,
    36. signingCredentials: creds);
    37. var jwtHandler = new JwtSecurityTokenHandler();
    38. var encodedJwt = jwtHandler.WriteToken(jwt);
    39. return encodedJwt;
    40. }
    41. ///
    42. /// 解析
    43. ///
    44. ///
    45. ///
    46. public static TokenModelJWT SerializeJWT(string jwtStr)
    47. {
    48. var jwtHandler = new JwtSecurityTokenHandler();
    49. JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
    50. object role = new object(); ;
    51. try
    52. {
    53. jwtToken.Payload.TryGetValue(ClaimTypes.Role, out role);
    54. }
    55. catch (Exception e)
    56. {
    57. Console.WriteLine(e);
    58. throw;
    59. }
    60. var tm = new TokenModelJWT
    61. {
    62. Uid = Convert.ToInt32(jwtToken.Id),
    63. Role = role != null ? role.ToString() : "",
    64. };
    65. return tm;
    66. }
    67. }
    68. ///
    69. /// 令牌
    70. ///
    71. public class TokenModelJWT
    72. {
    73. ///
    74. /// Id
    75. ///
    76. public long Uid { get; set; }
    77. ///
    78. /// 角色
    79. ///
    80. public string Role { get; set; }
    81. ///
    82. /// 职能
    83. ///
    84. public string Work { get; set; }
    85. }

    配置文件appsettings.json

    1. {
    2. "Logging": {
    3. "LogLevel": {
    4. "Default": "Warning"
    5. }
    6. },
    7. "Audience": {
    8. "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //至少要16位
    9. "Issuer": "nmmking.Core",
    10. "Audience": "yika"
    11. },
    12. "Startup": {
    13. "Cors": {
    14. "IPs": "http://127.0.0.1:2364,http://localhost:2364,http://localhost:8080,http://localhost:8021,http://localhost:1818"
    15. }
    16. },
    17. "AllowedHosts": "*"
    18. }
    在Startup.cs文件注册和配置到管道

    1. #region 基于策略的授权(简单版)
    2. // 1【授权】、这个和上边的异曲同工,好处就是不用在controller中,写多个 roles 。
    3. // 然后这么写 [Authorize(Policy = "Admin")]
    4. services.AddAuthorization(options =>
    5. {
    6. options.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
    7. options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
    8. options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
    9. });
    10. #endregion
    11. #region 【认证】
    12. //读取配置文件
    13. var audienceConfig = Configuration.GetSection("Audience");
    14. var symmetricKeyAsBase64 = audienceConfig["Secret"];
    15. var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
    16. var signingKey = new SymmetricSecurityKey(keyByteArray);
    17. //2.1【认证】
    18. services.AddAuthentication(x =>
    19. {
    20. x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    21. x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    22. })
    23. .AddJwtBearer(o =>
    24. {
    25. o.TokenValidationParameters = new TokenValidationParameters
    26. {
    27. ValidateIssuerSigningKey = true,
    28. IssuerSigningKey = signingKey,
    29. ValidateIssuer = true,
    30. ValidIssuer = audienceConfig["Issuer"],//发行人
    31. ValidateAudience = true,
    32. ValidAudience = audienceConfig["Audience"],//订阅人
    33. ValidateLifetime = true,
    34. ClockSkew = TimeSpan.Zero,
    35. RequireExpirationTime = true,
    36. };
    37. });
    38. #endregion
    app.UseAuthentication();

    接口 GetJWTToken

    1. [Produces("application/json")]
    2. [Route("api/[controller]/[action]")]
    3. public class ValuesController : ControllerBase
    4. {
    5. }
    1. ///
    2. /// 登录接口:随便输入字符,获取token,然后添加 Authoritarian
    3. ///
    4. ///
    5. ///
    6. ///
    7. [HttpGet]
    8. public async Task<object> GetJWTToken(string name, string pass)
    9. {
    10. string jwtStr = string.Empty;
    11. bool suc = false;
    12. //这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作
    13. //这里直接写死了
    14. if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
    15. {
    16. return new JsonResult(new
    17. {
    18. Status = false,
    19. message = "用户名或密码不能为空"
    20. });
    21. }
    22. TokenModelJWT tokenModel = new TokenModelJWT();
    23. tokenModel.Uid = 1;
    24. tokenModel.Role = name;
    25. jwtStr = JwtHelper.IssueJWT(tokenModel);
    26. suc = true;
    27. return Ok(new
    28. {
    29. success = suc,
    30. token = jwtStr
    31. });
    32. }

    测试1:测试 Get 

    1. ///
    2. /// 这个也需要认证,只不过登录即可,不一定是Admin
    3. ///
    4. ///
    5. ///
    6. [HttpGet]
    7. [Authorize]
    8. public ActionResult<string> Get()
    9. {
    10. return "value";
    11. }
    token 逾期,访问 Get 接口, 结果提示没有权限(未授权),如下图所示:

    用户重新登录获取 token (这里没有指定的用户,只要登录就行),如下图所示:

     ​​​​​​再次访问 Get 接口,访问成功如下图所示:

    接口2:

    1. ///
    2. /// 这个需要认证,角色必须是Admin,其他的不需要
    3. ///
    4. ///
    5. [HttpGet]
    6. [Authorize(Policy = "SystemOrAdmin")]
    7. public ActionResultstring>> GetData()
    8. {
    9. _logger.LogError("this is an error");
    10. return new string[] { "value1", "value2" };
    11. }

    随意的用户登录获取 token,如下所示

     登录的用户不是 Admin,结果是拒绝访问

     如果是admin用户,请求参数和请求头如下:

    请求成功 

     

    8.Swagger和JWT设置

    nuget 安装 Microsoft.OpenApi ,Swashbuckle.AspNetCore,Swashbuckle.AspNetCore.Filters。

    在Startup.cs设置:

    1. private const string ApiName = "nmmking.Core.Api";
    2. private readonly string version = "V1";
    1. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    2. {
    3. if (env.IsDevelopment())
    4. {
    5. app.UseDeveloperExceptionPage();
    6. }
    7. app.UseCors("LimitRequests");
    8. //注册异常处理中间件
    9. app.UseMiddleware();
    10. #region Swagger
    11. app.UseSwagger();
    12. app.UseSwaggerUI(c =>
    13. {
    14. c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}");
    15. //c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("index.html");
    16. c.RoutePrefix = "";
    17. });
    18. #endregion
    19. // 开启权限
    20. app.UseAuthentication();
    21. app.UseMvc();
    22. }
    1. public IServiceProvider ConfigureServices(IServiceCollection services)
    2. {
    3. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    4. services.AddCors(c =>
    5. {
    6. c.AddPolicy("LimitRequests", policy =>
    7. {
    8. policy
    9. //.AllowAnyOrigin()
    10. .WithOrigins(new string[]{ "http://localhost:8881" })
    11. //.WithOrigins(Appsettings.app(new string[] { "Startup", "Cors", "IPs" }).Split(','))
    12. .AllowAnyHeader()
    13. .AllowAnyMethod();
    14. });
    15. });
    16. #region Swagger UI Service
    17. var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
    18. services.AddSwaggerGen(c =>
    19. {
    20. //遍历出全部的版本,做文档信息展示
    21. c.SwaggerDoc(version, new OpenApiInfo
    22. {
    23. Version = version,
    24. Title = $"{ApiName} 接口文档——{RuntimeInformation.FrameworkDescription}",
    25. Description = $"{ApiName} HTTP API " + version,
    26. Contact = new OpenApiContact { Name = ApiName, Email = "nmmking.Core@xxx.com", Url = new Uri("http地址") },
    27. License = new OpenApiLicense { Name = ApiName + " 官方文档", Url = new Uri("http地址") }
    28. });
    29. c.OrderActionsBy(o => o.RelativePath);
    30. //就是这里
    31. var xmlPath = Path.Combine(basePath, "nmmking.Core.Api.xml");//这个就是刚刚配置的xml文件名
    32. c.IncludeXmlComments(xmlPath, true);//默认的第二个参数是false,这个是controller的注释,记得修改
    33. var xmlPath2 = Path.Combine(basePath, "nmmking.Core.Model.xml");
    34. c.IncludeXmlComments(xmlPath2, true);
    35. #region Token绑定到ConfigureServices
    36. // 开启加权小锁
    37. c.OperationFilter();
    38. c.OperationFilter();
    39. // 在header中添加token,传递到后台
    40. c.OperationFilter();
    41. // Jwt Bearer 认证,必须是 oauth2
    42. c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    43. {
    44. Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
    45. Name = "Authorization",//jwt默认的参数名称
    46. In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
    47. Type = SecuritySchemeType.ApiKey
    48. });
    49. #endregion
    50. });
    51. #endregion
    52. #region 授权
    53. // 读取配置文件
    54. var audienceConfig = Configuration.GetSection("Audience");
    55. var symmetricKeyAsBase64 = audienceConfig["Secret"];
    56. var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
    57. var signingKey = new SymmetricSecurityKey(keyByteArray);
    58. var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); //签名
    59. // 角色与接口的权限要求参数
    60. var permissionRequirement = new PermissionRequirement(
    61. ClaimTypes.Role,//基于角色的授权
    62. audienceConfig["Issuer"],//发行人
    63. audienceConfig["Audience"],//听众
    64. signingCredentials,//签名凭据
    65. expiration: TimeSpan.FromSeconds(60 * 60)//接口的过期时间
    66. );
    67. // 授权
    68. services.AddAuthorization(options =>
    69. {
    70. // 权限变量配置
    71. options.AddPolicy("Permission",
    72. policy => policy.Requirements.Add(permissionRequirement));
    73. });
    74. // 令牌验证参数
    75. var tokenValidationParameters = new TokenValidationParameters
    76. {
    77. ValidateIssuerSigningKey = true,
    78. IssuerSigningKey = signingKey,
    79. ValidateIssuer = true,
    80. ValidIssuer = audienceConfig["Issuer"],//发行人
    81. ValidateAudience = true,
    82. ValidAudience = audienceConfig["Audience"],//订阅人
    83. ValidateLifetime = true,
    84. ClockSkew = TimeSpan.FromSeconds(30),
    85. RequireExpirationTime = true,
    86. };
    87. services.AddAuthentication("Bearer")
    88. .AddJwtBearer(o =>
    89. {
    90. o.TokenValidationParameters = tokenValidationParameters;
    91. o.Events = new JwtBearerEvents
    92. {
    93. OnAuthenticationFailed = context =>
    94. {
    95. // 如果过期,则把<是否过期>添加到,返回头信息中
    96. if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
    97. {
    98. context.Response.Headers.Add("Token-Expired", "true");
    99. }
    100. return Task.CompletedTask;
    101. }
    102. };
    103. });
    104. services.AddSingleton(permissionRequirement);
    105. #endregion
    106. return services.BuildDynamicProxyProvider();
    107. }

     

  • 相关阅读:
    Maven 使用过程中碰到的问题持续集成
    Z410 2023款无人机,专为零基础开发者打造的入门级开源无人机
    CF486D Valid Sets
    百度主动推送不能用了,百度自动推送代码送给大家
    29.STM32红外遥控器
    centost7下安装oracle11g 总结踩坑
    同步FIFO设计实现(8/7)
    【面试题- springcloud】- Ribbon 负载均衡
    【MindSpore】MindQuantum中如何处理遇到的一些问题
    ubuntu------anaconda和openvino安装
  • 原文地址:https://blog.csdn.net/nmmking/article/details/137844468