我无法使用AngularJs将RequestVerificationToken从网页传递到服务器。
我的AngularJs代码是:
var app = angular.module('validation', []);
app.controller('SignUpController', function ($scope, $http) {
$scope.model = {};
$scope.email = {};
$scope.sendEmail = function () {
$http({
method: 'POST',
url: '/Contact/Test',
data: $scope.email,
headers: {
'RequestVerificationToken': $scope.antiForgeryToken
}
}).success();
};
});
自定义属性代码:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustomAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
private void ValidateRequestHeader(HttpRequestBase request)
{
string cookieToken = String.Empty;
string formToken = String.Empty;
string tokenValue = request.Headers["RequestVerificationToken"];
if (!String.IsNullOrEmpty(tokenValue))
{
string[] tokens = tokenValue.Split(':');
if (tokens.Length == 2)
{
cookieToken = tokens[0].Trim();
formToken = tokens[1].Trim();
}
}
AntiForgery.Validate(cookieToken, formToken);
}
public void OnAuthorization(AuthorizationContext filterContext)
{
try
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
ValidateRequestHeader(filterContext.HttpContext.Request);
}
else
{
AntiForgery.Validate();
}
}
catch (HttpAntiForgeryException e)
{
throw new HttpAntiForgeryException("Anti forgery token cookie not found");
}
}
}
表格是:
@functions{
public string GetAntiForgeryToken()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
<div ng-app="validation" ng-controller="SignUpController">
<form role="form" id="frmContact" action="@Url.Action("Index", "Contact")" method="POST">
<input id="antiForgeryToken" ng-model="antiForgeryToken" type="hidden" ng-init="antiForgeryToken='@GetAntiForgeryToken()'" />
<fieldset class="form-group">
@Html.LabelFor(x => x.EmailTitle)
@Html.TextBoxFor(x => x.EmailTitle, new { placeholder = @Resource.EmailTitle, @class = "form-control", data_ng_model = "new.email.title" })
</fieldset>
<fieldset class="form-group">
@Html.LabelFor(x => x.EmailAddress)
@Html.TextBoxFor(x => x.EmailAddress, new { placeholder = @Resource.EmailAddress, @class = "form-control", data_ng_model = "new.email.address" })
</fieldset>
<fieldset class="form-group">
@Html.LabelFor(x => x.EmailMessage)
@Html.TextAreaFor(x => x.EmailMessage, new { placeholder = @Resource.EmailMessage, @class = "form-control", data_ng_model = "new.email.message" })
</fieldset>
<div>
<button type="submit" name="btnEmailForm" id="btnEmailForm" class="btnLogin" ng-click="sendEmail()" value="sendMessage">@Resource.ContactFormSendMessageButton</button>
</div>
<div id="errorMessages" class="error">{{message}}</div>
</form>
</div>
我已经阅读了以下帖子,但似乎无法解决问题,并且还从https://github.com/techbrij/angularjs-asp-net-mvc获取了代码,该代码在该示例中有效但在我的MVC应用程序中无效:
http://techbrij.com/angularjs-antiforgerytoken-asp-net-mvc
https://parthivpandya.wordpress.com/2013/11/25/angularjs-and-antiforgerytoken-in-asp-net-mvc/
AngularJS Web Api AntiForgeryToken CSRF
http://bartwullems.blogspot.co.uk/2014/10/angularjs-and-aspnet-mvc-isajaxrequest.html
Where exactly to put the antiforgeryToken
http://www.ojdevelops.com/2016/01/using-antiforgerytokens-in-aspnet-mvc.html
任何人都可以帮助解决这个问题
答案 0 :(得分:0)
在这种情况下,您执行表单submit
和$scope.sendEmail
操作,它们可能会相互冲突,以防止出现此行为,您可以使用ng-submit
指令。并且还将属性name= '__RequestVerificationToken'
和ng-value="antiForgeryToken"
添加到相应的input
。
答案 1 :(得分:0)
重要提示:[ValidateAntiForgeryToken]
的默认行为期望表单值中的__RequestVerificationToken
令牌。要将请求以格式值格式发送到服务器,需要将content-type
设置为application/x-www-form-urlencoded
。但是很不幸,我没有此选项,我的内容类型是application/json
。因此,我采用了这种自定义路径。
让我解释一下我采用的方法。
步骤1:在视图(.cshtml)中声明@Html.AntiForgeryToken()
,如下所示:
<form id="inputForm" name="inputForm" ng-submit="submit(broker)" novalidate>
@Html.AntiForgeryToken()
/* other controls of form */
</form>
步骤2:@Html.AntiForgeryToken()
将呈现一个隐藏字段,该字段将令牌值保存为:
<input name="__RequestVerificationToken" type="hidden" value="GvTcz2tTgHOS2KK_7jpHvPWEJPcbJmHIpSAlxY1">
第3步:为防伪令牌验证创建自定义属性,
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class HbValidateAntiForgeryToken : FilterAttribute, IAuthorizationFilter, IExceptionFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
try
{
var antiForgeryCookie = filterContext.HttpContext.Request.Cookies[AntiForgeryConfig.CookieName];
AntiForgery.Validate(antiForgeryCookie != null ? antiForgeryCookie.Value : null,
filterContext.HttpContext.Request.Headers["__RequestVerificationToken"]);
}
catch (Exception ex)
{
throw new SecurityException("Unauthorised access detected and blocked");
}
}
public void OnException(ExceptionContext filterContext)
{
if (filterContext.Exception != null &&
filterContext.Exception is System.Security.SecurityException)
{
filterContext.Result = new HttpUnauthorizedResult();
// Handle error page scenario here
}
}
}
第4步:在需要的地方声明上述属性(仅在控制器的HttpPost方法上。请勿在HttpGet上声明)
[HttpPost]
[HbValidateAntiForgeryToken]
public JsonResult IsUsernameExists(string username)
{
}
第5步:在AngularJS中,在工厂通过__RequestVerificationToken
作为标题。
hbServices.factory('RegistrationService', ['$resource',
function ($resource) {
return $resource(applicationPath + 'api/MyUserMembership/:dest', {}, {
createNewUser: { method: 'POST', isArray: false, params: { dest: 'CreateNewUser' },
headers: {
'__RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
}
},
isUsernameExists: { method: 'POST', isArray: false, params: { dest: 'IsUsernameExists' },
headers: {
'__RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
}
}
});
}]);
请注意,我传递__RequestVerificationToken
值的方式是从ASP.NET MVC的@Html.AntiForgeryToken()
呈现的隐藏字段中读取的。
我的应用程序正在使用jquery,并且已经具有jquery的引用,因此读取值很容易。您可以尝试其他方法读取此值
摘要
AntiForgery.Validate()
在这里具有验证伪造令牌的价值的魔力,到目前为止还很不错。希望这会有所帮助!