diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
old mode 100644
new mode 100755
index 9bb9f4a..d10230f
--- a/django/contrib/admin/sites.py
+++ b/django/contrib/admin/sites.py
@@ -293,13 +293,23 @@ class AdminSite(object):
         This should *not* assume the user is already logged in.
         """
         from django.contrib.auth.views import logout
-        defaults = {
-            'current_app': self.name,
-            'extra_context': extra_context or {},
-        }
-        if self.logout_template is not None:
-            defaults['template_name'] = self.logout_template
-        return logout(request, **defaults)
+
+        if request.method == "POST":
+            defaults = {
+                'current_app': self.name,
+                'extra_context': extra_context or {},
+            }
+
+            if self.logout_template is not None:
+                defaults['template_name'] = self.logout_template
+
+            return logout(request, **defaults)
+        else:
+            context = {
+                'title' : _('Are you sure?'),
+            }
+            return TemplateResponse(request, 'admin/logout_confirmation.html', context)
+        
 
     @never_cache
     def login(self, request, extra_context=None):
diff --git a/django/contrib/admin/templates/admin/base.html b/django/contrib/admin/templates/admin/base.html
old mode 100644
new mode 100755
index 4b3c429..4482bb8
--- a/django/contrib/admin/templates/admin/base.html
+++ b/django/contrib/admin/templates/admin/base.html
@@ -7,6 +7,23 @@
 <!--[if lte IE 7]><link rel="stylesheet" type="text/css" href="{% block stylesheet_ie %}{% static "admin/css/ie.css" %}{% endblock %}" /><![endif]-->
 {% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% static "admin/css/rtl.css" %}{% endblock %}" />{% endif %}
 <script type="text/javascript">window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin/" %}{% endfilter %}";</script>
+<script type="text/javascript" src="{% static "admin/js/jquery.min.js" %}"></script>
+<script type="text/javascript" src="{% static "admin/js/jquery.init.js" %}"></script>
+<script id="admin-logout-template" defer type="text/html">
+    <form id="logout-form" action="{% url 'admin:logout' %}" method="post">{% csrf_token %}</form>
+</script>
+<script type="text/javascript">
+    (function($) {
+        $(document).ready(function() {
+            $('a[href="{% url 'admin:logout' %}"]').click(function(ev) {
+                ev.preventDefault();
+                $('body').append($('#admin-logout-template').html());
+                $('#logout-form').submit();
+            });
+        });
+    })(django.jQuery);
+</script>
+
 {% block extrahead %}{% endblock %}
 {% block blockbots %}<meta name="robots" content="NONE,NOARCHIVE" />{% endblock %}
 </head>
diff --git a/django/contrib/admin/templates/admin/logout_confirmation.html b/django/contrib/admin/templates/admin/logout_confirmation.html
new file mode 100755
index 0000000..17f08c5
--- /dev/null
+++ b/django/contrib/admin/templates/admin/logout_confirmation.html
@@ -0,0 +1,21 @@
+{% extends "admin/base_site.html" %}
+{% load i18n %}
+
+{% block breadcrumbs %}
+    <div class="breadcrumbs">
+        <a href="../">{% trans "Home" %}</a> &rsaquo;
+    </div>
+{% endblock %}
+
+
+
+{% block content %}
+    <p>{% blocktrans %}Are you sure you want to logout?{% endblocktrans %}</p>
+    <form action="" method="post">
+        {% csrf_token %}
+        <div>
+            <input type="hidden" name="post" value="yes" />
+            <input type="submit" value="{% trans "Yes, I'm sure" %}" />
+        </div>
+    </form>
+{% endblock %}
\ No newline at end of file
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
old mode 100644
new mode 100755
index 22b65a6..348e2af
--- a/tests/regressiontests/admin_views/tests.py
+++ b/tests/regressiontests/admin_views/tests.py
@@ -618,7 +618,7 @@ class CustomModelAdminTest(AdminViewBasicTest):
         self.assertTrue('Hello from a custom login template' in request.content)
 
     def testCustomAdminSiteLogoutTemplate(self):
-        request = self.client.get('/test_admin/admin2/logout/')
+        request = self.client.post('/test_admin/admin2/logout/')
         self.assertIsInstance(request, TemplateResponse)
         self.assertTemplateUsed(request, 'custom_admin/logout.html')
         self.assertTrue('Hello from a custom logout template' in request.content)
@@ -745,7 +745,7 @@ class AdminViewPermissionsTest(TestCase):
         login = self.client.post('/test_admin/admin/', self.super_login)
         self.assertRedirects(login, '/test_admin/admin/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Test if user enters e-mail address
         request = self.client.get('/test_admin/admin/')
@@ -767,7 +767,7 @@ class AdminViewPermissionsTest(TestCase):
         login = self.client.post('/test_admin/admin/', self.adduser_login)
         self.assertRedirects(login, '/test_admin/admin/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Change User
         request = self.client.get('/test_admin/admin/')
@@ -775,7 +775,7 @@ class AdminViewPermissionsTest(TestCase):
         login = self.client.post('/test_admin/admin/', self.changeuser_login)
         self.assertRedirects(login, '/test_admin/admin/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Delete User
         request = self.client.get('/test_admin/admin/')
@@ -783,7 +783,7 @@ class AdminViewPermissionsTest(TestCase):
         login = self.client.post('/test_admin/admin/', self.deleteuser_login)
         self.assertRedirects(login, '/test_admin/admin/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Regular User should not be able to login.
         request = self.client.get('/test_admin/admin/')
@@ -828,7 +828,7 @@ class AdminViewPermissionsTest(TestCase):
         post = self.client.post('/test_admin/admin/admin_views/article/add/', add_dict)
         self.assertEqual(post.status_code, 403)
         self.assertEqual(Article.objects.all().count(), 3)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Add user may login and POST to add view, then redirect to admin root
         self.client.get('/test_admin/admin/')
@@ -843,7 +843,7 @@ class AdminViewPermissionsTest(TestCase):
         self.assertEqual(Article.objects.all().count(), 4)
         self.assertEqual(len(mail.outbox), 1)
         self.assertEqual(mail.outbox[0].subject, 'Greetings from a created object')
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Super can add too, but is redirected to the change list view
         self.client.get('/test_admin/admin/')
@@ -855,7 +855,7 @@ class AdminViewPermissionsTest(TestCase):
         post = self.client.post('/test_admin/admin/admin_views/article/add/', add_dict)
         self.assertRedirects(post, '/test_admin/admin/admin_views/article/')
         self.assertEqual(Article.objects.all().count(), 5)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # 8509 - if a normal user is already logged in, it is possible
         # to change user into the superuser without error
@@ -883,7 +883,7 @@ class AdminViewPermissionsTest(TestCase):
         self.assertEqual(request.status_code, 403)
         post = self.client.post('/test_admin/admin/admin_views/article/1/', change_dict)
         self.assertEqual(post.status_code, 403)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # change user can view all items and edit them
         self.client.get('/test_admin/admin/')
@@ -907,7 +907,7 @@ class AdminViewPermissionsTest(TestCase):
         self.assertEqual(request.status_code, 200)
         self.assertTrue('Please correct the errors below.' in post.content,
                         'Plural error message not found in response to post with multiple errors.')
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Test redirection when using row-level change permissions. Refs #11513.
         RowLevelChangePermissionModel.objects.create(id=1, name="odd id")
@@ -924,7 +924,7 @@ class AdminViewPermissionsTest(TestCase):
             request = self.client.post('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/2/', {'name': 'changed'})
             self.assertEqual(RowLevelChangePermissionModel.objects.get(id=2).name, 'changed')
             self.assertRedirects(request, '/test_admin/admin/')
-            self.client.get('/test_admin/admin/logout/')
+            self.client.post('/test_admin/admin/logout/')
         for login_dict in [self.joepublic_login, self.no_username_login]:
             self.client.post('/test_admin/admin/', login_dict)
             request = self.client.get('/test_admin/admin/admin_views/rowlevelchangepermissionmodel/1/')
@@ -941,7 +941,7 @@ class AdminViewPermissionsTest(TestCase):
             self.assertEqual(RowLevelChangePermissionModel.objects.get(id=2).name, 'changed')
             self.assertEqual(request.status_code, 200)
             self.assertContains(request, 'login-form')
-            self.client.get('/test_admin/admin/logout/')
+            self.client.post('/test_admin/admin/logout/')
 
     def testConditionallyShowAddSectionLink(self):
         """
