AddStackExchangeRedisCache哨兵模式 | Cookie身份认证多台服务器部署认证AddDataProtection

using ZKHK.EntityFramework.Core;
using Furion;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Serilog;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ZKHK.Web.Core
{
    public class Startup : AppStartup
    {

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCorsAccessor();
            services.AddRemoteRequest();
            services.AddStackExchangeRedisCache(options =>
            {                
                options.InstanceName = "furion_"; // 键名前缀
                options.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions()
                {
                    EndPoints = { { "127.0.0.1", 35679 }, { "127.0.0.1", 35680 }, { "127.0.0.1", 35681 } },
                    Password = "123456",
                    ServiceName = "mymaster",
                    DefaultDatabase = 10,
                    AllowAdmin = true,
                    AbortOnConnectFail = false,
                    KeepAlive = 180,
                    TieBreaker = "",                  
                    CommandMap = StackExchange.Redis.CommandMap.Create(new HashSet//哨兵模式, EXCLUDE a few commands
                    {
                        "INFO", "CONFIG", "CLUSTER","PING", "ECHO", "CLIENT"
                    }, available: false),
                    //CommandMap = StackExchange.Redis.CommandMap.Sentinel,
                };
                
            });

            services.AddDbContext(options => options.UseSqlServer(App.Configuration["ConnectionStrings:UseMykeys"]));

            //哨兵模式,Redis 配置
            var configurationOptions = new StackExchange.Redis.ConfigurationOptions()
            {
                EndPoints = { { "127.0.0.1", 35679 }, { "127.0.0.1", 35680 }, { "127.0.0.1", 35681 } },
                Password = "123456",
                ServiceName = "mymaster",
                DefaultDatabase = 10,
                AllowAdmin = true,
                AbortOnConnectFail = false,
                KeepAlive = 180,
                TieBreaker = "",
                CommandMap = StackExchange.Redis.CommandMap.Create(new HashSet//哨兵模式 EXCLUDE a few commands
                {
                    "INFO", "CONFIG", "CLUSTER","PING", "ECHO", "CLIENT"
                }, available: false),
                //CommandMap = StackExchange.Redis.CommandMap.Sentinel,
            };
            var redis = StackExchange.Redis.ConnectionMultiplexer.Connect(configurationOptions);//创建Redis实例
            //配置 ASP.NET 核心数据保护,初始化数据保护系统时,它会根据操作环境应用默认设置。这些设置通常适用于在单台计算机上运行的应用,但是如果你的web分布在多台服务器上,则需要做配置
            //分布式部署建议将秘钥存储在Redis中,或者数据库中,当我们使用基于Cookie的认证的时候,就不会出现[Authorize]认证失败而报 "将您重定向的次数过多"的错误
            services.AddDataProtection()  // 配置数据保护,应用之间共享受保护的有效负载
                .SetApplicationName("SSO")
                .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys"); //将密钥存储在Redis中,可以用于在多台服务器上部署站点,站点之间的cookie数据共享 ,需要引入:Microsoft.AspNetCore.DataProtection.StackExchangeRedis
                //.PersistKeysToDbContext() //将秘钥存储在数据库中,可以用于在多台服务器上部署站点,站点之间的cookie数据共享,需要引入:Microsoft.AspNetCore.DataProtection.EntityFrameworkCore(注意版本的兼容问题)
                //.PersistKeysToFileSystem(new DirectoryInfo("D:\\share_keys\\")); //将秘钥存储在本地,只能用于单台服务器上部署多个站点,站点之间的cookie数据共享 
                //.PersistKeysToRegistry(Microsoft.Win32.RegistryKey.FromHandle(null)); //将秘钥存储在注册表中,只能用于单台服务器上部署多个站点,站点之间的cookie数据共享

            services.AddAuthentication(options =>//认证
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;

            });
            services.AddJwt(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            }).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
            {
                options.LoginPath = new PathString("/Account/Login");
                options.AccessDeniedPath = new PathString("/Errors/ClientError");//资源未通过任何授权策略授权,禁止访问路径
                options.LogoutPath = new PathString("/Account/Logout");
                options.Events.OnRedirectToAccessDenied = context =>
                {
                    context.Response.StatusCode = 403;//如果此处不这样处理,则当出现403无授权的错误时候,则会重定向到/Errors/ClientError 而重定向后Http状态码为200,而不是我们需要的403了
                    return Task.CompletedTask;
                };
                options.Cookie.Name = ".AspNet.SharedCookie";//设置统一的Cookie名称
                //options.Cookie.Domain = "ZKHK.com.cn";//设置Cookie的域为根域,这样所有子域都可以发现这个Cookie
                options.Cookie.Path = "/";
            });
            services.AddRazorPages().AddFriendlyException().AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();//首字母小写
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //避免循环引用
                options.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
            });
            services.AddControllersWithViews().AddInjectWithUnifyResult().AddRazorRuntimeCompilation().AddAppLocalization();//视图预编译、动态编译,及新增语言全球化
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Errors/ServerError");
                app.UseStatusCodePagesWithRedirects("/Errors/ClientError?code={0}");
            }
            app.UseHsts();
            app.UseCorsAccessor();
            //app.UseHttpsRedirection(); //强制使用HTTPS ,它会将HTTP转换成HTTPS
            app.UseAppLocalization();
            app.UseStaticFiles();
            app.UseSerilogRequestLogging();    // Serilog日志必须在 UseStaticFiles 和 UseRouting 之间
            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseInject();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");

                endpoints.MapRazorPages();
            });
        }
    }
}

数据库上下文

    /// 
    /// MyKeysContext库上下文,AddDataProtection数据保护,将保护秘钥存储在数据库中,就必须实现IDataProtectionKeyContext接口
    /// 
    public class MyKeysContext : DbContext, IDataProtectionKeyContext
    {
        // A recommended constructor overload when using EF Core 
        // with dependency injection.
        public MyKeysContext(DbContextOptions options)
            : base(options) { }

        // This maps to the table that stores keys.
        public DbSet DataProtectionKeys { get; set; }
    }

你可能感兴趣的:(认证与授权,json)