0

在花了几天时间尝试了社区推荐的各种解决方案之后,我仍然找不到解决这个问题的方法。
我有多个应用程序需要实现单点登录。所有的应用程序都有两个项目。前端应用程序和后端应用程序。前端应用程序是用 ReactJS 编写的,后端是用 .Net core 2.2 编写的。所有应用程序都托管在 Azure 应用服务中。例如,用户身份验证系统有两个应用程序authweb.mydomain.org (ReactJS) 和authbackend.mydomain.org (.Net Core)。对于一个实例,所有其他应用程序都应通过此应用程序进行身份验证,app1 有两个 Web 应用程序app1web.mydomain.orgapp1backend.mydomain.org
我选择了 cookie 身份验证方法来实现这个单点登录(不确定这是这个 scnario 的最完美选择)。用户使用他/她的用户名和密码登录到身份验证应用程序 ( authweb.mydomain.org )。然后后端(authbackend.mydomain.org)验证用户并在凭据有效时生成身份验证 cookie。这里我就不提我的ReactJs前端的源码了

authbackend.mydomain.org StartUp.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDataProtection()
       .SetApplicationName("SharedCookieApp");

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
        })
        .AddCookie("Cookies", options =>
        {
            options.Cookie.Name = "auth_cookie";
            options.Cookie.SameSite = SameSiteMode.None;
            options.LoginPath = "/Account/Login/";
            options.LogoutPath = "/Account/Logout/";
            options.Cookie.Domain = ".mydoamin.org";
            options.Events = new CookieAuthenticationEvents
            {
                OnRedirectToLogin = redirectContext =>
                 {
                     redirectContext.HttpContext.Response.StatusCode = 401;
                     return Task.CompletedTask;
                 }
            };
            //options.DataProtectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@"c:\shared-auth-ticket-keys\"));
        });

        services.AddHttpContextAccessor();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        services.AddCors(options =>
        {
            options.AddPolicy("AllowSpecificOrigin",
                builder => builder.AllowAnyHeader().AllowAnyMethod().SetIsOriginAllowed(_ => true).AllowCredentials());
        });
    }

    // 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.UseCors("AllowSpecificOrigin");
        app.UseAuthentication();

        app.UseMvc();
    }
}

authbackend.mydomain.org AccountController.cs 对用户进行身份验证

[EnableCors("AllowSpecificOrigin")]
[Route("[controller]/[action]")]
[ApiController]
public class AccountController : ControllerBase
{
    [HttpPost]
    [AllowAnonymous]
    public async Task<UserObject> Login([FromBody] UserLogin user)
    {
        try
        {
            if(user.UserName=="demo" && user.Password == "demo")
            {
                UserObject loggedInUser = UserObject.GetUser();

                var identity = new ClaimsIdentity("Cookies");
                identity.AddClaim(new Claim(ClaimTypes.Name, loggedInUser.UserName));
                identity.AddClaim(new Claim(ClaimTypes.GivenName, loggedInUser.FirstName));
                identity.AddClaim(new Claim(ClaimTypes.Surname, loggedInUser.LastName));
                var principal = new ClaimsPrincipal(identity);
                await HttpContext.SignInAsync("Cookies",principal);

                return loggedInUser;
            }
            return null;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    [HttpPost]
    public async Task<bool> Logout()
    {
        await HttpContext.SignOutAsync();
        return true;
    }
}

一旦用户登录到 auth 应用程序,就会生成 auth cookie,并将用户重定向到 auth 应用程序的主页

authbackend.mydomain.org HomeController.cs

[Authorize(AuthenticationSchemes= "Cookies")]
[EnableCors("AllowSpecificOrigin")]
[Route("[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
    public string Index()
    {
        var usr = User;
        var cookie = Request.Cookies;
        var headerCookie = Request.HttpContext.Request.Cookies;

        return "User is authenticated";
    }
}

Cookie 按预期生成
在此处输入图像描述

现在用户想要使用相同的身份验证 Cookie访问app1web.mydomain.org 。当我打开app1web.mydomain.org时,这些 cookie 在浏览器 cookie 部分中显示。此应用程序在其后端 ( app1backend.mydomain.org ) 中验证用户,以确保用户已通过身份验证。
app1backend.mydomain.org Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDataProtection()
       //.PersistKeysToFileSystem(new DirectoryInfo(@"c:\shared-auth-ticket-keys\"))
       .SetApplicationName("SharedCookieApp");

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = "Cookies";
        })
        .AddCookie("Cookies", options =>
        {
            options.Cookie.Name = "auth_cookie";
            options.Cookie.SameSite = SameSiteMode.None;
            options.LoginPath = "/Account/Login/";
            options.LogoutPath = "/Account/Logout/";
            options.Cookie.Domain = ".mydomain.org";
            options.Events = new CookieAuthenticationEvents
            {
                OnRedirectToLogin = redirectContext =>
                {
                    redirectContext.HttpContext.Response.StatusCode = 401;
                    return Task.CompletedTask;
                }
            };

        });



        services.AddHttpContextAccessor();

        services.AddCors(options =>
        {
            options.AddPolicy("AllowSpecificOrigin",
                builder => builder.AllowAnyHeader().AllowAnyMethod().SetIsOriginAllowed(_ => true).AllowCredentials());
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // 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.UseCors("AllowSpecificOrigin");
        app.UseAuthentication();

        app.UseMvc();

    }
}

app1backend.mydomain.org HomeController.js

[Authorize(AuthenticationSchemes = "Cookies")]
[EnableCors("AllowSpecificOrigin")]
[Route("[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
    [HttpGet]
    public string Index()
    {
        var usr = User;
        var cookie = Request.Cookies;
        var headerCookie = Request.HttpContext.Request.Cookies;
        return Request.HttpContext.Request.Cookies["auth_cookie"];
    }
}

当我调用上面的 Index 方法时,401-Unauthorized 从后端返回。但是 cookie 正在传递到后端。
当我将应用程序托管到 Azure 应用服务时,这在 localhost 上运行良好,但没有对 app1 进行身份验证。请有人解释一下我在这里错过了什么。非常感谢您的帮助。

4

0 回答 0