@@ -1004,7 +1004,7 @@ class AdminViewPermissionsTest(TestCase):
         request = self.client.get('/test_admin/admin/admin_views/customarticle/%d/history/' % article_pk)
         self.assertTemplateUsed(request, 'custom_admin/object_history.html')
 
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
     def testDeleteView(self):
         """Delete view should restrict access and actually delete items."""
@@ -1019,7 +1019,7 @@ class AdminViewPermissionsTest(TestCase):
         post = self.client.post('/test_admin/admin/admin_views/article/1/delete/', delete_dict)
         self.assertEqual(post.status_code, 403)
         self.assertEqual(Article.objects.all().count(), 3)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Delete user can delete
         self.client.get('/test_admin/admin/')
@@ -1038,7 +1038,7 @@ class AdminViewPermissionsTest(TestCase):
         article_ct = ContentType.objects.get_for_model(Article)
         logged = LogEntry.objects.get(content_type=article_ct, action_flag=DELETION)
         self.assertEqual(logged.object_id, u'1')
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
     def testDisabledPermissionsWhenLoggedIn(self):
         self.client.login(username='super', password='secret')
@@ -1339,7 +1339,7 @@ class SecureViewTests(TestCase):
         login = self.client.post('/test_admin/admin/secure-view/', self.super_login)
         self.assertRedirects(login, '/test_admin/admin/secure-view/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
         # make sure the view removes test cookie
         self.assertEqual(self.client.session.test_cookie_worked(), False)
 
@@ -1363,7 +1363,7 @@ class SecureViewTests(TestCase):
         login = self.client.post('/test_admin/admin/secure-view/', self.adduser_login)
         self.assertRedirects(login, '/test_admin/admin/secure-view/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Change User
         request = self.client.get('/test_admin/admin/secure-view/')
@@ -1371,7 +1371,7 @@ class SecureViewTests(TestCase):
         login = self.client.post('/test_admin/admin/secure-view/', self.changeuser_login)
         self.assertRedirects(login, '/test_admin/admin/secure-view/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Delete User
         request = self.client.get('/test_admin/admin/secure-view/')
@@ -1379,7 +1379,7 @@ class SecureViewTests(TestCase):
         login = self.client.post('/test_admin/admin/secure-view/', self.deleteuser_login)
         self.assertRedirects(login, '/test_admin/admin/secure-view/')
         self.assertFalse(login.context)
-        self.client.get('/test_admin/admin/logout/')
+        self.client.post('/test_admin/admin/logout/')
 
         # Regular User should not be able to login.
         request = self.client.get('/test_admin/admin/secure-view/')
@@ -1502,10 +1502,10 @@ class AdminViewListEditable(TestCase):
         # 4 action inputs (3 regular checkboxes, 1 checkbox to select all)
         # main form submit button = 1
         # search field and search submit button = 2
-        # CSRF field = 1
+        # CSRF field = 1 + 1 (the logout form has a CSRF field and is on every page in the admin.)
         # field to track 'select all' across paginated views = 1
         # 6 + 3 + 4 + 1 + 2 + 1 + 1 = 18 inputs
-        self.assertEqual(response.content.count("<input"), 18)
+        self.assertEqual(response.content.count("<input"), 19)
         # 1 select per object = 3 selects
         self.assertEqual(response.content.count("<select"), 4)
 
@@ -2690,7 +2690,7 @@ class NeverCacheTests(TestCase):
 
     def testLogout(self):
         "Check the never-cache status of logout view"
-        response = self.client.get('/test_admin/admin/logout/')
+        response = self.client.post('/test_admin/admin/logout/')
         self.assertEqual(get_max_age(response), 0)
 
     def testPasswordChange(self):
@@ -2748,8 +2748,9 @@ class ReadonlyTest(TestCase):
         self.assertEqual(response.status_code, 200)
         self.assertNotContains(response, 'name="posted"')
         # 3 fields + 2 submit buttons + 4 inline management form fields, + 2
-        # hidden fields for inlines + 1 field for the inline + 2 empty form
-        self.assertEqual(response.content.count("<input"), 14)
+        # hidden fields for inlines + 1 field for the inline + 2 empty form + 1
+        # input for csrf token on logout form in js.
+        self.assertEqual(response.content.count("<input"), 15)
         self.assertContains(response, formats.localize(datetime.date.today()))
         self.assertContains(response,
             "<label>Awesomeness level:</label>")
@@ -3222,3 +3223,29 @@ class AdminCustomSaveRelatedTests(TestCase):
 
         self.assertEqual('Josh Stone', Parent.objects.latest('id').name)
         self.assertEqual([u'Catherine Stone', u'Paul Stone'], children_names)
+
+
+class AdminViewLogoutTest(TestCase):
+    fixtures = ['admin-views-users.xml', ]
+
+    def setUp(self):
+        self.client.login(username='super', password='secret')
+
+    def tearDown(self):
+        self.client.logout()
+
+    def test_logout_attempt_using_get(self):
+        response = self.client.get('/test_admin/admin/logout/')
+        self.assertEqual(response.status_code, 200)
+        # since we are issuing a GET request we should be rendering 
+        # the confirmation template
+        self.assertTemplateUsed(response, 'admin/logout_confirmation.html')
+        
+    def test_logout_attempt_using_post(self):
+        # 15619 - you must POST to the logout view to actually logout.
+        response = self.client.post('/test_admin/admin/logout/')
+        self.assertEqual(response.status_code, 200)
+        # since we are issuing a POST request we should be logging out the
+        # user immediatly.
+        self.assertTemplateUsed(response, 'registration/logged_out.html')
+
