随着 ASP.net MVC 5 的出现,Account Controller 和 Account Views 也随之而来。在 Register View 中有行
@Html.AntiForgeryToken()
在注册 Controller 上面有属性:
[ValidateAntiForgeryToken]
我决定使用 JSON 从 javascript 向服务器发送数据(我正在使用 Angular 和 $http.post 方法)。
我的问题是如何使用 javascript 发送此 AntiForgeryToken 并在 Controller 中对其进行验证?
还有我应该包括的更多安全措施吗?
最佳答案
AngularJS 内置了对 XSRF(又名防伪造)的支持
XSRF is a technique by which an unauthorized site can gain your user's private data. Angular provides a mechanism to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain could read the cookie, your server can be assured that the XHR came from JavaScript running on your domain. The header will not be set for cross-domain requests.
如果您想利用此功能,您必须创建操作过滤器来创建和验证 XSRF-TOKEN cookie。 这是我使用的简化版本。
AntiForgeryTokenCookieAttribute - 使用此属性添加 XSRF-TOKEN cookie
/// <summary>
/// Create a XSRF token in the XSRF-TOKEN cookie which is automatically read by AngularJS
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AntiForgeryTokenCookieAttribute : ActionFilterAttribute
{
private readonly IAntiForgeryVerificationTokenStore _verificationTokenStore = new AntiForgeryVerificationTokenCookieStore(); //TODO: make configurable
private const string CookieName = "XSRF-TOKEN"; //TODO: make configurable
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var oldVerificationToken = _verificationTokenStore.GetVerificationToken(filterContext.HttpContext.Request);
string newVerificationToken;
string newToken;
AntiForgery.GetTokens(oldVerificationToken, out newVerificationToken, out newToken);
if (newVerificationToken != null)
{
_verificationTokenStore.StoreVerificationToken(filterContext.HttpContext.Response, newVerificationToken);
}
filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(CookieName, newToken));
}
}
ValidateAntiForgeryTokenHeaderAttribute
/// <summary>
/// Validate the XSRF token stored in the X-XSRF-TOKEN header.
/// If the header doesn't exist, look for the XSRF token in the from post.
///
/// Compatible with ValidateAntiForgeryTokenAttribute
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ValidateAntiForgeryTokenHeaderAttribute : FilterAttribute, IAuthorizationFilter
{
private readonly IAntiForgeryVerificationTokenStore _verificationTokenStore = new AntiForgeryVerificationTokenCookieStore(); //TODO: make configurable
private const string TokenHeaderName = "X-XSRF-TOKEN"; //TODO: make configurable
public void OnAuthorization(AuthorizationContext filterContext)
{
var token = filterContext.HttpContext.Request.Headers[TokenHeaderName];
if (token != null)
{
//validate the token stored in header
var verificationToken = _verificationTokenStore.GetVerificationToken(filterContext.HttpContext.Request);
if (verificationToken == null) { throw new HttpAntiForgeryException("Required verification token not found"); }
AntiForgery.Validate(verificationToken, token);
}
else
{
//validate the token stored in form. Same as ValidateAntiForgeryTokenAttribute
AntiForgery.Validate();
}
}
}
IAntiForgeryVerificationTokenStore
public interface IAntiForgeryVerificationTokenStore
{
string GetVerificationToken(HttpRequestBase request);
void StoreVerificationToken(HttpResponseBase response, string token);
}
AntiForgeryVerificationTokenCookieStore
public class AntiForgeryVerificationTokenCookieStore : IAntiForgeryVerificationTokenStore
{
public string GetVerificationToken(HttpRequestBase request)
{
if (request == null) { throw new ArgumentNullException("request"); }
var token = request.Cookies[AntiForgeryConfig.CookieName];
return token != null ? token.Value : null;
}
public void StoreVerificationToken(HttpResponseBase response, string token)
{
if (response == null) { throw new ArgumentNullException("response"); }
if (token == null) { throw new ArgumentNullException("token"); }
response.Cookies.Add(new HttpCookie(AntiForgeryConfig.CookieName, token) { HttpOnly = true, Secure = AntiForgeryConfig.RequireSsl });
}
}
关于javascript - ASP.net 身份从 javascript 发送 AntiForgeryToken,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20533286/