当年刚接触 ASP.NET Core 2.2 时,留下的学习笔记。现在把它挪到 CSDN,也是对过去学习 ASP.NET Core 痕迹进行记录。
VS 2019 + ASP.NET Core 2.2 + sqlSugarCore (ORM)
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.1用 nuget 安装 sqlSugarCore ,新建 model 类
- namespace nmmking.Core.Model.Models
- {
- public class User
- {
- [SugarColumn(IsNullable =false,IsPrimaryKey =true,IsIdentity =true)]
- public int Id { get; set; }
- [SugarColumn(Length =50)]
- public string Name { get; set; }
- [SugarColumn(Length =50,IsNullable =true)]
- public string Password { get; set; }
- }
- }
2.2 新建IDbContext接口
- namespace nmmking.Core.Model
- {
- public interface IDbContext
- {
- ///
- /// 操作数据库对象
- ///
- SqlSugarClient db { get; }
-
- ///
- /// 创建数据表
- ///
- /// 是否备份
- /// string类型映射的长度
- /// 要创建的数据表
- void CreateTable(bool Backup = false, int StringDefaultLength = 50, params Type[] types);
-
- ///
- /// 创建表
- ///
- /// 是否备份
- /// string类型映射的长度
- //public void CreateAllTable(bool Backup = false, int StringDefaultLength = 50);
- }
- }
2.3 新建MyContext类
- public class MyContext: IDbContext
- {
-
- public SqlSugarClient db
- {
- get
- {
- return new SqlSugarClient(new ConnectionConfig()
- {
- ConnectionString = "server=.;database=nmmkingCoreDb;uid=sa;pwd=123456;",
- DbType = DbType.SqlServer,//数据库类型
- IsAutoCloseConnection = true,//自动释放数据务,如果存在事务,在事务结束后释放
- InitKeyType = InitKeyType.Attribute,//从实体特性中读取主键自增列信息
- });
- }
- }
-
- //public static SqlSugarClient GetInstance()
- //{
- // db = new SqlSugarClient(new ConnectionConfig()
- // {
- // ConnectionString = "server=.;database=StudentDb;uid=sa;pwd=123456;",
- // DbType = DbType.SqlServer,//设置数据库类型
- // IsAutoCloseConnection = true,//自动释放数据库,如果存在事务,在事务结束之后释放。
- // InitKeyType = InitKeyType.Attribute//从实体特性中读取主键自增列信息
- // });
-
- // //db.Aop.OnLogExecuting = (sql, pars) =>
- // //{
- // // Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject
- // // (pars.ToDictionary(it => it.ParameterName, it => it.Value)));
- // // Console.WriteLine();
- // //};
-
- // return db;
- //}
-
- public void CreateTable(bool Backup = false, int StringDefaultLength = 50, params Type[] types)
- {
- //设置varchar的默认长度
- db.CodeFirst.SetStringDefaultLength(StringDefaultLength);
- db.DbMaintenance.CreateDatabase();
-
- //创建表
- if (Backup)
- {
- db.CodeFirst.BackupTable().InitTables(types);
- }
- else
- {
- db.CodeFirst.InitTables(types);
- }
- }
-
- public SimpleClient<User> userDb { get { return new SimpleClient
(db); } } -
- //public SqlSugarClient db => throw new NotImplementedException();
- }
2.4 使用
- namespace nmmking.Core.Test
- {
- class Program
- {
- static void Main(string[] args)
- {
- MyContext context = new MyContext();
- context.CreateTable(false, 50, typeof(User));
-
- //AppDbContext context = new AppDbContext();
- //context.CreateTable(false, 50, typeof(Students), typeof(Schools));
-
- Console.WriteLine("Hello World!");
- }
- }
- }

