• Asp.Net Core基于Cookie实现同域单点登录(SSO)


    在同一个域名下有很多子系统

    如:a.giant.com  b.giant.com   c.giant.com等

    但是这些系统都是giant.com这个子域。

    这样的情况就可以在不引用其它框架的情况下,直接基于Cookie实现同域单点登录SSO

    注:用ID4,OAuth,其它SSO框架也同样可以实现。本文不讨论。

    为了简单表示。在这里登录页只输入一个用户名,然后登录
    后台接收到登录名后,构建登录信息。然后登录
    代码如下:

        <form enctype="application/x-www-form-urlencoded" method="post">
            @if (!User.Identity.IsAuthenticated)
            {
                <div><label>用户名:<input type="text" name="UserName" /></label><button type="submit">登录</button></div>
            }
            else
            {
                <div><label>用户名:@User.Identity.Name</label><a href="/Home/SignOut">退出</a></div>
            }
        </form>
        public class HomeController : Controller
        {
            public IActionResult Index()
            {
                return View();
            }
            [HttpPost]
            public async Task<IActionResult> Index(string UserName)
            {
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, UserName)
                };
    
                var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
                return RedirectToAction("Index");
            }
            public async Task<IActionResult> SignOut()
            {
                await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
                return RedirectToAction("Index");
            }
        }
        public class Startup
        {
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
                services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_2);
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                app.UseAuthentication();
                app.UseMvcWithDefaultRoute();
            }
        }

    这样就可以实现一个子系统的简单登录,效果如下

    同样创建一个COM.WebB.SSO,写同样的代码实现登录。

    但是这样只能A站点登录A系统,B站点登录B系统。两个系统相互独立

    如果我们要实现aUser登录A系统后,B系统也自动登录aUser。

    那么就可做如下改造

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<SSOContext>(option => {
                    option.UseSqlServer(Configuration.GetConnectionString("SSO"));
                });
                services.AddDataProtection()
                    .PersistKeysToDbContext<SSOContext>()  //把加密数据保存在数据库
                    //.PersistKeysToFileSystem(new DirectoryInfo(@"\serversharedirectory"))  //把加密信息保存大文件夹
                    .SetApplicationName("SSO");  //把所有子系统都设置为统一的应用名称
    
                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,options=> {
                        options.Cookie.Name = ".AspNet.SharedCookie";//设置统一的Cookie名称
                        options.Cookie.Domain = ".giant.com";//设置Cookie的域为根域,这样所有子域都可以发现这个Cookie
                    });
                services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_2);
            }

    主要是增加了services.AddDataProtection配置
    其中,数据加密配置保存方式现阶段asp.net Core支持
    1。保存到文件:PersistKeysToFileSystem
    2。保存到数据库:PersistKeysToDbContext<Context>
    3。保存到Redis:PersistKeysToStackExchangeRedis
    4。保存到Azure:PersistKeysToAzureBlobStorage
    当然也可以自己实现存储方式,实现IXmlRepository

    我这里实现了保存到数据库,代码如下:

        public class SSOContext : DbContext, IDataProtectionKeyContext
        {
            public SSOContext(DbContextOptions<SSOContext> option)
                : base(option)
            { }
            public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
        }

    主要就是在DbContext基础上实现接口:IDataProtectionKeyContext

    这里修改配置主要统一了数据加密方式与统一应用名称
    这样其它子域的Cookie加密数据就能识别。

    再配置统一的Cookie名称与写的域名为根域。
    这样所有子域都能发现与识别此登录的Cookie信息
    这样就可以实现一个系统登录,其它子系统都登录
    一个子系统退出。其它子系统也都退出的功能

    源代码下载地址:https://github.com/GiantLiu/COM.SSO

  • 相关阅读:
    开始学习设计模式
    <转载>CCeButtonST v1.2
    CRITICAL_SECTION 学习
    简单工厂模式
    《转》Owner Draw Button StepbyStep
    低调 平和
    MFC RTTI (DECLARE_DYNAMIC 及IMPLEMENT_DYNAMIC 宏)
    为程序集延迟签名.
    NBear3.7 在 Suse11 下 的 MonoDevelop2(Alpha2)改造成功。
    Mono开发。
  • 原文地址:https://www.cnblogs.com/liuju150/p/10114778.html
Copyright © 2020-2023  润新知