asp.net-mvc
Html.AntiForgeryToken
수색…
소개
위조 방지 토큰은 사이트 간 요청 위조로부터 응용 프로그램을 보호하는 데 사용할 수 있습니다. 이 기능을 사용하려면 양식에서 AntiForgeryToken 메서드를 호출하고 보호 할 작업 메서드에 ValidateAntiForgeryTokenAttribute 특성을 추가합니다.
양식을 제출할 때 유효성을 검사하는 숨겨진 양식 필드 (위조 토큰)를 생성합니다.
통사론
- @ Html.AntiForgeryToken ()
비고
CSRF 토큰 ( __RequestVerificationToken
)을 사용하여 ajax 요청을 제출할 때 콘텐츠 유형이 application/json
설정되어 있지 않은지 확인하십시오. jQuery를 사용하는 경우 자동으로 컨텐츠 유형을 application/x-www-form-urlencoded
합니다. 그러면 ASP.NET MVC에서이를 인식합니다.
주의
이 값을 설정할 때는주의하십시오. 부적절하게 사용하면 응용 프로그램의 보안 취약점을 열 수 있습니다.
기본 사용법
@Html.AntiForgeryToken()
도우미 메서드는 사이트 간 요청 위조 (또는 CSRF) 공격으로부터 보호합니다.
기존 폼 중 하나에서 Html.AntiForgeryToken()
도우미를 사용하고 [ValidateAntiForgeryToken]
특성을 사용하여 해당 컨트롤러 액션을 Html.AntiForgeryToken()
사용할 수 있습니다.
면도기 (YourView.cshtml)
@using (Html.BeginForm("Manage", "Account")) {
@Html.AntiForgeryToken()
<!-- ... -->
}
또는
<form>
@Html.AntiForgeryToken()
<!-- ... -->
</form>
컨트롤러 (YourController.cs)
목표 동작 방법 :
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult ActionMethod(ModelObject model)
{
// ...
}
ID 휴리스틱 검사 비활성화
종종 예외가 표시됩니다.
Anti forgery token is meant for user "" but the current user is "username"
이는 위조 토큰이 현재 로그인 한 사용자와 연결되어 있기 때문입니다. 이 오류는 사용자가 로그인했지만 토큰이 사이트의 익명 사용자로 계속 링크되어있을 때 나타납니다.
이 동작을 해결할 수있는 몇 가지 방법이 있지만 사용자의 로그인 상태에 CSRF 토큰을 연결하지 않으려면이 기능을 비활성화해야합니다.
Global.asax
파일 또는 이와 유사한 응용 프로그램 시작 논리에이 행을 입력하십시오.
AntiForgeryConfig.SuppressIdentityHeuristicChecks = true;
모든 게시물의 유효성 검사
CSRF에 의해 야기 된 취약점으로 인해 일반적으로 모든 HttpPosts에 대해 AntiForgeryToken을 확인하는 것이 좋은 방법으로 간주됩니다 (게시물에 기술적 인 문제가 있거나 다른 인증 메커니즘 및 / 또는 게시물은 db 또는 파일에 저장하는 것과 같이 상태를 변경하지 않습니다.) 잊지 않도록 특별한 "ignore"속성으로 동작을 장식하지 않는 한 모든 HttpPost를 자동으로 확인하는 특수 GlobalActionFilter를 추가 할 수 있습니다.
[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
bool skipCheck = filterContext.ActionDescriptor.IsDefined(typeof(DontCheckForAntiForgeryTokenAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(DontCheckForAntiForgeryTokenAttribute), true);
if (skipCheck)
return;
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null
? antiForgeryCookie.Value
: null;
AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute()
.OnAuthorization(filterContext);
}
}
}
}
/// <summary>
/// this should ONLY be used on POSTS that DO NOT MUTATE STATE
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class DontCheckForAntiForgeryTokenAttribute : Attribute { }
모든 요청에 대해 확인되도록하려면 글로벌 액션 필터에 추가하십시오.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//...
filters.Add(new ValidateAntiForgeryTokenOnAllPosts());
//...
}
}
사전 사용 : 모든 POST에 대해 기본 Antiforgery 필터 적용
각 POST
요청에 Antiforgery attribute
을 적용하는 것을 Antiforgery attribute
기본적으로 만들어야합니다. 이 샘플은 Antiforgery filter
가 항상 모든 POST
요청에 적용되는지 확인 POST
.
먼저 새로운 AntiForgeryTokenFilter
필터를 만듭니다.
//This will add ValidateAntiForgeryToken Attribute to all HttpPost action methods
public class AntiForgeryTokenFilter : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
List<Filter> result = new List<Filter>();
string incomingVerb = controllerContext.HttpContext.Request.HttpMethod;
if (String.Equals(incomingVerb, "POST", StringComparison.OrdinalIgnoreCase))
{
result.Add(new Filter(new ValidateAntiForgeryTokenAttribute(), FilterScope.Global, null));
}
return result;
}
}
그런 다음이 사용자 정의 필터를 MVC, Application_Start에 등록하십시오.
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//Cactch generic error
filters.Add(new HandleErrorAttribute());
//Anti forgery token hack for every post request
FilterProviders.Providers.Add(new AntiForgeryTokenFilter());
}
}
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
이제 모든 POST
요청은 Antiforgery 속성을 사용하여 기본적으로 보호되므로 각 POST 메소드에 [ValidateAntiForgeryToken]
속성이 더 이상 필요하지 않습니다.
Jquery Ajax 요청과 함께 AntiForgeryToken 사용하기
먼저 양식을 만듭니다.
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
}
액션 메소드
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(FormViewModel formData)
{
// ...
}
스크립트
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script>
var formData = new FormData($('form')[0]);
$.ajax({
method: "POST",
url: "/demo/test",
data: formData ,
success: function (data) {
console.log(data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
})
</script>
contentType이 application/x-www-form-urlencoded
이외의 항목으로 설정되지 않았는지 확인하십시오. 지정된 Jquery의 기본값이 application/x-www-form-urlencoded