3.1 IBaseRepository
- namespace nmmking.Core.IRepository
- {
- public interface IBaseRepository<T> where T:class
- {
- Task
QueryById(object id, bool IsUseCache = false) ; //根据id查询 -
- Task
> GetEntities(Expressionbool>> whereLambda); //根据查询条件查询
-
- Task<bool> Add(T entity);
-
- Task<bool> DeleteById(object Id);
-
- Task<bool> Update(T entity);
- }
- }
3.2 BaseRepository
- namespace nmmking.Core.Repository
- {
- public class BaseRepository<T> : IBaseRepository<T> where T : class, new()
- {
- private readonly IDbContext _dbContext;
-
- public BaseRepository(IDbContext dbContext)
- {
- this._dbContext = dbContext;
- }
-
- // 增加单条数据
- public async Task<bool> Add(T entity)
- {
- return await _dbContext.db.Insertable
(entity).ExecuteCommandAsync() > 0; - }
-
- // 根据id删除单条数据
- public async Task<bool> DeleteById(object id)
- {
- return await _dbContext.db.Deleteable
(id).ExecuteCommandHasChangeAsync(); - }
-
- // 查询数据列表
- public async Task<List<T>> GetEntities(Expression
bool >> whereExpression) - {
- return await _dbContext.db.Queryable
().WhereIF(whereExpression != null, whereExpression).ToListAsync(); - }
-
- // 根据Id查询一条数据
- public async Task
QueryById(object id, bool IsUseCache =false) - {
- return await _dbContext.db.Queryable
().WithCacheIF(IsUseCache).In(id).SingleAsync(); - }
-
- // 更新实体数据
- public Task<bool> Update(T entity)
- {
- var i = await Task.Run(() => dbcontext.Updateable(model).ExecuteCommand());
- return i > 0;
- }
- }
- }
4.1 nuget 安装 Microsoft.Extensions.Configuration.Binder,Microsoft.Extensions.Configuration.Json。

4.2 新建 Appsettings 类
- namespace nmmking.Core.Common.Helper
- {
- ///
- /// appsettings.json操作类
- ///
- public class Appsettings
- {
- static IConfiguration Configuration { get; set; }
- static string contentPath { get; set; }
-
-
- static Appsettings()
- {
- //如果你把配置文件 是 根据环境变量来分开了,可以这样写
- //Path = $"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}.json";
-
- Configuration = new ConfigurationBuilder()
- .Add(new JsonConfigurationSource { Path = "appsettings.json", ReloadOnChange = true })//请注意要把当前appsetting.json 文件->右键->属性->复制到输出目录->始终复制
- .Build();
- }
-
- ///
- /// 封装要操作的字符
- ///
- /// 节点配置
- ///
- public static string app(params string[] sections)
- {
- try
- {
-
- if (sections.Any())
- {
- return Configuration[string.Join(":", sections)];
- }
- }
- catch (Exception) { }
-
- return "";
- }
-
- ///
- /// 递归获取配置信息数组
- ///
- ///
- ///
- ///
- public static List<T> app<T>(params string[] sections)
- {
- List
list = new List(); - // 引用 Microsoft.Extensions.Configuration.Binder 包
- Configuration.Bind(string.Join(":", sections), list);
- return list;
- }
- }
- }
4.3 使用
- string iss = Appsettings.app(new string[] { "Audience", "Issuer" });
- string aud = Appsettings.app(new string[] { "Audience", "Audience" });
5.1 允许所有域名访问接口
在Startup.cs文件的ConfigureServices方法添加:
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
-
- services.AddCors(c =>
- {
- c.AddPolicy("LimitRequests", policy =>
- {
- policy
- .AllowAnyOrigin()
- .AllowAnyHeader()
- .AllowAnyMethod();
- });
- });
-
- services.AddTransient(typeof(IBaseRepository<>), typeof(BaseRepository<>));
-
- services.AddTransient
(); -
- services.AddTransient
(); - }
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- app.UseCors("LimitRequests");
- app.UseMvc();
- }
运行:http://localhost:61576/api/values

测试一下,打开百度地址:https://www.baidu.com/,按F12,在Console输入:
- $.get("http://localhost:61576/api/values",function(data,status){
- console.log(data);
- });

5.2 限制域的访问
- services.AddCors(c =>
- {
- c.AddPolicy("LimitRequests", policy =>
- {
- policy
- //.AllowAnyOrigin()
- .WithOrigins(new string[]{ "http://localhost:8881" })
- //.WithOrigins(Appsettings.app(new string[] { "Startup", "Cors", "IPs" }).Split(','))
- .AllowAnyHeader()
- .AllowAnyMethod();
- });
- });
-
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- app.UseCors("LimitRequests");
- app.UseMvc();
- }
5.3 跨域访问
下载 nginx ,http://nginx.org/en/download.html,配置 nginx。

新建 index.html
-
If you click on me, I will disappear.
-
-
出现跨域问题

修改访问地址
- services.AddCors(c =>
- {
- c.AddPolicy("LimitRequests", policy =>
- {
- policy
- //.AllowAnyOrigin()
- .WithOrigins(new string[]{ "http://localhost:8889" })
- //.WithOrigins(Appsettings.app(new string[] { "Startup", "Cors", "IPs" }).Split(','))
- .AllowAnyHeader()
- .AllowAnyMethod();
- });
- });


