花了几天的时间并尝试了社区推荐的各种解决方案后,我仍然找不到解决此问题的方法。
我有多个应用程序需要实现单点登录。所有的应用程序都有两个项目。前端应用程序和后端应用程序。前端应用程序是用ReactJS编写的,后端应用程序是.Net核心2.2编写的。所有应用程序都托管在Azure应用程序服务中。
例如,用户身份验证系统具有两个应用程序 authweb.mydomain.org (ReactJS)和 authbackend.mydomain.org 强大>(。Net核心)。所有其他应用程序都应通过该应用程序进行实例身份验证,app1具有两个Web应用程序 app1web.mydomain.org 和 app1backend.mydomain.org < / em>
我选择了cookie身份验证方法来实现此单点登录(不确定这是此方案的最完美选择)。用户使用其用户名和密码登录auth应用程序( authweb.mydomain.org )。然后backend( 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访问 app1web.mydomain.org 。当我打开 app1web.mydomain.org 时,这些cookie在浏览器cookie部分中是apprar。此应用程序在后端( 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 App Services时,它可以与localhost正常工作,但不能对app1进行身份验证。请有人向我解释我在这里错过的事情。非常感谢您的帮助。