using Autofac; using log4net; using log4net.Config; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.OpenApi.Models; using System.Text.Encodings.Web; using System.Text.Unicode; using Competition.BLL; using Competition.DAL; using Competition.Model; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using System.Linq; using System.IO; using Microsoft.AspNetCore.Mvc; using Autofac.Core; using Newtonsoft.Json.Serialization; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; using Newtonsoft.Json; using Competition.Common.Util; using static System.Net.WebRequestMethods; using Newtonsoft.Json.Linq; using System.Security.Claims; namespace CompetitionAPI { public class Startup { public static log4net.Repository.ILoggerRepository repository; public Startup(IConfiguration configuration) { Configuration = configuration; repository = LogManager.CreateRepository("NETCoreRepository"); XmlConfigurator.Configure(repository, new FileInfo("Log4net.config")); } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //配置跨域访问问题 services.AddCors( options => options.AddPolicy("CorsTest", p => p.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod() ) ); services.Configure(options => { options.KeyLengthLimit = int.MaxValue; options.ValueLengthLimit = int.MaxValue; options.MultipartBodyLengthLimit = int.MaxValue; options.MultipartHeadersLengthLimit = int.MaxValue; }); services.Configure(options => { options.Limits.MaxRequestBodySize = int.MaxValue; options.Limits.MaxRequestBufferSize = int.MaxValue; }); //禁用自动模型验证 services.Configure(options => { options.SuppressModelStateInvalidFilter = true; }); services.AddDbContext(options => options.UseMySql(Configuration.GetConnectionString("MySQL"))); services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); }); ////注册Swagger生成器,定义一个和多个Swagger 文档 //services.AddSwaggerGen(c => //{ // c.SwaggerDoc("v1", new OpenApiInfo { Title = "CompetitionAPI" }); // // 为 Swagger JSON and UI设置xml文档注释路径 // var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);//获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径) // var xmlPath = Path.Combine(basePath, "CompetitionAPI.xml"); // c.IncludeXmlComments(xmlPath); //}); services.AddControllers().AddNewtonsoftJson(options => { //配置返回Json大小写格式与Model一致 options.SerializerSettings.ContractResolver = new DefaultContractResolver(); }); //添加MVC组件 services.AddMvc().AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }); }); //注入Http services.AddSingleton(); // 确保 TokenService 类被正确注册 services.AddSingleton(new TokenService(Configuration["Jwt:SecretKey"], Configuration["Jwt:Issuer"])); // 添加身份验证服务 services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = Configuration["Jwt:Issuer"], ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"])), ValidateAudience = false, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; options.Events = new JwtBearerEvents { // 添加自定义的Token验证后的处理逻辑 OnTokenValidated = async context => { try { // 获取请求头中的Authorization值 string authorizationHeader = context.HttpContext.Request.Headers["Authorization"]; // 确保Authorization头存在且以Bearer开头 if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.StartsWith("Bearer ")) { // 提取Token值 //var token = authorizationHeader.Substring("Bearer ".Length).Trim(); var token = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiIyMDIxMTAxMzEzNTczOTIwMDczOTE0Iiwicm9sZSI6IjAiLCJuYmYiOjE3MzEyOTM5OTYsImV4cCI6MTczMTM4MDM5NiwiaWF0IjoxNzMxMjkzOTk2LCJpc3MiOiJ5b3VyX2lzc3VlciJ9.d7ymDYzNgCrwz1KVMlIbM_tZRY7E4MFEvZfeesAAeUM"; // 在这里可以访问验证后的Principal(包含用户信息) var claimsPrincipal = context.Principal.Claims; var userId = claimsPrincipal.First(claim => claim.Type == ClaimTypes.NameIdentifier).Value; var roleId = claimsPrincipal.First(claim => claim.Type == ClaimTypes.Role).Value; if (roleId == "2") { Competition.Mysql.BLL.admin_user bll = new Competition.Mysql.BLL.admin_user(); var user_model = bll.GetModel(userId); if (user_model != null) { if (user_model.r4 != token) { context.Fail(""); } } else { context.Fail(""); } } } else { context.Fail(""); } } catch (Exception ex) { // 记录日志或处理异常 context.Fail(ex); } }, //此处为权限验证失败后触发的事件 OnChallenge = context => { //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦,必须 context.HandleResponse(); var response = Tool.GetJsonWithCode(APICode.TokenFail, "Authentication failed"); //自定义自己想要返回的数据结果,我这里要返回的是Json对象,通过引用Newtonsoft.Json库进行转换 var payload = JsonConvert.SerializeObject(response); //自定义返回的数据类型 context.Response.ContentType = "application/json"; //自定义返回状态码,默认为401 我这里改成 200 context.Response.StatusCode = StatusCodes.Status401Unauthorized; //输出Json数据结果 context.Response.WriteAsync(payload); return Task.FromResult(0); } }; }); } public void ConfigureContainer(ContainerBuilder builder) { //AUTOFAC注入 builder.RegisterAssemblyTypes(typeof(BaseRepository<,>).Assembly) .Where(t => t.Name.EndsWith("Repository")) .AsImplementedInterfaces(); builder.RegisterAssemblyTypes(typeof(BaseService<,>).Assembly) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { //DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); //defaultFilesOptions.DefaultFileNames.Clear(); //defaultFilesOptions.DefaultFileNames.Add("index.html"); //app.UseDefaultFiles(defaultFilesOptions); app.UseDefaultFiles(); app.UseStaticFiles(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } // 启用身份验证中间件 app.UseAuthentication(); app.UseRouting(); app.UseCors("CorsTest");//其中app.UseCors()必须放在app.UseRouting()和app.UseEndpoints之间,不然还是解决不了问题。 app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); ////启用中间件服务生成Swagger作为JSON终结点 //app.UseSwagger(); ////启用中间件服务对swagger-ui,指定Swagger JSON终结点 //app.UseSwaggerUI(c => //{ // c.SwaggerEndpoint("/swagger/v1/swagger.json", "CompetitionAPI"); //}); } } }