注册服务
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup
() - .ConfigureLogging((hostingContext, builder) =>
- {
- //过滤掉系统默认的一些日志
- builder.AddFilter("System", LogLevel.Error);
- builder.AddFilter("Microsoft", LogLevel.Error);
- //builder.AddFilter();
-
- //可配置文件
- var path = Path.Combine(Directory.GetCurrentDirectory(),
- "Log4net.config");
- builder.AddLog4Net(path);
- });
配置文件,下面文件配置了error和info两种级别的日志
- "1.0" encoding="utf-8"?>
- <log4net>
-
-
-
- <appender name="ErrorLog" type="log4net.Appender.RollingFileAppender">
- <file value="Log/"/>
- <appendToFile value="true" />
- <rollingStyle value="Date" />
-
- <datePattern value=""GlobalExceptionLogs_"yyyyMMdd".log"" />
-
- <StaticLogFileName value="false"/>
-
- <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
-
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%date| %-5level %newline%message%newline--------------------------------%newline" />
- layout>
- <filter type="log4net.Filter.LevelRangeFilter">
- <levelMin value="ERROR" />
- <levelMax value="FATAL" />
- filter>
- appender>
-
-
-
- <appender name="InfoLog" type="log4net.Appender.RollingFileAppender">
-
- <file value="Log/"/>
- <appendToFile value="true" />
- <rollingStyle value="Date" />
-
- <StaticLogFileName value="false"/>
-
- <datePattern value=""GlobalInfoLogs_"yyyyMMdd".log"" />
-
- <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
-
- <layout type="log4net.Layout.PatternLayout">
- <conversionPattern value="%date| %-5level %newline%message%newline--------------------------------%newline" />
- layout>
- <filter type="log4net.Filter.LevelRangeFilter">
- <levelMin value="DEBUG" />
- <levelMax value="WARN" />
- filter>
- appender>
-
-
- <root>
-
-
-
- <level value="ALL" />
-
- <appender-ref ref="ErrorLog" />
- <appender-ref ref="InfoLog" />
- root>
- log4net>
使用
- [Produces("application/json")]
- [Route("api/Values")]
- [AllowAnonymous]
- public class ValuesController : ControllerBase
- {
- private readonly IUserService _userService;
- private readonly ILogger
_logger; -
- public ValuesController(IUserService userService,ILogger
logger ) - {
- this._userService = userService;
- this._logger = logger;
- }
-
- // GET api/values
- [HttpGet]
- public ActionResult
string>> Get() - {
- _logger.LogError("this is an error");
- return new string[] { "value1", "value2" };
- }
- }

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

