Пример #1
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure <CookiePolicyOptions>(options =>
            {
                options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
                options.Secure         = CookieSecurePolicy.SameAsRequest;
                options.OnAppendCookie = cookieContext =>
                                         AuthenticationHelper.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
                options.OnDeleteCookie = cookieContext =>
                                         AuthenticationHelper.CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            });

            services.AddHealthChecks();

            services.AddJsonLocalization(options =>
            {
                options.ResourcesPath     = Configuration.GetAppSetting("ResourcesPath");
                options.ResourcesPathType = ResourcesPathType.CultureBased;
            });

            services.AddResponseCaching();
            services.AddResponseCompression();

            services.AddControllersWithViews(options =>
            {
                options.CacheProfiles.Add("default", new CacheProfile()
                {
                    Duration        = 300,
                    VaryByQueryKeys = new[] { "*" }
                });
                options.CacheProfiles.Add("private", new CacheProfile()
                {
                    Duration        = 300,
                    Location        = ResponseCacheLocation.Client,
                    VaryByQueryKeys = new[] { "*" }
                });
                options.CacheProfiles.Add("noCache", new CacheProfile()
                {
                    Duration = null,
                    NoStore  = true
                });
            })
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver      = new DefaultContractResolver();
                options.SerializerSettings.DateTimeZoneHandling  = DateTimeZoneHandling.Utc;    // 设置时区为 UTC
                options.SerializerSettings.NullValueHandling     = NullValueHandling.Ignore;
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            })
            .AddViewLocalization()
            .AddDataAnnotationsLocalization()
            ;

            var supportedCultureNames = Configuration.GetSection("Localization:SupportedCultures")?.Get <string[]>();

            if (supportedCultureNames == null || supportedCultureNames.Length == 0)
            {
                supportedCultureNames = new[] { "zh", "en" };
            }
            var supportedCultures = supportedCultureNames.Select(name => new CultureInfo(name)).ToArray();

            services.Configure <RequestLocalizationOptions>(options =>
            {
                options.DefaultRequestCulture = new RequestCulture(supportedCultures[0].Name);
                // Formatting numbers, dates, etc.
                options.SupportedCultures = supportedCultures;
                // UI strings that we have localized.
                options.SupportedUICultures = supportedCultures;
            });

            //Cookie Authentication
            services.AddAuthentication(options =>
            {
                options.DefaultScheme          = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;

                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultForbidScheme       = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme       = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignOutScheme      = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                //options.LoginPath = "/Admin/Account/Login";
                options.AccessDeniedPath = "/Account/AccessDenied";
                options.LogoutPath       = "/Account/LogOut";

                // Cookie settings
                options.Cookie.HttpOnly     = true;
                options.Cookie.SecurePolicy = CookieSecurePolicy.None;
            })
            .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.Authority            = Configuration["Authorization:Authority"];
                options.RequireHttpsMetadata = false;

                options.NameClaimType = "name";
                options.RoleClaimType = "role";
            })
            .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
            {
                var authorizationConfiguration = Configuration.GetSection("Authorization");
                authorizationConfiguration.Bind(options);

                options.ResponseType = OpenIdConnectResponseType.CodeIdToken;

                options.SaveTokens = true;
                options.GetClaimsFromUserInfoEndpoint = true;
                options.ClaimActions.MapJsonKey("role", "role");

                options.TokenValidationParameters = new TokenValidationParameters()
                {
                    NameClaimType = "name",
                    RoleClaimType = "role",
                };
                options.Events.OnMessageReceived = context =>
                {
                    context.Properties.IsPersistent = true;
                    return(Task.CompletedTask);
                };
                options.Events.OnRedirectToIdentityProvider = rc =>
                {
                    rc.ProtocolMessage.RedirectUri = authorizationConfiguration["RedirectUri"];
                    return(Task.CompletedTask);
                };
            })
            ;
            services.AddAuthorization(options =>
            {
                options.AddPolicy("ReservationManager", builder => builder
                                  .AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme)
                                  .RequireAuthenticatedUser()
                                  .RequireRole("ReservationManager", "ReservationAdmin")
                                  );
                options.AddPolicy("ReservationAdmin", builder => builder
                                  .AddAuthenticationSchemes(OpenIdConnectDefaults.AuthenticationScheme)
                                  .RequireAuthenticatedUser()
                                  .RequireRole("ReservationAdmin")
                                  );
                options.AddPolicy("ReservationApi", builder => builder
                                  .AddAuthenticationSchemes(IdentityServerAuthenticationDefaults.AuthenticationScheme)
                                  .RequireAuthenticatedUser()
                                  .RequireScope("ReservationApi")
                                  );
            });

            // addDbContext
            services.AddDbContextPool <ReservationDbContext>(option =>
            {
                var dbType = Configuration.GetAppSetting("DbType");
                if ("InMemory".EqualsIgnoreCase(dbType))
                {
                    option.UseInMemoryDatabase("Reservation");
                }
                else if ("MySql".EqualsIgnoreCase(dbType))
                {
                    option.UseMySql(Configuration.GetConnectionString("Reservation"));
                }
                else
                {
                    option.UseSqlServer(Configuration.GetConnectionString("Reservation"));
                }
            }, 100);

            services.AddGoogleRecaptchaHelper(Configuration.GetSection("GoogleRecaptcha"), client =>
            {
                client.Timeout = TimeSpan.FromSeconds(3);
            });
            services.AddTencentCaptchaHelper(options =>
            {
                options.AppId     = Configuration["Tencent:Captcha:AppId"];
                options.AppSecret = Configuration["Tencent:Captcha:AppSecret"];
            }, client =>
            {
                client.Timeout = TimeSpan.FromSeconds(3);
            });
            services.AddHttpClient <ChatBotHelper>(client =>
            {
                client.Timeout = TimeSpan.FromSeconds(5);
            });
            services.TryAddSingleton <ChatBotHelper>();
            services.AddHttpClient <WechatAPI.Helper.WeChatHelper>();
            services.TryAddSingleton <WechatAPI.Helper.WeChatHelper>();

            // registerApplicationSettingService
            if (HostEnvironment.IsDevelopment())
            {
                services.TryAddSingleton <IApplicationSettingService, ApplicationSettingInMemoryService>();
                services.TryAddSingleton <ICacheClient, InMemoryCacheClient>();
            }
            else
            {
                services.TryAddSingleton <IApplicationSettingService, ApplicationSettingInRedisService>();
            }

            // register access control service
            services.AddAccessControlHelper()
            .AddResourceAccessStrategy <AdminPermissionRequireStrategy>()
            .AddControlAccessStrategy <AdminOnlyControlAccessStrategy>()
            ;

            // DataProtection persist in redis
            var dataProtectionBuilder = services.AddDataProtection()
                                        .SetApplicationName(ApplicationHelper.ApplicationName);

            if (!HostEnvironment.IsDevelopment())
            {
                services.AddRedisConfig(options =>
                {
                    options.DefaultDatabase = 0;
                    options.RedisServers    = new[]
                    {
                        new RedisServerConfiguration(Configuration.GetConnectionString("Redis") ?? "127.0.0.1"),
                    };
                    options.CachePrefix = "OpenReservation";
                });

                dataProtectionBuilder.PersistKeysToStackExchangeRedis(
                    () => DependencyResolver.Current
                    .ResolveService <IDatabase>(),
                    "DataProtection-Keys");
            }

            // events
            services.AddEvents()
            .AddEventHandler <NoticeViewEvent, NoticeViewEventHandler>()
            .AddEventHandler <OperationLogEvent, OperationLogEventHandler>()
            ;

            services.Configure <CustomExceptionHandlerOptions>(options =>
            {
                options.OnRequestAborted = (context, logger) => Task.CompletedTask;

                options.OnException = (context, logger, exception) =>
                {
                    var ex = exception;
                    if (exception is AggregateException aggregateException)
                    {
                        ex = aggregateException.Unwrap();
                    }

                    if (context.RequestAborted.IsCancellationRequested && (
                            ex is TaskCanceledException || ex is OperationCanceledException)
                        )
                    {
                        return(Task.CompletedTask);
                    }

                    logger.LogError(exception, exception.Message);
                    return(Task.CompletedTask);
                };
            });

            // gitee storage
            services.AddGiteeStorageProvider(Configuration.GetSection("Storage:Gitee"));

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc(ApplicationHelper.ApplicationName, new OpenApiInfo {
                    Title = "活动室预约系统 API", Version = "1.0"
                });

                options.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, $"{typeof(Notice).Assembly.GetName().Name}.xml"));
                options.IncludeXmlComments(System.IO.Path.Combine(AppContext.BaseDirectory, $"{typeof(API.NoticeController).Assembly.GetName().Name}.xml"), true);
                // Add security definitions
                options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {
                    Description = "Please enter into field the word 'Bearer' followed by a space and the JWT value",
                    Name        = "Authorization",
                    In          = ParameterLocation.Header,
                    Type        = SecuritySchemeType.ApiKey,
                });
                options.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference()
                            {
                                Id   = "Bearer",
                                Type = ReferenceType.SecurityScheme
                            }
                        }, Array.Empty <string>()
                    }
                });
            });

            services.AddHttpContextUserIdProvider(options =>
            {
                options.UserIdFactory = context =>
                {
                    var user = context?.User;
                    if (null != user && user.Identity.IsAuthenticated)
                    {
                        return($"{user.GetUserId()}--{user.Identity.Name}");
                    }

                    var userIp = context?.GetUserIP();
                    if (null != userIp)
                    {
                        return(userIp);
                    }

                    return($"{Environment.MachineName}__{Environment.UserName}");
                };
            });

            // RegisterAssemblyModules
            services.RegisterAssemblyModules();
        }