Exemple #1
0
        /// <summary>
        /// 配置 IdentityServer 服务端
        /// nuget包: IdentityServer4 IdentityServer4.EntityFramework
        /// 1.实现用户验证登陆
        /// 2.用户验证成功后通过设置增加API访问权限
        /// </summary>
        /// <param name="services"></param>
        private void ConfigureIdentityServer(IServiceCollection services)
        {
            services.Configure <CookiePolicyOptions>(options =>
            {
                options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
                options.OnAppendCookie        = cookieContext =>
                                                CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
                options.OnDeleteCookie = cookieContext =>
                                         CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
            });

            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

            services.AddIdentityServer(options =>
            {
                // 配置用户登录的交互页面,默认为 /Account/Login
                options.UserInteraction = new UserInteractionOptions {
                    LoginUrl = AppInfo.LoginUrl
                };
                // 设置请求 token 成功后, 写入 token 的 Issuer,设置为"null"后不验证 Issuer. 可在 IdSrv 服务终结点 '/.well-known/openid-configuration' 查看 Issuer
                // 设置为 null、空字符串或者不设置时: IssuerUri 被默认为为项目监听地址
                options.IssuerUri = "null";
                options.Authentication.CookieLifetime = TimeSpan.FromHours(0.5);
                // 用户名密码 验证成功之后,将凭证写入cookie
                // 在cookie有效期内不需要重新登录, 直接通过凭证获取code ???
            })
            .AddSigningCredential(AppInfo.Instance.Certificate) // 配置 token 加密的证书
            .AddConfigurationStore(options =>                   // 持久化资源、客户端
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(AppOptions.ResolveConnectionString <string>("Identity"),
                                                                  sqlServerOptionsAction: sqlOptions =>
                {
                    // 配置ConfigurationDbContext在运行时迁移绑定的Assembly
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                });
            })
            .AddOperationalStore(options =>    // 持久化 授权码、刷新令牌、用户授权信息consents
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(AppOptions.ResolveConnectionString <string>("Identity"),
                                                                  sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                });
                options.EnableTokenCleanup = true;    // 配置自动清除令牌
            })
            .AddProfileService <MyProfileService>()
            .AddResourceOwnerValidator <MyResourceOwnerPasswordValidator>();
        }
Exemple #2
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            IMvcBuilder builder = services.AddControllersWithViews(options =>
            {
                // it doesn't require tokens for requests made using the following safe HTTP methods: GET, HEAD, OPTIONS, and TRACE
                options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());

                options.Configure();
            })
                                  .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
                                  .AddDataAnnotationsLocalization()
                                  .AddJsonOptions(options => options.JsonSerializerOptions.Configure())
                                  .ConfigureApiBehaviorOptions(options => options.Configure());

#if DEBUG
            if (Env.IsDevelopment())
            {
                builder.AddRazorRuntimeCompilation();
            }
#endif

            services.AddPortableObjectLocalization(options => options.ResourcesPath = "Localization");

            services.Configure <RequestLocalizationOptions>(options =>
            {
                var supportedCultures = new[] { "zh-CN", "en-US" };

                options.SetDefaultCulture(supportedCultures[0])
                .AddSupportedCultures(supportedCultures)
                .AddSupportedUICultures(supportedCultures);
            });


            services.AddResponseCompression((options) =>
            {
                // https://resources.infosecinstitute.com/the-breach-attack/
                // Disable compression on dynamically generated pages which over secure connections to avoid security problems.
                options.EnableForHttps = false;
            });


            // Microsoft.Extensions.Caching.StackExchangeRedis
            //services.AddStackExchangeRedisCache(options =>
            //{
            //    options.Configuration = "localhost:5000";
            //    options.InstanceName = "LightBlogCache";
            //});


            ConfigureIdentityServer(services);


            services.AddDbContext <UserDbContext>((sp, options) =>
            {
                // 闭包 or 反模式
                //sp.GetRequiredService<UserDbContext>();
                var identityConnStr = AppOptions.ResolveConnectionString <string>("Identity");
                options.UseSqlServer(identityConnStr,
                                     sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
                });
            });
            services.AddTransient <IRepository <User, int>, UserRepository>();
            services.AddTransient <IUserService <User>, UserService>();


            services.AddScoped <EncryptFormResourceFilterAttribute>();
            services.AddSingleton(AppInfo.Instance.Certificate);
            services.AddScoped <InjectResultActionFilter>();


            var jsPath = DashboardRoutes.Routes.Contains("/js[0-9]+") ? "/js[0-9]+" : "/js[0-9]{3}";
            //DashboardRoutes.Routes.Append(jsPath, new EmbeddedResourceDispatcher("application/javascript", Assembly.GetExecutingAssembly(),$"{typeof(Startup).Namespace}.HangfireCustomDashboard.hangfire.custom.js"));
            DashboardRoutes.Routes.Append(jsPath, new StaticFileDispatcher("application/javascript", "js/hangfire.custom.js", Env.WebRootFileProvider));


            var IdentityConnStr = AppOptions.ResolveConnectionString <string>("Identity");
            services.AddHangfire(x => x.UseSqlServerStorage(IdentityConnStr));
            services.AddHangfireServer();


            services.AddTransient <IJobManageService, JobManageService>();
            services.AddSingleton <JobEntryResolver>();


            services.AddSingleton <IActionContextAccessor, ActionContextAccessor>();


            services.AddHostedService <ConsumeScopedServiceHostedService>();
            services.AddScoped <IScopedProcessingService, ScopedProcessingService>();


            //services.AddDNTCaptcha(options =>
            //// options.UseSessionStorageProvider() // -> It doesn't rely on the server or client's times. Also it's the safest one.
            //// options.UseMemoryCacheStorageProvider() // -> It relies on the server's times. It's safer than the CookieStorageProvider.
            //options.UseCookieStorageProvider() // -> It relies on the server and client's times. It's ideal for scalability, because it doesn't save anything in the server's memory
            //// options.UseDistributedCacheStorageProvider() // --> It's ideal for scalability using `services.AddStackExchangeRedisCache()` for instance.

            //// Don't set this line (remove it) to use the installed system's fonts (FontName = "Tahoma").
            //// Or if you want to use a custom font, make sure that font is present in the wwwroot/fonts folder and also use a good and complete font!
            //// .UseCustomFont(Path.Combine(_env.WebRootPath, "fonts", "name.ttf"))
            //// .AbsoluteExpiration(minutes: 7)
            //// .ShowThousandsSeparators(false);
            //);


            services.Configure <MultiTenancyOptions <string> >(Configuration.GetSection("MultiTenancy"));
            services.PostConfigure <MultiTenancyOptions <string> >(options => {
                IRequestTenantProvider <string> provider = null;
                options.RequestTenantProviders.Add(provider);
            });
        }