2014-11-25 19:04:38 +03:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8" >
< meta charset = "utf-8" >
2015-05-14 12:03:42 +03:00
< title > AJAX, CSRF & CORS< / title >
2014-11-25 19:04:38 +03:00
< link href = "../../img/favicon.ico" rel = "icon" type = "image/x-icon" >
< link rel = "canonical" href = "http://www.django-rest-framework.org/topics/ajax-csrf-cors/" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< meta name = "description" content = "Django, API, REST, AJAX, CSRF & CORS" >
< meta name = "author" content = "Tom Christie" >
<!-- Le styles -->
< link href = "../../css/prettify.css" rel = "stylesheet" >
< link href = "../../css/bootstrap.css" rel = "stylesheet" >
< link href = "../../css/bootstrap-responsive.css" rel = "stylesheet" >
< link href = "../../css/default.css" rel = "stylesheet" >
<!-- Le HTML5 shim, for IE6 - 8 support of HTML5 elements -->
<!-- [if lt IE 9]>
< script src = "http://html5shim.googlecode.com/svn/trunk/html5.js" > < / script >
<![endif]-->
< script type = "text/javascript" >
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-18852272-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
< / script >
< style >
span.fusion-wrap a {
display: block;
margin-top: 10px;
color: black;
}
a.fusion-poweredby {
display: block;
margin-top: 10px;
}
@media (max-width: 767px) {
div.promo {
display: none;
}
}
< / style >
< / head >
< body onload = "prettyPrint()" class = "-page" >
< div class = "wrapper" >
< div class = "navbar navbar-inverse navbar-fixed-top" >
< div class = "navbar-inner" >
< div class = "container-fluid" >
< a class = "repo-link btn btn-primary btn-small" href = "https://github.com/tomchristie/django-rest-framework/tree/master" > GitHub< / a >
2015-05-14 12:03:42 +03:00
< a class = "repo-link btn btn-inverse btn-small " rel = "prev" href = "../browser-enhancements/" >
2014-11-25 19:04:38 +03:00
Next < i class = "icon-arrow-right icon-white" > < / i >
< / a >
2015-05-14 12:03:42 +03:00
< a class = "repo-link btn btn-inverse btn-small " rel = "next" href = "../internationalization/" >
2014-11-25 19:04:38 +03:00
< i class = "icon-arrow-left icon-white" > < / i > Previous
< / a >
< a class = "repo-link btn btn-inverse btn-small" href = "#searchModal" data-toggle = "modal" > < i class = "icon-search icon-white" > < / i > Search< / a >
< a class = "btn btn-navbar" data-toggle = "collapse" data-target = ".nav-collapse" >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< / a >
< a class = "brand" href = "http://www.django-rest-framework.org" > Django REST framework< / a >
< div class = "nav-collapse collapse" >
<!-- Main navigation -->
< ul class = "nav navbar-nav" >
< li > < a href = "/" > Home< / a > < / li >
2015-05-14 12:03:42 +03:00
< li >
< a href = "../.." > Home< / a >
< / li >
2014-11-25 19:04:38 +03:00
< li class = "dropdown" >
2014-11-25 19:31:00 +03:00
< a href = "#" class = "dropdown-toggle" data-toggle = "dropdown" > Tutorial < b class = "caret" > < / b > < / a >
2014-11-25 19:04:38 +03:00
< ul class = "dropdown-menu" >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../tutorial/quickstart/" > Quickstart< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../tutorial/1-serialization/" > 1 - Serialization< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../tutorial/2-requests-and-responses/" > 2 - Requests and responses< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../tutorial/3-class-based-views/" > 3 - Class based views< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../tutorial/4-authentication-and-permissions/" > 4 - Authentication and permissions< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../tutorial/5-relationships-and-hyperlinked-apis/" > 5 - Relationships and hyperlinked APIs< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../tutorial/6-viewsets-and-routers/" > 6 - Viewsets and routers< / a >
2014-11-25 19:04:38 +03:00
< / li >
< / ul >
< / li >
< li class = "dropdown" >
< a href = "#" class = "dropdown-toggle" data-toggle = "dropdown" > API Guide < b class = "caret" > < / b > < / a >
< ul class = "dropdown-menu" >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/requests/" > Requests< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/responses/" > Responses< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/views/" > Views< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/generic-views/" > Generic views< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/viewsets/" > Viewsets< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/routers/" > Routers< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/parsers/" > Parsers< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/renderers/" > Renderers< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/serializers/" > Serializers< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/fields/" > Serializer fields< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/relations/" > Serializer relations< / a >
2014-11-25 19:04:38 +03:00
< / li >
2014-12-01 15:20:07 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/validators/" > Validators< / a >
2014-12-01 15:20:07 +03:00
< / li >
2014-11-25 19:04:38 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/authentication/" > Authentication< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/permissions/" > Permissions< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/throttling/" > Throttling< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/filtering/" > Filtering< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/pagination/" > Pagination< / a >
2014-11-25 19:04:38 +03:00
< / li >
2015-03-06 15:05:16 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/versioning/" > Versioning< / a >
2015-03-06 15:05:16 +03:00
< / li >
2014-11-25 19:04:38 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/content-negotiation/" > Content negotiation< / a >
2014-11-25 19:04:38 +03:00
< / li >
2014-12-18 18:42:42 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/metadata/" > Metadata< / a >
2014-12-18 18:42:42 +03:00
< / li >
2014-11-25 19:04:38 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/format-suffixes/" > Format suffixes< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/reverse/" > Returning URLs< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/exceptions/" > Exceptions< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/status-codes/" > Status codes< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/testing/" > Testing< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../../api-guide/settings/" > Settings< / a >
2014-11-25 19:04:38 +03:00
< / li >
< / ul >
< / li >
< li class = "dropdown active" >
< a href = "#" class = "dropdown-toggle" data-toggle = "dropdown" > Topics < b class = "caret" > < / b > < / a >
< ul class = "dropdown-menu" >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../documenting-your-api/" > Documenting your API< / a >
2014-11-25 19:04:38 +03:00
< / li >
2015-03-06 15:05:16 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../internationalization/" > Internationalization< / a >
2015-03-06 15:05:16 +03:00
< / li >
2014-11-25 19:04:38 +03:00
< li class = "active" >
2015-05-14 12:03:42 +03:00
< a href = "./" > AJAX, CSRF & CORS< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../browser-enhancements/" > Browser enhancements< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../browsable-api/" > The Browsable API< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../rest-hypermedia-hateoas/" > REST, Hypermedia & HATEOAS< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../third-party-resources/" > Third Party Resources< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../contributing/" > Contributing to REST framework< / a >
2014-11-25 19:04:38 +03:00
< / li >
2014-12-18 16:49:50 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../project-management/" > Project management< / a >
2014-12-18 16:49:50 +03:00
< / li >
2014-11-25 19:04:38 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../3.0-announcement/" > 3.0 Announcement< / a >
2014-11-25 19:04:38 +03:00
< / li >
2014-12-01 15:20:07 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../3.1-announcement/" > 3.1 Announcement< / a >
2014-12-01 15:20:07 +03:00
< / li >
2014-11-25 19:04:38 +03:00
< li >
2015-05-14 12:03:42 +03:00
< a href = "../kickstarter-announcement/" > Kickstarter Announcement< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
2015-05-14 12:03:42 +03:00
< a href = "../release-notes/" > Release Notes< / a >
2014-11-25 19:04:38 +03:00
< / li >
< / ul >
< / li >
< / ul >
< / div >
<!-- /.nav - collapse -->
< / div >
< / div >
< / div >
< div class = "body-content" >
< div class = "container-fluid" >
<!-- Search Modal -->
< div id = "searchModal" class = "modal hide fade" tabindex = "-1" role = "dialog" aria-labelledby = "myModalLabel" aria-hidden = "true" >
< div class = "modal-header" >
< button type = "button" class = "close" data-dismiss = "modal" aria-hidden = "true" > × < / button >
< h3 id = "myModalLabel" > Documentation search< / h3 >
< / div >
< div class = "modal-body" >
<!-- Custom google search -->
< script >
(function() {
var cx = '015016005043623903336:rxraeohqk6w';
var gcse = document.createElement('script');
gcse.type = 'text/javascript';
gcse.async = true;
gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
'//www.google.com/cse/cse.js?cx=' + cx;
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(gcse, s);
})();
< / script >
< gcse:search > < / gcse:search >
< / div >
< div class = "modal-footer" >
< button class = "btn" data-dismiss = "modal" aria-hidden = "true" > Close< / button >
< / div >
< / div >
< div class = "row-fluid" >
< div class = "span3" >
<!-- TODO
< p style = "margin-top: -12px" >
< a class = "btn btn-mini btn-primary" style = "width: 60px" > « previous< / a >
< a class = "btn btn-mini btn-primary" style = "float: right; margin-right: 8px; width: 60px;" > next » < / a >
< / p >
-->
< div id = "table-of-contents" >
< ul class = "nav nav-list side-nav well sidebar-nav-fixed" >
< li class = "main" >
2015-05-14 12:03:42 +03:00
< a href = "#working-with-ajax-csrf-cors" > Working with AJAX, CSRF CORS< / a >
2014-11-25 19:04:38 +03:00
< / li >
< li >
< a href = "#javascript-clients" > Javascript clients< / a >
< / li >
< li >
< a href = "#csrf-protection" > CSRF protection< / a >
< / li >
< li >
< a href = "#cors" > CORS< / a >
< / li >
< / ul >
< / div >
< / div >
< div id = "main-content" class = "span9" >
< h1 id = "working-with-ajax-csrf-cors" > Working with AJAX, CSRF & CORS< / h1 >
< blockquote >
< p > "Take a close look at possible CSRF / XSRF vulnerabilities on your own websites. They're the worst kind of vulnerability — very easy to exploit by attackers, yet not so intuitively easy to understand for software developers, at least until you've been bitten by one."< / p >
< p > — < a href = "http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html" > Jeff Atwood< / a > < / p >
< / blockquote >
< h2 id = "javascript-clients" > Javascript clients< / h2 >
< p > If you’ re building a JavaScript client to interface with your Web API, you'll need to consider if the client can use the same authentication policy that is used by the rest of the website, and also determine if you need to use CSRF tokens or CORS headers.< / p >
< p > AJAX requests that are made within the same context as the API they are interacting with will typically use < code > SessionAuthentication< / code > . This ensures that once a user has logged in, any AJAX requests made can be authenticated using the same session-based authentication that is used for the rest of the website.< / p >
< p > AJAX requests that are made on a different site from the API they are communicating with will typically need to use a non-session-based authentication scheme, such as < code > TokenAuthentication< / code > .< / p >
< h2 id = "csrf-protection" > CSRF protection< / h2 >
< p > < a href = "https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)" > Cross Site Request Forgery< / a > protection is a mechanism of guarding against a particular type of attack, which can occur when a user has not logged out of a web site, and continues to have a valid session. In this circumstance a malicious site may be able to perform actions against the target site, within the context of the logged-in session.< / p >
< p > To guard against these type of attacks, you need to do two things:< / p >
< ol >
< li > Ensure that the 'safe' HTTP operations, such as < code > GET< / code > , < code > HEAD< / code > and < code > OPTIONS< / code > cannot be used to alter any server-side state.< / li >
< li > Ensure that any 'unsafe' HTTP operations, such as < code > POST< / code > , < code > PUT< / code > , < code > PATCH< / code > and < code > DELETE< / code > , always require a valid CSRF token.< / li >
< / ol >
< p > If you're using < code > SessionAuthentication< / code > you'll need to include valid CSRF tokens for any < code > POST< / code > , < code > PUT< / code > , < code > PATCH< / code > or < code > DELETE< / code > operations.< / p >
< p > In order to make AJAX requests, you need to include CSRF token in the HTTP header, as < a href = "https://docs.djangoproject.com/en/dev/ref/csrf/#ajax" > described in the Django documentation< / a > .< / p >
< h2 id = "cors" > CORS< / h2 >
< p > < a href = "http://www.w3.org/TR/cors/" > Cross-Origin Resource Sharing< / a > is a mechanism for allowing clients to interact with APIs that are hosted on a different domain. CORS works by requiring the server to include a specific set of headers that allow a browser to determine if and when cross-domain requests should be allowed.< / p >
< p > The best way to deal with CORS in REST framework is to add the required response headers in middleware. This ensures that CORS is supported transparently, without having to change any behavior in your views.< / p >
< p > < a href = "https://github.com/ottoyiu/" > Otto Yiu< / a > maintains the < a href = "https://github.com/ottoyiu/django-cors-headers/" > django-cors-headers< / a > package, which is known to work correctly with REST framework APIs.< / p >
< / div >
<!-- /span -->
< / div >
<!-- /row -->
< / div >
<!-- /.fluid - container -->
< / div >
<!-- /.body content -->
< div id = "push" > < / div >
< / div >
<!-- /.wrapper -->
< footer class = "span12" >
2014-12-01 15:20:07 +03:00
< p > Documentation built with < a href = "http://www.mkdocs.org/" > MkDocs< / a > .< / a >
2014-11-25 19:04:38 +03:00
< / p >
< / footer >
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
< script src = "../../js/jquery-1.8.1-min.js" > < / script >
< script src = "../../js/prettify-1.0.js" > < / script >
< script src = "../../js/bootstrap-2.1.1-min.js" > < / script >
2014-12-11 12:55:10 +03:00
< script src = "../../js/theme.js" > < / script >
2014-11-25 19:04:38 +03:00
< script >
//$('.side-nav').scrollspy()
var shiftWindow = function() {
scrollBy(0, -50)
};
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
$('.dropdown-menu').on('click touchstart', function(event) {
event.stopPropagation();
});
// Dynamically force sidenav to no higher than browser window
$('.side-nav').css('max-height', window.innerHeight - 130);
$(function() {
$(window).resize(function() {
$('.side-nav').css('max-height', window.innerHeight - 130);
});
});
< / script >
< / body >
< / html >