我有一个webforms网站正在调用我们正在开发的新MVC6网站。用户将使用表单身份验证在webforms网站上一直登录,然后重定向到新的MVC6网站。我知道在MVC6中我应该使用Cookie身份验证,但无法让它解密cookie。我怀疑它是关于web.config和machinekey的变化,但我真的被卡住了。
这就是我所做的。
我已按如下方式设置了Cookie身份验证
app.UseCookieAuthentication(options =>
{
options.CookieName = "MyWebformsCookie";
options.AutomaticAuthenticate = true;
options.AuthenticationScheme = "Cookies";
options.TicketDataFormat = new MySecureDataFormat();
options.DataProtectionProvider = new MyDataProtectionProvider();
//options.CookieDomain = "localhost";
});
课程如下
public class MySecureDataFormat : ISecureDataFormat<AuthenticationTicket>
{
public string Protect(AuthenticationTicket data)
{
return string.Empty;
}
public string Protect(AuthenticationTicket data, string purpose)
{
return string.Empty;
}
public AuthenticationTicket Unprotect(string protectedText)
{
return null;
}
public AuthenticationTicket Unprotect(string protectedText, string purpose)
{
var ticket = FormsAuthentication.Decrypt(protectedText);
return null;
}
}
正在读取cookie,并且调用了Unprotect方法,但随后在FormsAuthentication.Decrypt方法上出现错误,错误
类型&#39; System.Web.HttpException&#39;的例外情况发生在System.Web.dll中但未在用户代码中处理
其他信息:无法验证数据。
Stack = at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(布尔 fEncrypt,Byte [] buf,Byte []修饰符,Int32 start,Int32 length, Boolean useValidationSymAlgo,Boolean useLegacyMode,IVType ivType, 布尔符号数据)at System.Web.Security.FormsAuthentication.Decrypt(字符串 encryptedTicket)at WebApplication.Mvc.MySecureDataFormat.Unprotect(String protectedText, 字符串目的) C:\ SVNCode \ GlobalConnectV2 \ WebApplication.Mvc \ Startup.cs:第153行 在 Microsoft.AspNet.Authentication.Cookies.CookieAuthenticationHandler.d__9.MoveNext()
所以这让我相信它不是阅读机器的关键。我在wwwroot文件夹中的web.config中有这个
<configuration>
<system.webServer>
...
</system.webServer>
<system.web>
<machineKey compatibilityMode="Framework20SP2" validation="SHA1" decryption="AES" validationKey="mykey" decryptionKey="dec" />
</system.web>
</configuration>
这适用于早期的MVC应用,但猜测MVC6中发生了一些变化。我也试过以下但没有运气
services.ConfigureDataProtection(configure =>
{
configure.UseCryptographicAlgorithms(new Microsoft.AspNet.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptionOptions()
{
EncryptionAlgorithm = Microsoft.AspNet.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = Microsoft.AspNet.DataProtection.AuthenticatedEncryption.ValidationAlgorithm.HMACSHA256
});
});
有什么建议吗?
答案 0 :(得分:11)
我没有尝试在ASP.NET 5应用程序中使用FormsAuthentication.Decrypt()
。
最后,我根据可用的文档编写了一个解密例程,并查看了Microsoft为系统Web提供的参考源代码。
解密使用SHA1进行验证的表单身份验证Cookie以及用于加密的AES所需的类可以在我的GIST中找到:https://gist.github.com/dazinator/0cdb8e1fbf81d3ed5d44
获得这些后,您可以像以前一样创建自定义TicketFormat:
public class FormsAuthCookieTicketFormat : ISecureDataFormat<AuthenticationTicket>
{
private LegacyFormsAuthenticationTicketEncryptor _Encryptor;
private Sha1HashProvider _HashProvider;
public FormsAuthCookieTicketFormat(string decryptionKey, string validationKey)
{
_Encryptor = new LegacyFormsAuthenticationTicketEncryptor(decryptionKey);
_HashProvider = new Sha1HashProvider(validationKey);
}
public string Protect(AuthenticationTicket data)
{
throw new NotImplementedException();
}
public string Protect(AuthenticationTicket data, string purpose)
{
throw new NotImplementedException();
}
public AuthenticationTicket Unprotect(string protectedText)
{
throw new NotImplementedException();
}
public AuthenticationTicket Unprotect(string protectedText, string purpose)
{
var ticket = _Encryptor.DecryptCookie(protectedText, _HashProvider);
var identity = new ClaimsIdentity("MyCookie");
identity.AddClaim(new Claim(ClaimTypes.Name, ticket.Name));
identity.AddClaim(new Claim(ClaimTypes.IsPersistent, ticket.IsPersistent.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Expired, ticket.Expired.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Expiration, ticket.Expiration.ToString()));
identity.AddClaim(new Claim(ClaimTypes.CookiePath, ticket.CookiePath));
identity.AddClaim(new Claim(ClaimTypes.Version, ticket.Version.ToString()));
// Add some additional properties to the authentication ticket.
var props = new AuthenticationProperties();
props.ExpiresUtc = ticket.Expiration.ToUniversalTime();
props.IsPersistent = ticket.IsPersistent;
var principal = new ClaimsPrincipal(identity);
var authTicket = new AuthenticationTicket(principal, props, CookieDetails.AuthenticationScheme);
return authTicket;
}
然后将其连线:
var formsCookieFormat = new FormsAuthCookieTicketFormat(_DecryptionKeyText, _ValidationKeyText);
app.UseCookieAuthentication(options =>
{
// shortened for brevity...
options.TicketDataFormat = formsCookieFormat ;
options.CookieName = "MyCookie";
});
答案 1 :(得分:3)
有whole section of documentation on docs.asp.net名为Replacing machineKey
。
它主要与包Microsoft.AspNet.DataProtection.SystemWeb
有关。
然后,您就可以在代码或配置中设置密钥,并且可以直接从asp.net-5读取这些Cookie。
以下是有关如何操作的代码示例(来自文档):
public override void ConfigureServices(IServiceCollection services)
{
services.ConfigureDataProtection(configure =>
{
configure.SetApplicationName("my-app");
configure.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\myapp-keys\"));
configure.ProtectKeysWithDpapi();
});
}
当然,您必须在依赖项列表中添加前面提到的包,这可能会迫使您使用Windows(不确定,但它确实在CoreClr中编译)。
这不适用于现有的machineKey,但它会生成一个新的设置,允许您从那里开始。
答案 2 :(得分:1)
当您对用户进行身份验证时,请将身份验证Cookie的域设置为二级域,即parent.com(您的asp.net端)。每个子域(MVC站点)将根据请求接收父域的cookie,因此可以对每个子域进行身份验证,因为您将使用共享身份验证cookie。
验证码:
System.Web.HttpCookie authcookie = System.Web.Security.FormsAuthentication.GetAuthCookie(UserName, False);
authcookie.Domain = "parent.com";
HttpResponse.AppendCookie(authcookie);
HttpResponse.Redirect(System.Web.Security.FormsAuthentication.GetRedirectUrl(UserName,
False));