ASP.NET MVC 구현할 때, POST 로 전송시, anti-forgery token 을 함께 전송하는 방법을 찾아봤습니다. jQuery 버전은 3.5.1 버전이며, ajax 통신을 통해 전송하였습니다.
form 태그 안에 token 값을 생성합니다.
@Html.Partial("_AntiForgeryTokens")
jQuery 를 이용하여 token 값을 header 에 __RequestVerificationToken 를 키로 하여 토큰 값과 함께 전송합니다.
var token = $('input[name="__RequestVerificationToken"]', $('#frm')).val();
if (window.confirm("1:1문의 요청하시겠습니까?")) {
$.ajax({
url: '@Url.Action("WriteSend", "QNA")',
headers: { '__RequestVerificationToken': token },
type: 'post',
dataType: 'json', //json으로 응답받을 때
contentType: 'application/json; charset=utf-8',
data: '{ p: "' + GetJsonToEncParam(requJson) + '", contents: "' + contents + '" }',
success: function (result) {
if (result.success) {
$('html').scrollTop(0);
$("form").each(function () {
if (this.id == "frm") this.reset();
});
$(".qnafrm").hide();
$(".qnaConfirm").show();
}
else {
alert(result.msg);
}
},
error: function (xhr, status, error) {
console.log(xhr, status, error);
console.log("error");
}
});
}
보통은 [ValidateAntiForgeryToken] 를 사용하여 토큰 값이 존재하는지 또는 검증을 확인해 줍니다. 하지만, 이상하게도 전송은 하였지만 받아지지 않고 오류가 발생됩니다.
[HttpPost]
[ValidateInput(false)]
[ValidateAntiForgeryToken]
public ActionResult WriteSend(string p, string contents)
{
//구문 기술...
}
이를 해결하기 위해서 [ValidateAntiForgeryToken] 를 사용하지 않고 별도로 어트리뷰트를 만듭니다.
어트리뷰트 이름은 [ValidateHeaderAntiForgeryToken] 으로 하였습니다.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
var httpContext = filterContext.HttpContext;
var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
}
}
직접 커스텀한 어트리뷰트를 컨트롤러에 적용해 봤습니다.
[HttpPost]
[ValidateInput(false)]
//[ValidateAntiForgeryToken]
[ValidateHeaderAntiForgeryToken]
public ActionResult WriteSend(string p, string contents)
{
//구문 기술...
}
테스트 검증 한 결과 문제 없이 통과 되어 오류 없이 처리가 되었습니다.
도움 받은 stackoverflow 사이트는 아래 제공해 드립니다.
참고 사이트
https://stackoverflow.com/a/46468504
__RequestVerificationToken is not present with Ajax POST
I'm using jQuery DataTales to request a POST URL from MVC5 and trying to add an anti-forgery token. I've added it to both the headers and also the request body, but still get a 500 error: "The requ...
stackoverflow.com
https://stackoverflow.com/questions/33306859/the-required-anti-forgery-cookie-requestverificationtoken-is-not-present?rq=1
The required anti-forgery cookie "__RequestVerificationToken" is not present
My website is raising this exception around 20 times a day, usually the form works fine but there are instances where this issue occur and I don't know why is so random. This is logged exception by
stackoverflow.com
jQuery 로 post submit 전송 할 경우
form 의 post submit 전송시에는 [ValidateAntiForgeryToken] 이슈없이 작동 잘됩니다.
다시 말하면, jQuery 가 아닌 일반적인 form 의 post submit 전송시에는 이슈없이 ValidateAntiForgeryToken 작동이 잘됩니다.
@using (Html.BeginForm("RegisterSave", Controllers, FormMethod.Post, new { id = "form1", name = "form1" }))
{
@Html.Partial("_AntiForgeryTokens")
@Html.Hidden("p", "")
<a id="btnSave" href="jvascript:void(0);" class="cmn-ev-form-applybtn chlg-apply-btn gfw500 fs26 orange">이벤트 응모하기</a>
}
$("#btnSave").click(function (e) {
e.preventDefault();
if (window.confirm("are you send?")) {
$("#form1").submit();
}
}
$('form').submit(function (e) {
var formJson = $(this).serializeFormJSON();
$("#p").val(GetJsonToEncParam(formJson));
});
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RegisterSave(string p)
{
return Content(@"<script>alert(' 참여해 주셔서 감사합니다.');location.href='/';</script>");
}
그리고 ValidateAntiForgeryToken 를 사용하기 위해서는 HTTPS 즉 SSL 형태이어야 하며, HTTPS 로 접속하여 확인하셔야 합니다. http 접속 경로인데 아래와 같이 requiredSSL 을 true 로 할 경우 위와 같이 문제가 발생될 수 도 있으니 http 환경에서는 false 로 셋팅이 되어 있어야 겠습니다.
- web.config 파일 내부
<httpCookies requireSSL="true"/>