gpt4 book ai didi

c# - 创建的 CookieAuthentication cookie 的内容?

转载 作者:行者123 更新时间:2023-11-30 15:54:34 25 4
gpt4 key购买 nike

简短版:有没有办法确定由 .net-Core-2 中的 CookieAuthentication 机制创建的 cookie 的内容

上下文:
我目前正在努力使网站符合 GDPR,这意味着记录我们网站上使用和设置的所有 cookie。我们使用 asp.net core 2 和 Identity 来处理用户登录和注销。问题是所有由身份设置的 cookie 以及如何记录它们。 cookies 1.

  • AspNetCore.Identity.Application

这个 cookie 很简单,它包含登录信息、权限等。如果您删除它,您将从我们的网站注销。它对我们的应用程序至关重要,因此无需担心。

问题是下面的cookie(注意,是一个cookie分成三部分)

  • AspNetCore.Cookies
  • AspNetCore.CookiesC1
  • AspNetCore.CookiesC2

它由 cookieAuthentication 使用和设置,但实际上似乎没有做任何事情。您可以从浏览器中删除它们,并且仍然可以正常使用该网站。例如进行更改并保存 i,您将不会被强制注销。

这带来了一个问题,因为根据新的 GDPR 法律,如果这些 cookie block 是可选的,用户应该能够停用它们。 (后面的问题)

问题就变成了:我怎样才能知道这个 cookie 做了什么以及它包含什么信息。两者同样重要。

尝试过的方法:我试图通过查看源代码来寻找答案,但项目开发在过去的 2 年里断断续续,因此相当拼凑。我还尝试使用这篇文章解密 cookie How to manually decrypt an ASP.NET Core Authentication cookie?作为指南,但我只用 C# 开发了不到 4 个月,所以我无法让它工作,因为它似乎针对的是较旧/不同版本的 .net-core。

注意!由于这是我在堆栈上提出的第一个问题,我欢迎就如何使我的问题更清晰或对本网站的普通民众更有用提出建议和提示。

编辑_1:好吧,启动文件中确实没有太多配置

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true
});

有一些代码可以通过 Microsoft 启用 OpenId。但是会放在这个 cookie 中吗?

// Configure the OWIN Pipeline to use OpenId Connect Authentication
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = Configuration["ClientId"],
Authority = string.Format(Configuration["AadInstance"],
Configuration["Tenant"]),
PostLogoutRedirectUri = Configuration["PostLogoutRedirectUri"],
ClientSecret = Configuration["ClientSecret"],
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false
},
Events = new OpenIdConnectEvents
{
OnAuthenticationFailed = OnAuthenticationFailed,
OnRedirectToIdentityProvider = (context) =>
{
if (context.HttpContext.Request.Query.ContainsKey("domain"))
{
context.ProtocolMessage.DomainHint =
context.HttpContext.Request.Query["domain"];
}

return Task.FromResult(0);
},
OnTokenValidated = OnTokenValidated
}
});

edit_2:删除了 DI 和杂项日志记录,但这基本上是整个文件

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json.Serialization;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

public class Startup
{
public UserManager<ApplicationUser> UserManager { get; set; }
public SignInManager<ApplicationUser> SignInManager { get; set; }
public IConfigurationRoot Configuration { get; set; }

public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);

if (env.IsDevelopment())
{
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets<Startup>();
}

builder.AddEnvironmentVariables();
Configuration = builder.Build();
}


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Adds a default in-memory implementation of IDistributedCache
services.AddMemoryCache();

services.AddSession();

services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddHangfire(x => x.UseSqlServerStorage(Configuration.GetConnectionString("DefaultConnection")));

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddIdentity<ApplicationUser, IdentityRole>(o => {
// configure identity options
o.Password.RequireDigit = true;
o.Password.RequireLowercase = true;
o.Password.RequireUppercase = true;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 8;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, options => options.ResourcesPath = "Resources")
.AddDataAnnotationsLocalization()
.AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});

// OpenID Connect Authentication Requires Cookie Auth
services.AddAuthentication(options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public async void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
SampleDataInitializer sampleData,
SeedData seedData)
{
app.UseSession();

if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();

try
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
.CreateScope())
{
serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
.Database.Migrate();
}
}
catch { }
}
else
{
app.UseExceptionHandler("/Home/Error");

// For more details on creating database during deployment see http://go.microsoft.com/fwlink/?LinkID=615859
try
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
.CreateScope())
{
serviceScope.ServiceProvider.GetService<ApplicationDbContext>()
.Database.Migrate();
}
}
catch { }
}

app.UseStaticFiles();
app.UseIdentity();

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true
});

// Configure the OWIN Pipeline to use OpenId Connect Authentication
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = Configuration["ClientId"],
Authority = string.Format(Configuration["AadInstance"], Configuration["Tenant"]),
PostLogoutRedirectUri = Configuration["PostLogoutRedirectUri"],
ClientSecret = Configuration["ClientSecret"],
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false
},
Events = new OpenIdConnectEvents
{
OnAuthenticationFailed = OnAuthenticationFailed,
OnRedirectToIdentityProvider = (context) =>
{
if (context.HttpContext.Request.Query.ContainsKey("domain"))
{
context.ProtocolMessage.DomainHint = context.HttpContext.Request.Query["domain"];
}

return Task.FromResult(0);
},
OnTokenValidated = OnTokenValidated
}

});

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

await seedData.SeedBuyOutPoliciesForDepartments();
}