新建Jwt操作类
- public class JwtHelper
- {
-
- ///
- /// 颁发JWT字符串
- ///
- ///
- ///
- public static string IssueJWT(TokenModelJWT tokenModel)
- {
- var dateTime = DateTime.UtcNow;
-
- string iss = Appsettings.app(new string[] { "Audience", "Issuer" });
- string aud = Appsettings.app(new string[] { "Audience", "Audience" });
- string secret = Appsettings.app(new string[] { "Audience", "Secret" });
-
- //var claims = new Claim[] //old
- var claims = new List
- {
- //下边为Claim的默认配置
- new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ToString()),
- new Claim(JwtRegisteredClaimNames.Iat, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"),
- new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,
- //这个就是过期时间,目前是过期100秒,可自定义,注意JWT有自己的缓冲过期时间
- new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(DateTime.Now.AddSeconds(100)).ToUnixTimeSeconds()}"),
- new Claim(JwtRegisteredClaimNames.Iss,iss),
- new Claim(JwtRegisteredClaimNames.Aud,aud),
-
- //new Claim(ClaimTypes.Role,tokenModel.Role),//为了解决一个用户多个角色(比如:Admin,System),用下边的方法
- };
-
- // 可以将一个用户的多个角色全部赋予;
- // 作者:DX 提供技术支持;
- claims.AddRange(tokenModel.Role.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
-
-
-
- //秘钥 (SymmetricSecurityKey 对安全性的要求,密钥的长度太短会报出异常)
- var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
- var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
-
- var jwt = new JwtSecurityToken(
- issuer: iss,
- claims: claims,
- signingCredentials: creds);
-
- var jwtHandler = new JwtSecurityTokenHandler();
- var encodedJwt = jwtHandler.WriteToken(jwt);
-
- return encodedJwt;
- }
-
- ///
- /// 解析
- ///
- ///
- ///
- public static TokenModelJWT SerializeJWT(string jwtStr)
- {
- var jwtHandler = new JwtSecurityTokenHandler();
- JwtSecurityToken jwtToken = jwtHandler.ReadJwtToken(jwtStr);
- object role = new object(); ;
- try
- {
- jwtToken.Payload.TryGetValue(ClaimTypes.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;
- }
- }
-
- ///
- /// 令牌
- ///
- public class TokenModelJWT
- {
- ///
- /// Id
- ///
- public long Uid { get; set; }
- ///
- /// 角色
- ///
- public string Role { get; set; }
- ///
- /// 职能
- ///
- public string Work { get; set; }
-
- }
配置文件appsettings.json
- {
- "Logging": {
- "LogLevel": {
- "Default": "Warning"
- }
- },
- "Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //至少要16位
- "Issuer": "nmmking.Core",
- "Audience": "yika"
- },
- "Startup": {
- "Cors": {
- "IPs": "http://127.0.0.1:2364,http://localhost:2364,http://localhost:8080,http://localhost:8021,http://localhost:1818"
- }
- },
- "AllowedHosts": "*"
- }

- #region 基于策略的授权(简单版)
- // 1【授权】、这个和上边的异曲同工,好处就是不用在controller中,写多个 roles 。
- // 然后这么写 [Authorize(Policy = "Admin")]
- services.AddAuthorization(options =>
- {
- options.AddPolicy("Client", policy => policy.RequireRole("Client").Build());
- options.AddPolicy("Admin", policy => policy.RequireRole("Admin").Build());
- options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
- });
-
- #endregion
-
- #region 【认证】
- //读取配置文件
- var audienceConfig = Configuration.GetSection("Audience");
- var symmetricKeyAsBase64 = audienceConfig["Secret"];
- var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
- var signingKey = new SymmetricSecurityKey(keyByteArray);
-
- //2.1【认证】
- services.AddAuthentication(x =>
- {
- x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
- x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
- })
- .AddJwtBearer(o =>
- {
- o.TokenValidationParameters = new TokenValidationParameters
- {
- ValidateIssuerSigningKey = true,
- IssuerSigningKey = signingKey,
- ValidateIssuer = true,
- ValidIssuer = audienceConfig["Issuer"],//发行人
- ValidateAudience = true,
- ValidAudience = audienceConfig["Audience"],//订阅人
- ValidateLifetime = true,
- ClockSkew = TimeSpan.Zero,
- RequireExpirationTime = true,
- };
-
- });
- #endregion
app.UseAuthentication();
接口 GetJWTToken
- [Produces("application/json")]
- [Route("api/[controller]/[action]")]
- public class ValuesController : ControllerBase
- {
- }
- ///
- /// 登录接口:随便输入字符,获取token,然后添加 Authoritarian
- ///
- ///
- ///
- ///
- [HttpGet]
- public async Task<object> GetJWTToken(string name, string pass)
- {
- string jwtStr = string.Empty;
- bool suc = false;
- //这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作
- //这里直接写死了
-
-
- if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
- {
- return new JsonResult(new
- {
- Status = false,
- message = "用户名或密码不能为空"
- });
- }
-
- TokenModelJWT tokenModel = new TokenModelJWT();
- tokenModel.Uid = 1;
- tokenModel.Role = name;
-
- jwtStr = JwtHelper.IssueJWT(tokenModel);
- suc = true;
-
-
- return Ok(new
- {
- success = suc,
- token = jwtStr
- });
- }
测试1:测试 Get
- ///
- /// 这个也需要认证,只不过登录即可,不一定是Admin
- ///
- ///
- ///
- [HttpGet]
- [Authorize]
- public ActionResult<string> Get()
- {
- return "value";
- }
用户重新登录获取 token (这里没有指定的用户,只要登录就行),如下图所示:

再次访问 Get 接口,访问成功如下图所示:
接口2:
- ///
- /// 这个需要认证,角色必须是Admin,其他的不需要
- ///
- ///
- [HttpGet]
- [Authorize(Policy = "SystemOrAdmin")]
- public ActionResult
string>> GetData() - {
- _logger.LogError("this is an error");
- return new string[] { "value1", "value2" };
- }
随意的用户登录获取 token,如下所示
登录的用户不是 Admin,结果是拒绝访问

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

请求成功
在Startup.cs设置:
- private const string ApiName = "nmmking.Core.Api";
- private readonly string version = "V1";
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- app.UseCors("LimitRequests");
-
- //注册异常处理中间件
- app.UseMiddleware
(); -
- #region Swagger
- app.UseSwagger();
- app.UseSwaggerUI(c =>
- {
- c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{ApiName} {version}");
- //c.IndexStream = () => GetType().GetTypeInfo().Assembly.GetManifestResourceStream("index.html");
- c.RoutePrefix = "";
- });
- #endregion
- // 开启权限
- app.UseAuthentication();
-
- app.UseMvc();
- }
- public IServiceProvider ConfigureServices(IServiceCollection services)
- {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
-
- services.AddCors(c =>
- {
- c.AddPolicy("LimitRequests", policy =>
- {
- policy
- //.AllowAnyOrigin()
- .WithOrigins(new string[]{ "http://localhost:8881" })
- //.WithOrigins(Appsettings.app(new string[] { "Startup", "Cors", "IPs" }).Split(','))
- .AllowAnyHeader()
- .AllowAnyMethod();
- });
- });
-
- #region Swagger UI Service
-
- var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;
- services.AddSwaggerGen(c =>
- {
- //遍历出全部的版本,做文档信息展示
- c.SwaggerDoc(version, new OpenApiInfo
- {
- Version = version,
- Title = $"{ApiName} 接口文档——{RuntimeInformation.FrameworkDescription}",
- Description = $"{ApiName} HTTP API " + version,
- Contact = new OpenApiContact { Name = ApiName, Email = "nmmking.Core@xxx.com", Url = new Uri("http地址") },
- License = new OpenApiLicense { Name = ApiName + " 官方文档", Url = new Uri("http地址") }
- });
- c.OrderActionsBy(o => o.RelativePath);
-
-
- //就是这里
- var xmlPath = Path.Combine(basePath, "nmmking.Core.Api.xml");//这个就是刚刚配置的xml文件名
- c.IncludeXmlComments(xmlPath, true);//默认的第二个参数是false,这个是controller的注释,记得修改
-
- var xmlPath2 = Path.Combine(basePath, "nmmking.Core.Model.xml");
- c.IncludeXmlComments(xmlPath2, true);
-
- #region Token绑定到ConfigureServices
-
- // 开启加权小锁
- c.OperationFilter
(); - c.OperationFilter
(); -
- // 在header中添加token,传递到后台
- c.OperationFilter
(); -
- // Jwt Bearer 认证,必须是 oauth2
- c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
- {
- Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
- Name = "Authorization",//jwt默认的参数名称
- In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
- Type = SecuritySchemeType.ApiKey
- });
- #endregion
- });
-
- #endregion
-
- #region 授权
- // 读取配置文件
- var audienceConfig = Configuration.GetSection("Audience");
- var symmetricKeyAsBase64 = audienceConfig["Secret"];
- var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
- var signingKey = new SymmetricSecurityKey(keyByteArray);
-
- var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); //签名
-
- // 角色与接口的权限要求参数
- var permissionRequirement = new PermissionRequirement(
- ClaimTypes.Role,//基于角色的授权
- audienceConfig["Issuer"],//发行人
- audienceConfig["Audience"],//听众
- signingCredentials,//签名凭据
- expiration: TimeSpan.FromSeconds(60 * 60)//接口的过期时间
- );
-
- // 授权
- services.AddAuthorization(options =>
- {
- // 权限变量配置
- options.AddPolicy("Permission",
- policy => policy.Requirements.Add(permissionRequirement));
- });
-
- // 令牌验证参数
- var tokenValidationParameters = new TokenValidationParameters
- {
- ValidateIssuerSigningKey = true,
- IssuerSigningKey = signingKey,
- ValidateIssuer = true,
- ValidIssuer = audienceConfig["Issuer"],//发行人
- ValidateAudience = true,
- ValidAudience = audienceConfig["Audience"],//订阅人
- ValidateLifetime = true,
- ClockSkew = TimeSpan.FromSeconds(30),
- RequireExpirationTime = true,
- };
-
- services.AddAuthentication("Bearer")
- .AddJwtBearer(o =>
- {
- o.TokenValidationParameters = tokenValidationParameters;
- o.Events = new JwtBearerEvents
- {
- OnAuthenticationFailed = context =>
- {
- // 如果过期,则把<是否过期>添加到,返回头信息中
- if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
- {
- context.Response.Headers.Add("Token-Expired", "true");
- }
- return Task.CompletedTask;
- }
- };
- });
-
- services.AddSingleton(permissionRequirement);
-
- #endregion
-
- return services.BuildDynamicProxyProvider();
- }