让我们考虑一个常见的 ASP.NET Core 场景。首先,我们添加中间件:
public void Configure(IApplicationBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "MyCookie",
CookieName = "MyCookie",
LoginPath = new PathString("/Home/Login/"),
AccessDeniedPath = new PathString("/Home/AccessDenied/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
//...
}
然后序列化一个主体:
await HttpContext.Authentication.SignInAsync("MyCookie", principal);
这两个调用之后,将在客户端存储一个加密的cookie。你可以在任何浏览器开发工具中看到cookie(在我的情况下是分块的):
从应用程序代码中处理cookie不是问题(也不是问题)。
我的问题是:如何在应用程序外解密cookie?我猜需要一个私钥,怎么获取它?
我查看了文档,只发现了普通的单词:
这将创建一个加密的cookie并将其添加到当前响应中。在配置期间指定的AuthenticationScheme在调用SignInAsync时也必须使用。
底层使用的加密是ASP.NET的数据保护系统。如果您在多台机器上托管、负载平衡或使用Web Farm,则需要配置数据保护以使用相同的密钥环和应用程序标识符。
那么,是否可能解密身份验证cookie?如果可以,如何解密?
更新#1:基于Ron C的很好的答案和评论,我最终得到了这段代码:
public class Startup
{
//constructor is omitted...
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection().PersistKeysToFileSystem(
new DirectoryInfo(@"C:\temp-keys\"));
services.AddMvc();
}
public void Configure(IApplicationBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationScheme = "MyCookie",
CookieName = "MyCookie",
LoginPath = new PathString("/Home/Index/"),
AccessDeniedPath = new PathString("/Home/AccessDenied/"),
AutomaticAuthenticate = true,
AutomaticChallenge = true
});
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
}
public class HomeController : Controller
{
public async Task<IActionResult> Index()
{
await HttpContext.Authentication.SignInAsync("MyCookie", new ClaimsPrincipal());
return View();
}
public IActionResult DecryptCookie()
{
var provider = DataProtectionProvider.Create(new DirectoryInfo(@"C:\temp-keys\"));
string cookieValue = HttpContext.Request.Cookies["MyCookie"];
var dataProtector = provider.CreateProtector(
typeof(CookieAuthenticationMiddleware).FullName, "MyCookie", "v2");
UTF8Encoding specialUtf8Encoding = new UTF8Encoding(false, true);
byte[] protectedBytes = Base64UrlTextEncoder.Decode(cookieValue);
byte[] plainBytes = dataProtector.Unprotect(protectedBytes);
string plainText = specialUtf8Encoding.GetString(plainBytes);
return Content(plainText);
}
}
很不幸,这段代码在调用Unprotect
方法时总是产生异常:
Microsoft.AspNetCore.DataProtection.dll中的CryptographicException异常: 附加信息:有效载荷无效。
我在几台机器上测试了这个代码的不同变化,但没有得到积极的结果。可能是我的错误,但是错在哪里呢?
更新 #2:我的错误在于DataProtectionProvider
没有在UseCookieAuthentication
中设置。再次感谢@RonC。