private async Task<Task> OnTokenValidated(TokenValidatedContext context)
{
try
{
// Get tenant Id from Claims
var claim = context.Ticket.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid");

if (claim?.Value == null)
{
context.HttpContext.Session.SetError("Not able to access tenant id from claim");
return Task.FromResult(true);
}

var tenantId = claim.Value;

var roleClaims = context.Ticket.Principal.Claims.Where(c => c.Type.ToLower().EndsWith("identity/claims/role")).ToList();

//// Get group claims from logged in user
var groupClaims = context.Ticket.Principal.Claims.Where(c => c.Type.ToLower() == "groups").ToList();

var checkClaim = context.HttpContext.Session.GetString("CheckClaim");

if (!string.IsNullOrEmpty(checkClaim))
{
context.HttpContext.Session.Remove("CheckClaim");

var claimInfo = "";

foreach (var currentUserClaim in context.Ticket.Principal.Claims)
{
claimInfo += $"Type: {currentUserClaim.Type} Value: {currentUserClaim.Value} <br/>";
}

// Add groups to claimInfo string
claimInfo += "<br/>Groups: <br/>";
foreach (var groupClaim in groupClaims)
{
claimInfo += $"{groupClaim.Value}, ";
}

// Add role(s) to claimInfo string
claimInfo += "<br />Roles: <br />";
foreach (var roleClaim in roleClaims)
{
claimInfo += $"{roleClaim.Value}, ";
}

context.HttpContext.Session.SetString("Claim", claimInfo);

return Task.FromResult(true);
}

var applicationDbContext = context.HttpContext.RequestServices.GetService<ApplicationDbContext>();

// Check that tenant id exist in database
var customer = applicationDbContext.Customers.Include(c => c.Departments).FirstOrDefault(x => x.TenantId == tenantId);
if (customer == null)
{
context.HttpContext.Session.SetError("Your company is not configured to use log in with work account");
return Task.FromResult(true);
}

// Used to find user in database or create new user
var userManager = context.HttpContext.RequestServices.GetService<UserManager<ApplicationUser>>();

//// Used to update user role
var roleManager = context.HttpContext.RequestServices.GetService<RoleManager<IdentityRole>>();

// Get email adress from AD user
var email = context.Ticket.Principal.Identity.Name;

// Check if user exist in database
var user = await applicationDbContext.Users.Include(u => u.Department).FirstOrDefaultAsync(u => u.Email == email);


if (user == null)
{
if (!customer.AllowCreateUserOnSignIn)
{
context.HttpContext.Session.SetError(
"Your user does not exist in the portal and your company is not configured to allow creation of user on sign in. Please contact your administrator.", customer.ErrorText);

return Task.FromResult(true);
}

// Create new user with AdUser property set to true
var givenName =
context.Ticket.Principal.Claims.FirstOrDefault(
x => x.Type.ToLower().Contains("givenname"));
var surName =
context.Ticket.Principal.Claims.FirstOrDefault(
x => x.Type.ToLower().Contains("surname"));

user = new ApplicationUser
{
AdUser = true,
UserName = email,
Email = email,
FirstName = givenName != null ? givenName.Value : "",
LastName = surName != null ? surName.Value : "",
};

if (user.DepartmentId == null)
{
user.DepartmentId = customer.Departments.FirstOrDefault(d => d.Default)?.Id;
}

// Add user to database
var result = await userManager.CreateAsync(user);

if (!result.Succeeded)
{
context.HttpContext.Session.SetError(
"Your user does not exist in the portal. Please contact your administrator", customer.ErrorText);
return Task.FromResult(true);
}
}
else
{
//Not allowed to login if user is deactivated/resigned
if (user.ResignedDate != null)
{
context.HttpContext.Session.SetError("Your user is deactivated. Please contact your administrator", customer.ErrorText);
return Task.FromResult(true);
}
}

// Compare tenant id with user tenant
var userCustomer = await applicationDbContext.Customers.FirstOrDefaultAsync(c => c.Id == user.Department.CustomerId);
if (userCustomer == null || userCustomer.TenantId != tenantId)
{
context.HttpContext.Session.SetError("Your user does not exist in the portal. Please contact your administrator", customer.ErrorText);
return Task.FromResult(true);
}

// Sign in user
var signInManager = context.HttpContext.RequestServices.GetService<SignInManager<ApplicationUser>>();
await signInManager.SignInAsync(user, true);
}
catch (Exception ex)
{
context.HttpContext.Session.SetError("Sorry, an error occured during log in. Please contact your administrator");
}

return Task.FromResult(0);
}

// Entry point for the application.
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

host.Run();
}
}

最佳答案

如果存储的 Principal 对于单个 cookie 来说太大(考虑很多角色或声明),您将得到一个分块 cookie。 Cookie 的大小有限,因此分块将启动以允许主体的完全序列化。

在 ASP.NET Core 中使用 OAuth/OIDC/WS-Fed 时,是的,通常它会序列化为 cookie 身份验证 cookie,以便跨请求保存。 OAuth 可以在其结果中隐藏大量声明,因此您可以使用分块 cookie。

所以它真的是一个大 cookies ,分为多个部分,都是同一个 cookies 。因此,当涉及到您的网站按预期运行时,它们不是可选的。 (这不是 GDPR 的法律建议,需要来自实际律师)。

顺便说一句,ASP.NET Core 2.1 支持可选 cookie,您可以将 cookie 标记为必需或不需要(Cookie 身份验证将其 cookie 标记为必需),除非用户同意,否则 ASP.NET 不会写入可选 cookie供他们使用。

关于c# - 创建的 CookieAuthentication cookie 的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50130589/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com