我正在使用HMACSHA256在Web场环境中进行消息身份验证.
在web-farm中,每台机器都有相同的机器密钥,因此ViewState可以跨机器工作,但是,我需要进行跨机器的HMAC消息认证,所以我认为由于所有机器都使用相同的机器密钥,因此应该是一种从中导出密钥以用作HMAC密钥的方法.
我注意到.NET 4.0中有MachineKey类,但是,我仍然坚持使用.NET 3.5,这对我来说是不可用的.
有没有办法在所有机器上获得一个相同的排序键而不生成我自己的,在ASP.NET 3.5环境中使用?
我实际上并不需要机器密钥本身,只需要从机器密钥(或等效的)派生的验证密钥.
我想从我的ASP.Net MVC 5(.Net 4.5.1,本地托管在iisexpress上,从Visual Studio运行)传递身份验证cookie到我的WCF服务(.Net 4.5.1,在本地托管在WcfSvcHost上,从中运行) Visual Studio解决方案)并在那里解密.我已将两者配置为使用相同的机器密钥(ASP的Web.config,WCF的App.config):
<machineKey validationKey="930681CA8CDC1BC09118D6B37E4A1B7712CEDBBD9FA1E35407EA1CD440C7E6F2DB9E93DADAC4098F90ACC7417DBE57C196722FC67F313A6AAE0F946E2FF731B6" decryptionKey="714C9581DA522C636B2D97D80276D5ACC02C274A11ABF117C76181B0480D4AEA" validation="SHA1" decryption="AES" />
Run Code Online (Sandbox Code Playgroud)
两者都引用相同的System.Web.dll:
C:\ Program Files(x86)\ Reference Assemblies\Microsoft\Framework.NETFramework\v4.5.1\System.Web.dll(v4.0.30319)
但是当我尝试将cookieString传递给我的服务并调用时
FormsAuthenticationTicket tick = FormsAuthentication.Decrypt(cookieString);
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
无法验证数据
我反过来尝试了(在WCF服务上生成假票并在ASP网站上解密),这也没有用.我可以在ASP网站上生成一张票并在那里解密就好了.我也可以在服务上生成一张票,并在那里解密它没有任何问题.
var t1 = new FormsAuthenticationTicket("foo", false, 1337);
var cookie = FormsAuthentication.Encrypt(t1);
var t2 = FormsAuthentication.Decrypt(cookie);
Run Code Online (Sandbox Code Playgroud)
我还制作了一个小型控制台应用程序,在那里创建了一个票证,并在WCF服务上解密,没有任何问题.
因此,似乎ASP网站不使用指定的密钥来加密或解密数据.
有谁知道我能做些什么来解决这个问题?
编辑:我按照本指南获取cookie并将其传递给我的服务. http://thoughtorientedarchitecture.blogspot.de/2009/10/flowing-aspnet-forms-authentication.html
然而,正如我所说,我试图复制加密cookie的价值并在一个简单的控制台应用程序中使用相同的机器密码解密它,它不起作用.
即使我在本地主机上运行,我的 mvc 网站也给了我这个错误:
无法解密防伪令牌。如果此应用程序由 Web 场或群集托管,请确保所有计算机都运行相同版本的 ASP.NET 网页,并且配置指定显式加密和验证密钥。AutoGenerate 不能在集群中使用。
我使用了这个机器密钥:
<machineKey compatibilityMode="Framework20SP1" validationKey='AC0DA63E787522E3BA5D47D8FA0A46EB68BB89A35C6353D5E8D3D5CA416D0DA607E56C6D0861ED3B7194C3ED74C0CE79FE4CE2909F34A6CFBDE134C1A094CA40' decryptionKey='A68360896EF374401123C6C222A7AAD8D430DB4DE34938E1' validation='SHA1'/>
Run Code Online (Sandbox Code Playgroud)
但是还是没有用。另外,我从第三方提取了这个machinekey。我知道它不安全,但微软的方式太复杂了:使用 powershell 生成它?复杂的。然后用IIS?我的 IIS8 没有显示 machinekey 模块。所有这些东西到底是怎么回事。
好的,可能错误是由多个@html.antiforgerytoken 引起的。好吧,我确实有两个 antiforgerytoken,但是当我删除其中一个时,错误仍然存在。
我对这个问题感到非常沮丧。我希望有人会善意地提供帮助。相信那些MVC用户在开发MVC网站的时候也遇到过这种情况。就我而言,我只是一个新手,这是我部署的第一个 MVC 网站。
谢谢你的帮助
更新
控制器:
// POST: /Account/Manage
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Manage(ManageUserViewModel model)
{
bool hasPassword = HasPassword();
ViewBag.HasLocalPassword = hasPassword;
ViewBag.ReturnUrl = Url.Action("Manage");
if (hasPassword)
{
if (ModelState.IsValid)
{
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
if (result.Succeeded)
{
return RedirectToAction("Manage", new { Message = ManageMessageId.ChangePasswordSuccess });
}
else
{
AddErrors(result); …Run Code Online (Sandbox Code Playgroud) 我使用该MachineKey.Protect()方法来加密在我的asp.net MVC应用程序中作为查询字符串传递的id.
这是我用来加密/解密的代码:
public static string Encrypt(this string expression)
{
if (string.IsNullOrEmpty(expression))
return string.Empty;
byte[] stream = Encoding.Unicode.GetBytes(expression);
byte[] encodedValue = MachineKey.Protect(stream);
return HttpServerUtility.UrlTokenEncode(encodedValue);
}
public static string Decrypt(this string expression)
{
if (string.IsNullOrEmpty(expression))
return string.Empty;
byte[] stream = HttpServerUtility.UrlTokenDecode(expression);
byte[] decodedValue = MachineKey.Unprotect(stream);
return Encoding.Unicode.GetString(decodedValue);
}
Run Code Online (Sandbox Code Playgroud)
而且,这是MachineKey我web.config文件中的元素:
<system.web>
.
.
.
<machineKey validationKey="xxx" decryptionKey="xxx" validation="SHA1" decryption="AES" />
</system.web>
Run Code Online (Sandbox Code Playgroud)
问题是加密的id不是持久的.每当我调用该方法时,我都会得到一个新的加密表达式.我如何让它持久?
在asp.net中哪个更好用于MachineKey for 3.5 framework?
那是什么原因?
是的,关于这个特定错误有一百万个问题和线索,有许多记录良好的解决方案,我一定会尝试.但首先我想了解我的特定情况/环境的问题.
在我的情况下,这个错误似乎是完全随机的.我会在几周内没有看到它,然后有一天我会登录我的网站并得到错误.刷新页面,再次登录,没问题.在事件之间的这些时段中,Web服务器没有发生任何特别的特殊情况.
这是另一回事,错误说"如果此应用程序由Web场或群集托管......",但事实并非如此.它只是一个Windows Server 2008.
所以,我理解一般的解决方案是在web.config文件中添加一组静态机器密钥---但为什么这似乎是随机发生的,为什么它发生在我的站点上,它位于单个Windows Server 2008上机?
我正在使用ASP.NET 4,我的站点是在IIS上运行的Web应用程序.
错误信息:
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that <machineKey> configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪:
[ViewStateException: Invalid viewstate.
Client IP: ##::##:##:##:##
Port: ##
Referer: http://myserver/login.aspx
Path: /login.aspx
User-Agent: Opera/9.80 (Windows NT 6.1; WOW64; U; en) Presto/2.10.289 Version/12.01
ViewState: /wEPDw...6OCX]
[HttpException (0x80004005): Validation of viewstate MAC failed. If this application …Run Code Online (Sandbox Code Playgroud) 由于Auto-Scaling不允许缓冲时间和/或不够智能,不允许只有"新请求"进入由于自动缩放而被安排关闭的实例,我试图避免使用粘性 - ELB提供的会议.否则,此行为将使一些客户具有登录屏幕.
该网站和其他RESTful Web服务正在IIS7中运行.该网站使用基于经典表单的身份验证(MVC3中的内置成员资格提供程序),但很快将迁移到自定义成员资格提供程序以查看cookie并解密然后给出判决.RESTful Web服务已经在使用自定义成员资格提供程序.
在这种情况下,我认为对于我不能通过其ELB使用粘性会话而无法获得的网站.
RESTful Web服务的ELB可以配置为非粘性,因为它们会在每个请求上单独观察cookie,以查看auth令牌是否存在某些加密值.但是,这里的问题是FormsAuthentication.Enrypt和FormsAuthentication.Decrypt方法,它们使用MachineKeys.对 ?!如果没有,那么它没有问题,但如果他们这样做,那么如何在EC2中的自动标量实例之间同步机器密钥?
我的问题的部分答案似乎分布在多个帖子中,但到目前为止,将其放在一起对我来说还没有奏效,所以我希望当这篇文章得到解答时,它将形成更完整的指南
我有一个 ASP.NET Webforms 应用程序 (W1),我想在一段时间内开始升级到单独的 MVC 应用程序 (M1)。包含W1的解决方案已升级到4.5,并在解决方案中创建了M1。W1 使用 ASP.Net 会员框架。
在M1中,我将Authorize属性添加到HomeController中的About页面
[Authorize]
public ActionResult About()
我在 M1 中添加了一个指向“关于”页面的链接,该链接源自 W1 中要求用户登录的页面。
我希望用户能够登录到 W1,单击指向 M1 关于页面的链接并自动登录到 M1。
我已使用此处概述的方法从 W1 中提取了validationKey 和decryptionKey 。尽管这似乎是一个合乎逻辑的步骤,但我不确定是否需要这样做,因为不同的密钥仍然允许用户登录 W1。
第2步按照此处和此处的信息,并经过大量调试后,我修改了项目的 Web.config 文件部分,如下所示;
对于 W1:
<system.web>
<authentication mode="Forms">
<forms name="WRSAUTH"
loginUrl="~/Account/Login.aspx"
defaultUrl="Default.aspx"
protection="All"
timeout="60"
path="/"
domain=".localhost"
requireSSL="false"
slidingExpiration="true"
cookieless="UseCookies"
enableCrossAppRedirects="false" />
</authentication>
<machineKey validationKey="<ValidationKey>"
decryptionKey="<DecryptionKey>"
validation="SHA1"
decryption="AES"/>
<compilation debug="true" targetFramework="4.5">
<httpRuntime maxRequestLength="12288" />
</system.web>
Run Code Online (Sandbox Code Playgroud)
对于 M1:
<system.web> …Run Code Online (Sandbox Code Playgroud) 如果您使用Azure网站自动缩放,是否需要设置计算机密钥,以便加密的身份验证令牌可以在计算机之间共享?
这里有一个问题似乎与 我要问的问题相同.但是,该问题涉及Azure Web角色.我问的是Azure网站.
我有一个 ASP.NET 4.6 Web API 服务作为 Azure 应用服务在单个区域的单个应用服务计划中运行。我们正在修改此服务,使其部署在多个区域,并在前面有一个负载均衡器,每个区域都有自己的应用服务计划。因此,我们需要确保在每个应用服务计划上使用相同的计算机密钥,以防止用户在负载均衡器将其定向到不同的服务器时注销。
我们的应用程序已经使用 Azure 在单个应用服务计划上自动提供的机器密钥运行了一段时间。为了避免导致所有客户在过渡期间注销,我计划提取此现有计算机密钥,然后将其部署到其他区域的新应用程序服务计划上。听起来很简单,对吧?
然而提取这个密钥被证明是一个挑战。
我已经尝试过此处列出的解决方案:获取当前的 ASP.NET 计算机密钥
虽然每种方法确实返回某种密钥,但该密钥似乎与实际用于生成不记名令牌或保护刷新令牌票证的密钥不匹配。当我将这些密钥部署到其他服务器时,不记名令牌仍然被视为无效,并且尝试使用现有刷新令牌会导致响应invalid_grant。
此外,即使我在 web.config 中手动设置机器密钥(或在运行时使用此类代码),提取的机器密钥也不会与我手动设置的机器密钥匹配,这提供了进一步的证据,表明它们是什么返回的不是实际使用的机器密钥。在我的本地开发计算机和 Azure 中都是如此。
作为参考,这是我用来以三种不同方式提取解密和验证密钥的代码(删除了一些安全密码):
[DllImport(@"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll")]
internal static extern int EcbCallISAPI(IntPtr pECB, int iFunction, byte[] bufferIn, int sizeIn, byte[] bufferOut, int sizeOut);
[Route("machine-key-test")]
public async Task<JObject> GetMachineKeys()
{
return new JObject(
new JProperty("A", GetAdminData()),
new JProperty("B", GetAdminDataNoIsolateApps()),
new JProperty("C", GetAdminDataPre45()));
JObject GetAdminData()
{
string appPath = "/";
byte[] genKeys = new byte[1024];
byte[] autogenKeys = new byte[1024];
int …Run Code Online (Sandbox Code Playgroud) asp.net machinekey azure-app-service-plans azure-web-app-service
machinekey ×10
asp.net ×5
c# ×4
asp.net-mvc ×2
encryption ×2
amazon-ec2 ×1
autoscaling ×1
azure ×1
exception ×1
hmac ×1
viewstate ×1
wcf ×1
web-farm ×1