// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { /* * 对于Token签名需要一对公钥和私钥, * 不过IdentityServer为开发者提供了一个AddDeveloperSigningCredential()方法,它会帮我们搞定这个事,并默认存到硬盘中。 * 当切换到生产环境时,还是得使用正儿八经的证书,更换为使用AddSigningCredential()方法 */ // var basePath = PlatformServices.Default.Application.ApplicationBasePath; var basePath = AppContext.BaseDirectory; InMemoryConfiguration.Configuration = this.Configuration; services.AddIdentityServer() // .AddDeveloperSigningCredential() .AddSigningCredential(new X509Certificate2(Path.Combine(basePath, Configuration["Certificates:CerPath"]), Configuration["Certificates:Password"])) .AddTestUsers(InMemoryConfiguration.GetUsers().ToList()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources()); // for QuickStart-UI services.AddMvc(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region ²âÊÔIdentityServer4 var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; }) // in-memory, code config .AddTestUsers(InMemoryConfiguration.Users().ToList()) .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()); builder.AddDeveloperSigningCredential(); if (Environment.IsDevelopment()) { builder.AddDeveloperSigningCredential(); } else { throw new Exception("need to configure key material"); } #endregion services.AddRazorPages(); }
private static void Seed(IServiceScope serviceScope) { var context = serviceScope .ServiceProvider .GetRequiredService <ConfigurationDbContext>(); if (!context.Clients.Any()) { foreach (var client in InMemoryConfiguration.GetClients()) { context.Clients.Add(client.ToEntity()); } context.SaveChanges(); } if (!context.IdentityResources.Any()) { foreach (var resource in InMemoryConfiguration.GetIdentityResources()) { context.IdentityResources.Add(resource.ToEntity()); } context.SaveChanges(); } if (!context.ApiResources.Any()) { foreach (var resource in InMemoryConfiguration.GetApiResources()) { context.ApiResources.Add(resource.ToEntity()); } context.SaveChanges(); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //var basePath = PlatformServices.Default.Application.ApplicationBasePath; //InMemoryConfiguration.Configuration = this.Configuration; services.Configure <CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddIdentityServer() .AddDeveloperSigningCredential() //开发测试密钥 //.AddSigningCredential(new X509Certificate2(Path.Combine(basePath, //Configuration["Certificates:CerPath"]), //Configuration["Certificates:Password"])) .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddTestUsers(InMemoryConfiguration.GetUsers().ToList()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources()); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { var inMemoryConfiguration = new InMemoryConfiguration(); services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryClients(inMemoryConfiguration.GetClients()) .AddInMemoryApiResources(inMemoryConfiguration.GetResources()); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddIdentityServer() .AddDeveloperSigningCredential() .AddTestUsers(InMemoryConfiguration.GetUsers().ToList()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources()); }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer() .AddSigningCredential(new X509Certificate2(GetCertificatePath(), "password")) .AddTestUsers(InMemoryConfiguration.GetUsers()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()); services.AddMvc(); }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer() .AddDeveloperSigningCredential() // .AddSigningCredential(new X509Certificate2(@"C:\Users\Daniil\Desktop\APP\Oauth\socialnetwork.pfx", "password")) .AddTestUsers(InMemoryConfiguration.Users().ToList()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiResources(InMemoryConfiguration.ApiResources()); services.AddMvc(); }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { //var basePath = PlatformServices.Default.Application.ApplicationBasePath; //InMemoryConfiguration.Configuration = this.Configuration; services.AddIdentityServer() .AddDeveloperSigningCredential() //.AddSigningCredential(new X509Certificate2(Path.Combine(basePath,Configuration["Certificates:CerPath"]),Configuration["Certificates:Password"])) .AddTestUsers(InMemoryConfiguration.GetUsers().ToList()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources()); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // registers the IdentityServer services in DI and // it registers In-memory store for runtime state // for production scenarios you need a persistent or shared store // TODO: remove InMemory configs for production release :) services.AddIdentityServer() .AddDeveloperSigningCredential() .AddTestUsers(InMemoryConfiguration.GetTestUsers().ToList()) .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryClients(InMemoryConfiguration.GetClients()); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { var basePath = PlatformServices.Default.Application.ApplicationBasePath; InMemoryConfiguration.Configuration = this.Configuration; services.AddIdentityServer() //.AddDeveloperSigningCredential() .AddSigningCredential(new X509Certificate2(Path.Combine(basePath, Configuration["Certificates:CerPath"]), Configuration["Certificates:Password"])) .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddTestUsers(InMemoryConfiguration.GetUsers().ToList()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources()); // for QuickStart-UI services.AddMvc(); //services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
public void MigrateInMemoryDataToSqlServer(IApplicationBuilder app) { using (var scope = app.ApplicationServices.GetService <IServiceScopeFactory>().CreateScope()) { scope.ServiceProvider.GetRequiredService <PersistedGrantDbContext>().Database.Migrate(); var context = scope.ServiceProvider.GetRequiredService <ConfigurationDbContext>(); context.Database.Migrate(); if (!context.Clients.Any()) { foreach (var client in InMemoryConfiguration.GetClients()) { context.Clients.Add(client.ToEntity()); } context.SaveChanges(); } if (!context.IdentityResources.Any()) { foreach (var resource in InMemoryConfiguration.GetIdentityResources()) { context.IdentityResources.Add(resource.ToEntity()); } context.SaveChanges(); } if (!context.ApiResources.Any()) { foreach (var resource in InMemoryConfiguration.GetApiResources()) { context.ApiResources.Add(resource.ToEntity()); } context.SaveChanges(); } } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddSingleton(new GetTableData(Environment.ContentRootPath)); services.AddSingleton(new Appsettings(Environment.ContentRootPath)); services.AddSingleton <IUserService, UserService>(); services.AddSingleton <IRoleService, RoleService>(); services.AddSingleton <IUserRoleService, UserRoleService>(); #region ²âÊÔIdentityServer4 var builder = services.AddIdentityServer(options => { options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; }) // in-memory, code config .AddTestUsers(InMemoryConfiguration.Users().ToList()) .AddInMemoryApiResources(InMemoryConfiguration.GetApiResources()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()); //.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>() //.AddProfileService<CustomProfileService>(); builder.AddDeveloperSigningCredential(); if (Environment.IsDevelopment()) { builder.AddDeveloperSigningCredential(); } else { throw new Exception("need to configure key material"); } #endregion services.AddRazorPages(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region IdentityServer4+FreeSql InMemoryConfiguration.Configuration = this.Configuration; services.AddSingleton(Fsql); //services.AddScoped(typeof(IUnitOfWork), typeof(UnitOfWork)); services.AddScoped <IUnitOfWork>(sp => sp.GetService <IFreeSql>().CreateUnitOfWork()); services.AddFreeRepository(filter => { filter.Apply <IDeleteAduitEntity>("IsDeleted", a => a.IsDeleted == false); }, GetType().Assembly, typeof(AuditBaseRepository <>).Assembly); services.AddIdentityServer() #if DEBUG .AddDeveloperSigningCredential() #endif #if !DEBUG .AddSigningCredential(new X509Certificate2(Path.Combine(AppContext.BaseDirectory, Configuration["Certificates:Path"]), Configuration["Certificates:Password"])) #endif .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region AddAuthentication\AddIdentityServerAuthentication //AddAuthentication()是把验证服务注册到DI, 并配置了Bearer作为默认模式. //AddIdentityServerAuthentication()是在DI注册了token验证的处理者. //由于是本地运行, 所以就不使用https了, RequireHttpsMetadata = false.如果是生产环境, 一定要使用https. //Authority指定Authorization Server的地址. //ApiName要和Authorization Server里面配置ApiResource的name一样. //和 AddJwtBearer不能同时使用,目前还不理解区别。 //services // .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) // .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => // { // options.RequireHttpsMetadata = false; // for dev env // options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; ; // options.ApiName = Configuration["Service:Name"]; // match with configuration in IdentityServer // //options.JwtValidationClockSkew = TimeSpan.FromSeconds(60 * 5); // }); #endregion #region AddJwtBearer services.AddAuthentication(opts => { opts.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; opts.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; //opts.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; opts.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddCookie(options => { options.LoginPath = "/cms/oauth2/signin"; options.LogoutPath = "/cms/oauth2/signout"; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { //identityserver4 地址 也就是本项目地址 options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; options.RequireHttpsMetadata = false; options.Audience = Configuration["Service:Name"]; options.TokenValidationParameters = new TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey( Encoding.ASCII.GetBytes(Configuration["Authentication:JwtBearer:SecurityKey"])), // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = Configuration["Authentication:JwtBearer:Issuer"], // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = Configuration["Authentication:JwtBearer:Audience"], // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here //ClockSkew = TimeSpan.Zero }; //options.TokenValidationParameters = new TokenValidationParameters() //{ // ClockSkew = TimeSpan.Zero //偏移设置为了0s,用于测试过期策略,完全按照access_token的过期时间策略,默认原本为5分钟 //}; //使用Authorize设置为需要登录时,返回json格式数据。 options.Events = new JwtBearerEvents() { OnAuthenticationFailed = context => { //Token expired if (context.Exception.GetType() == typeof(SecurityTokenExpiredException)) { context.Response.Headers.Add("Token-Expired", "true"); } return(Task.CompletedTask); }, OnChallenge = context => { //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦 context.HandleResponse(); string msg; ErrorCode errorCode; int statusCode = StatusCodes.Status401Unauthorized; if (context.Error == "invalid_token" && context.ErrorDescription == "The token is expired") { msg = "令牌过期"; errorCode = ErrorCode.TokenExpired; statusCode = StatusCodes.Status422UnprocessableEntity; } else if (context.Error == "invalid_token" && context.ErrorDescription.IsNullOrEmpty()) { msg = "令牌失效"; errorCode = ErrorCode.TokenInvalidation; } else { msg = "请先登录";//""认证失败,请检查请求头或者重新登录"; errorCode = ErrorCode.AuthenticationFailed; } context.Response.ContentType = "application/json"; context.Response.StatusCode = statusCode; context.Response.WriteAsync(new ResultDto(errorCode, msg, context.HttpContext).ToString()); return(Task.FromResult(0)); } }; }) .AddGitHub(options => { options.ClientId = Configuration["Authentication:GitHub:ClientId"]; options.ClientSecret = Configuration["Authentication:GitHub:ClientSecret"]; options.Scope.Add("user:email"); //authenticateResult.Principal.FindFirst(ClaimTypes.Uri)?.Value; 得到GitHub头像 options.ClaimActions.MapJsonKey(LinConsts.Claims.AvatarUrl, "avatar_url"); options.ClaimActions.MapJsonKey(LinConsts.Claims.BIO, "bio"); options.ClaimActions.MapJsonKey(LinConsts.Claims.BlogAddress, "blog"); }); #endregion #endregion services.AddAutoMapper(typeof(UserProfile).Assembly, typeof(PoemProfile).Assembly); //services.AddCors(option => option.AddPolicy("cors", policy => policy.AllowAnyHeader().AllowAnyMethod().AllowCredentials().AllowAnyOrigin())); services.AddCors(); #region Mvc services.AddControllers(options => { options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); //设置SnakeCase形式的QueryString参数 options.Filters.Add <LinCmsExceptionFilter>(); options.Filters.Add <LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 }) .AddNewtonsoftJson(opt => { //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { ProcessDictionaryKeys = true } }; }) .ConfigureApiBehaviorOptions(options => { options.SuppressConsumesConstraintForFormFileParameters = true; //SuppressUseValidationProblemDetailsForInvalidModelStateResponses; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new ResultDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); #endregion services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); #region Scrutor 与单个单个注册等价,不过可批量注册 //services.AddScoped<ILogService, LogService>(); //services.AddScoped<IUserSevice, UserService>(); services.Scan(scan => scan //加载Startup这个类所在的程序集 .FromAssemblyOf <IAppService>() // 表示要注册那些类,上面的代码还做了过滤,只留下了以 Service 结尾的类 .AddClasses(classes => classes.Where(t => t.Name != "IFileService" && t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))) .UsingRegistrationStrategy(RegistrationStrategy.Skip) //表示将类型注册为提供其所有公共接口作为服务 .AsImplementedInterfaces() //表示注册的生命周期为 Transient .WithTransientLifetime() // We start out with all types in the assembly of ITransientService .FromAssemblyOf <IScopeDependency>() // AddClasses starts out with all public, non-abstract types in this assembly. // These types are then filtered by the delegate passed to the method. // In this case, we filter out only the classes that are assignable to ITransientService. .AddClasses(classes => classes.AssignableTo <ITransientDependency>()) // We then specify what type we want to register these classes as. // In this case, we want to register the types as all of its implemented interfaces. // So if a type implements 3 interfaces; A, B, C, we'd end up with three separate registrations. .AsImplementedInterfaces() // And lastly, we specify the lifetime of these registrations. .WithTransientLifetime() ); string serviceName = Configuration.GetSection("FILE:SERVICE").Value; if (serviceName == LinFile.LocalFileService) { services.AddTransient <IFileService, LocalFileService>(); } else { services.AddTransient <IFileService, QiniuService>(); } #endregion #region Swagger //Swagger重写PascalCase,改成SnakeCase模式 services.TryAddEnumerable(ServiceDescriptor .Transient <IApiDescriptionProvider, SnakeCaseQueryParametersApiDescriptionProvider>()); //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo() { Title = "LinCms", Version = "v1" }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath); }); #endregion //将Handler注册到DI系统中 services.AddScoped <IAuthorizationHandler, PermissionAuthorizationHandler>(); services.Configure <FormOptions>(options => { options.MultipartBodyLengthLimit = 1024 * 1024 * 2; options.MultipartHeadersCountLimit = 10; }); IConfigurationSection configurationSection = Configuration.GetSection("ConnectionStrings:Default"); services.AddCap(x => { x.UseMySql(configurationSection.Value); x.UseRabbitMQ("localhost"); x.UseDashboard(); x.FailedRetryCount = 5; x.FailedThresholdCallback = (type, msg) => { Console.WriteLine( $@"A message of type {type} failed after executing {x.FailedRetryCount} several times, requiring manual troubleshooting. Message name: {msg.GetName()}"); }; }); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region IdentityServer4+FreeSql InMemoryConfiguration.Configuration = this.Configuration; services.AddSingleton(Fsql); services.AddFreeRepository(filter => { filter.Apply <ISoftDeleteAduitEntity>("SoftDelete", a => a.IsDeleted == false); }, GetType().Assembly, typeof(AuditBaseRepository <>).Assembly); services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region AddAuthentication\AddIdentityServerAuthentication //AddAuthentication()是把验证服务注册到DI, 并配置了Bearer作为默认模式. //AddIdentityServerAuthentication()是在DI注册了token验证的处理者. //由于是本地运行, 所以就不使用https了, RequireHttpsMetadata = false.如果是生产环境, 一定要使用https. //Authority指定Authorization Server的地址. //ApiName要和Authorization Server里面配置ApiResource的name一样. //和 AddJwtBearer不能同时使用,目前还不理解区别。 //services // .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) // .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => // { // options.RequireHttpsMetadata = false; // for dev env // options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; ; // options.ApiName = Configuration["Service:Name"]; // match with configuration in IdentityServer // options.JwtValidationClockSkew = TimeSpan.FromSeconds(60*5); // }); #endregion #region AddJwtBearer services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { //identityserver4 地址 也就是本项目地址 options.Authority = $"{Configuration["Identity:Protocol"]}://{Configuration["Identity:IP"]}:{Configuration["Identity:Port"]}"; options.RequireHttpsMetadata = false; options.Audience = Configuration["Service:Name"]; //options.TokenValidationParameters = new TokenValidationParameters() //{ // ClockSkew = TimeSpan.Zero //偏移设置为了0s,用于测试过期策略,完全按照access_token的过期时间策略,默认原本为5分钟 //}; //使用Authorize设置为需要登录时,返回json格式数据。 options.Events = new JwtBearerEvents() { OnChallenge = context => { //此处代码为终止.Net Core默认的返回类型和数据结果,这个很重要哦 context.HandleResponse(); string msg; ErrorCode errorCode; int statusCode = StatusCodes.Status401Unauthorized; if (context.Error == "invalid_token" && context.ErrorDescription == "The token is expired") { msg = "令牌过期"; errorCode = ErrorCode.TokenExpired; statusCode = StatusCodes.Status422UnprocessableEntity; } else if (context.Error == "invalid_token" && context.ErrorDescription.IsNullOrEmpty()) { msg = "令牌失效"; errorCode = ErrorCode.TokenInvalidation; } else { msg = "认证失败,请检查请求头或者重新登陆"; errorCode = ErrorCode.TokenInvalidation; } context.Response.ContentType = "application/json"; context.Response.StatusCode = statusCode; context.Response.WriteAsync(new ResultDto(errorCode, msg, context.HttpContext).ToString()); return(Task.FromResult(0)); } }; }); #endregion #endregion services.AddAutoMapper(typeof(Startup).Assembly, typeof(PoemProfile).Assembly); services.AddCors(option => option.AddPolicy("cors", policy => policy.AllowAnyHeader().AllowAnyMethod().AllowCredentials().AllowAnyOrigin())); #region Mvc services.AddMvc(options => { options.ValueProviderFactories.Add(new SnakeCaseQueryValueProviderFactory()); //设置SnakeCase形式的QueryString参数 options.Filters.Add <LinCmsExceptionFilter>(); options.Filters.Add <LogActionFilterAttribute>(); // 添加请求方法时的日志记录过滤器 }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .ConfigureApiBehaviorOptions(options => { options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new ResultDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }) .AddJsonOptions(opt => { //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { ProcessDictionaryKeys = true } }; }); #endregion services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); #region Scrutor 与单个单个注册等价,不过可批量注册 //services.AddScoped<ILogService, LogService>(); //services.AddScoped<IUserSevice, UserService>(); services.Scan(scan => scan //加载Startup这个类所在的程序集 .FromAssemblyOf <Startup>() // 表示要注册那些类,上面的代码还做了过滤,只留下了以 Service 结尾的类 .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))) //表示将类型注册为提供其所有公共接口作为服务 .AsImplementedInterfaces() //表示注册的生命周期为 Transient .WithTransientLifetime() // We start out with all types in the assembly of ITransientService .FromAssemblyOf <IScopeDependency>() // AddClasses starts out with all public, non-abstract types in this assembly. // These types are then filtered by the delegate passed to the method. // In this case, we filter out only the classes that are assignable to ITransientService. .AddClasses(classes => classes.AssignableTo <ITransientDependency>()) // We then specify what type we want to register these classes as. // In this case, we want to register the types as all of its implemented interfaces. // So if a type implements 3 interfaces; A, B, C, we'd end up with three separate registrations. .AsImplementedInterfaces() // And lastly, we specify the lifetime of these registrations. .WithTransientLifetime() ); #endregion #region Swagger //Swagger重写PascalCase,改成SnakeCase模式 services.TryAddEnumerable(ServiceDescriptor .Transient <IApiDescriptionProvider, SnakeCaseQueryParametersApiDescriptionProvider>()); //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new Info() { Title = "LinCms", Version = "v1" }); var security = new Dictionary <string, IEnumerable <string> > { { "Bearer", new string[] { } }, }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new ApiKeyScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = "header", //jwt默认存放Authorization信息的位置(请求头中) Type = "apiKey" }); string basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);//获取应用程序所在目录(绝对,不受工作目录影响,建议采用此方法获取路径) string xmlPath = Path.Combine(basePath, "LinCms.Web.xml"); options.IncludeXmlComments(xmlPath); options.OperationFilter <SwaggerFileHeaderParameter>(); }); #endregion //将Handler注册到DI系统中 services.AddScoped <IAuthorizationHandler, PermissionAuthorizationHandler>(); services.Configure <FormOptions>(options => { options.MultipartBodyLengthLimit = 1024 * 1024 * 2; options.MultipartHeadersCountLimit = 10; }); }
public void ConfigureServices(IServiceCollection services) { InMemoryConfiguration.Configuration = this.Configuration; services.AddContext(); services.AddCors(); services.AddHash(); services.AddCryptography("lin-cms-dotnetcore-cryptography"); services.ConfigureApplicationCookie(options => { options.LoginPath = "/account/login"; }); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(120); }); services.AddIdentityServer(options => new IdentityServerOptions { UserInteraction = new UserInteractionOptions { LoginUrl = "/account/login", LogoutUrl = "/account/logout", } }) #if DEBUG .AddDeveloperSigningCredential() #endif #if !DEBUG .AddSigningCredential(new X509Certificate2( Path.Combine(AppContext.BaseDirectory, Configuration["Certificates:Path"]), Configuration["Certificates:Password"]) ) #endif .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddInMemoryApiScopes(InMemoryConfiguration.GetApiScopes()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region Swagger //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { string ApiName = "LinCms.IdentityServer4"; options.SwaggerDoc("v1", new OpenApiInfo() { Title = ApiName + RuntimeInformation.FrameworkDescription, Version = "v1", Contact = new OpenApiContact { Name = ApiName, Email = "*****@*****.**", Url = new Uri("https://www.cnblogs.com/igeekfan/") }, License = new OpenApiLicense { Name = ApiName + " 官方文档", Url = new Uri("https://luoyunchong.github.io/vovo-docs/dotnetcore/lin-cms/dotnetcore-start.html") } }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); try { string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath, true); } catch (Exception ex) { Log.Logger.Warning(ex.Message); } options.AddServer(new OpenApiServer() { Url = "", Description = "vvv" }); options.CustomOperationIds(apiDesc => { var controllerAction = apiDesc.ActionDescriptor as ControllerActionDescriptor; return(controllerAction.ControllerName + "-" + controllerAction.ActionName); }); }); #endregion services.AddTransient <IUserRepository, UserRepository>(); services.AddTransient <IUserIdentityService, UserIdentityService>(); services.AddTransient <ICurrentUser, CurrentUser>(); services.AddTransient(typeof(IAuditBaseRepository <>), typeof(AuditBaseRepository <>)); services.AddTransient(typeof(IAuditBaseRepository <,>), typeof(AuditBaseRepository <,>)); //services.AddTransient<CustomExceptionMiddleWare>(); services.AddAutoMapper(typeof(UserProfile).Assembly); services.AddControllersWithViews(options => { options.Filters.Add <LinCmsExceptionFilter>(); }) .AddNewtonsoftJson(opt => { //忽略循环引用 opt.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 //opt.SerializerSettings.ContractResolver = new DefaultContractResolver() //{ // NamingStrategy = new SnakeCaseNamingStrategy() // { // ProcessDictionaryKeys = true // } //}; }) .ConfigureApiBehaviorOptions(options => { options.SuppressConsumesConstraintForFormFileParameters = true; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); services.AddHttpsRedirection(options => { options.RedirectStatusCode = StatusCodes.Status308PermanentRedirect; options.HttpsPort = 443; }); services.AddHealthChecks(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { InMemoryConfiguration.Configuration = this.Configuration; services.AddSingleton(Fsql); services.AddScoped <IUnitOfWork>(sp => sp.GetService <IFreeSql>().CreateUnitOfWork()); services.AddFreeRepository(filter => { filter.Apply <IDeleteAduitEntity>("IsDeleted", a => a.IsDeleted == false); }, GetType().Assembly, typeof(AuditBaseRepository <>).Assembly); services.AddIdentityServer() #if DEBUG .AddDeveloperSigningCredential() #endif #if DEBUG .AddSigningCredential(new X509Certificate2( Path.Combine(AppContext.BaseDirectory, Configuration["Certificates:Path"]), Configuration["Certificates:Password"]) ) #endif .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region Swagger //Swagger重写PascalCase,改成SnakeCase模式 services.TryAddEnumerable(ServiceDescriptor .Transient <IApiDescriptionProvider, SnakeCaseQueryParametersApiDescriptionProvider>()); //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo() { Title = "LinCms.IdentityServer4", Version = "v1" }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath); }); #endregion services.AddTransient <ICurrentUser, CurrentUser>(); services.AddControllers(); }
public void ConfigureServices(IServiceCollection services) { InMemoryConfiguration.Configuration = this.Configuration; services.AddContext(); services.AddIdentityServer() #if DEBUG .AddDeveloperSigningCredential() #endif #if !DEBUG .AddSigningCredential(new X509Certificate2( Path.Combine(AppContext.BaseDirectory, Configuration["Certificates:Path"]), Configuration["Certificates:Password"]) ) #endif .AddInMemoryIdentityResources(InMemoryConfiguration.GetIdentityResources()) .AddInMemoryApiResources(InMemoryConfiguration.GetApis()) .AddInMemoryClients(InMemoryConfiguration.GetClients()) .AddProfileService <LinCmsProfileService>() .AddResourceOwnerValidator <LinCmsResourceOwnerPasswordValidator>(); #region Swagger //Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo() { Title = "LinCms.IdentityServer4", Version = "v1" }); var security = new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, Array.Empty <string>() } }; options.AddSecurityRequirement(security);//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致,这里是Bearer。 options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT授权(数据将在请求头中进行传输) 参数结构: \"Authorization: Bearer {token}\"", Name = "Authorization", //jwt默认的参数名称 In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中) Type = SecuritySchemeType.ApiKey }); string xmlPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Startup).Assembly.GetName().Name}.xml"); options.IncludeXmlComments(xmlPath); }); #endregion services.AddTransient <IUserRepository, UserRepository>(); services.AddTransient <IUserIdentityService, UserIdentityService>(); services.AddTransient <ICurrentUser, CurrentUser>(); services.AddTransient(typeof(IAuditBaseRepository <>), typeof(AuditBaseRepository <>)); services.AddTransient(typeof(IAuditBaseRepository <,>), typeof(AuditBaseRepository <,>)); services.AddTransient <CustomExceptionMiddleWare>(); services.AddCors(); services.AddAutoMapper(typeof(UserProfile).Assembly); services.AddControllers(options => { //options.Filters.Add<LinCmsExceptionFilter>(); }) .AddNewtonsoftJson(opt => { //opt.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:MM:ss"; //设置自定义时间戳格式 opt.SerializerSettings.Converters = new List <JsonConverter>() { new LinCmsTimeConverter() }; // 设置下划线方式,首字母是小写 opt.SerializerSettings.ContractResolver = new DefaultContractResolver() { NamingStrategy = new SnakeCaseNamingStrategy() { ProcessDictionaryKeys = true } }; }) .ConfigureApiBehaviorOptions(options => { options.SuppressConsumesConstraintForFormFileParameters = true; //自定义 BadRequest 响应 options.InvalidModelStateResponseFactory = context => { var problemDetails = new ValidationProblemDetails(context.ModelState); var resultDto = new UnifyResponseDto(ErrorCode.ParameterError, problemDetails.Errors, context.HttpContext); return(new BadRequestObjectResult(resultDto) { ContentTypes = { "application/json" } }); }; }); services.AddHealthChecks(); }