使用防伪令牌模拟 Windows 用户
Impersonate Windows User with AntiForgery Tokens
我有两个网站 API;一种是 public 一种是内部的。我想让 public 一个与内部一个进行通信。但是,我想要内部安全层的两层安全性:
- Windows 身份验证(已完成)
- 防伪令牌(这是我遇到的问题)
现在我正在 public API:
中生成 AntiForgery
令牌
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
然后我在内部 API:
的过滤器中将它们拉下来
var request = actionContext.Request;
if (!request.RequestUri.PathAndQuery.StartsWith("/api"))
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
}
string cookieToken = "";
string formToken = "";
IEnumerable<string> tokenHeaders;
if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
{
string[] tokens = tokenHeaders.First().Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
try
{
AntiForgery.Validate(cookieToken, formToken);
}
catch (HttpAntiForgeryException ex)
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
这有点管用。我得到的错误是:
The provided anti-forgery token was meant for user "", but the current user is "WINDOWS8VM\Michael".
在生成令牌时,我需要以某种方式模拟Windows用户,以便用户的相同。
另一个问题是 CredentialCache.DefaultNetworkCredentials
是空的。这几乎可以肯定是因为 Windows public API 的身份验证没有打开。但是,应用程序池有一个身份,这就是我要寻找的身份。
因为您只想验证您的内部 api 是否由受信任的调用者调用(即 - public api)- 您不需要使用防伪令牌。相反,您可以使用 AF 令牌用于 encrypt\sign 您自己在 public api 的数据的相同机制,然后解密和验证此数据是您在内部 api 所期望的。为此,您可以使用 MachineKey.Protect and MachineKey.Unprotect 方法。
如果您这样做,请注意用于加密的密钥可能因应用程序而异。查看 machineKey 元素的描述,并注意 IsolateApps
设置的效果。如果您的机器密钥配置为 IsolateApps
- 一个 IIS 应用程序将无法解密受另一个应用程序保护的数据(使用 AF 令牌也是如此),即使它们都位于同一台机器上。
另请注意,如果在这方面没有隔离应用程序,则同一台计算机上的任何 IIS 应用程序都可以使用相同的密钥加密数据并调用您的内部 api。但是,如果您只想保护您的 api 不受网络中其他机器的影响 - 这应该足够了。
如果您不确定要加密哪些数据 - 合并来自请求本身的所有敏感数据,对其进行哈希处理并保护该哈希。然后在内部 api 合并相同的数据,对其进行哈希处理,取消保护从调用者收到的数据并确保未受保护的数据与目标哈希匹配。
我有两个网站 API;一种是 public 一种是内部的。我想让 public 一个与内部一个进行通信。但是,我想要内部安全层的两层安全性:
- Windows 身份验证(已完成)
- 防伪令牌(这是我遇到的问题)
现在我正在 public API:
中生成AntiForgery
令牌
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
然后我在内部 API:
的过滤器中将它们拉下来var request = actionContext.Request;
if (!request.RequestUri.PathAndQuery.StartsWith("/api"))
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
}
string cookieToken = "";
string formToken = "";
IEnumerable<string> tokenHeaders;
if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
{
string[] tokens = tokenHeaders.First().Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
try
{
AntiForgery.Validate(cookieToken, formToken);
}
catch (HttpAntiForgeryException ex)
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK));
这有点管用。我得到的错误是:
The provided anti-forgery token was meant for user "", but the current user is "WINDOWS8VM\Michael".
在生成令牌时,我需要以某种方式模拟Windows用户,以便用户的相同。
另一个问题是 CredentialCache.DefaultNetworkCredentials
是空的。这几乎可以肯定是因为 Windows public API 的身份验证没有打开。但是,应用程序池有一个身份,这就是我要寻找的身份。
因为您只想验证您的内部 api 是否由受信任的调用者调用(即 - public api)- 您不需要使用防伪令牌。相反,您可以使用 AF 令牌用于 encrypt\sign 您自己在 public api 的数据的相同机制,然后解密和验证此数据是您在内部 api 所期望的。为此,您可以使用 MachineKey.Protect and MachineKey.Unprotect 方法。
如果您这样做,请注意用于加密的密钥可能因应用程序而异。查看 machineKey 元素的描述,并注意 IsolateApps
设置的效果。如果您的机器密钥配置为 IsolateApps
- 一个 IIS 应用程序将无法解密受另一个应用程序保护的数据(使用 AF 令牌也是如此),即使它们都位于同一台机器上。
另请注意,如果在这方面没有隔离应用程序,则同一台计算机上的任何 IIS 应用程序都可以使用相同的密钥加密数据并调用您的内部 api。但是,如果您只想保护您的 api 不受网络中其他机器的影响 - 这应该足够了。
如果您不确定要加密哪些数据 - 合并来自请求本身的所有敏感数据,对其进行哈希处理并保护该哈希。然后在内部 api 合并相同的数据,对其进行哈希处理,取消保护从调用者收到的数据并确保未受保护的数据与目标哈希匹配。