Ticket #14261: clickjack.diff
File clickjack.diff, 12.4 KB (added by , 14 years ago) |
---|
-
tests/regressiontests/middleware/tests.py
### Eclipse Workspace Patch 1.0 #P django-the-trunk
2 2 3 3 from django.conf import settings 4 4 from django.http import HttpRequest 5 from django.http import HttpResponse 6 from django.middleware.clickjacking import XFrameOptionsMiddleware 5 7 from django.middleware.common import CommonMiddleware 6 8 from django.middleware.http import ConditionalGetMiddleware 7 9 from django.test import TestCase … … 334 336 self.resp['Last-Modified'] = 'Sat, 12 Feb 2011 17:41:44 GMT' 335 337 self.resp = ConditionalGetMiddleware().process_response(self.req, self.resp) 336 338 self.assertEqual(self.resp.status_code, 200) 339 340 class XFrameOptionsMiddlewareTest(TestCase): 341 def tearDown(self): 342 if hasattr(settings, 'X_FRAME_OPTIONS'): 343 delattr(settings, 'X_FRAME_OPTIONS') 344 345 def test_same_origin(self): 346 """ 347 Tests that the X_FRAME_OPTIONS setting can be set to SAMEORIGIN to 348 have the middleware use that value for the HTTP header. 349 """ 350 settings.X_FRAME_OPTIONS = 'SAMEORIGIN' 351 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 352 HttpResponse()) 353 self.assertEqual(r['X-FRAME-OPTIONS'], 'SAMEORIGIN') 354 355 settings.X_FRAME_OPTIONS = 'sameorigin' 356 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 357 HttpResponse()) 358 self.assertEqual(r['X-FRAME-OPTIONS'], 'SAMEORIGIN') 359 360 def test_deny(self): 361 """ 362 Tests that the X_FRAME_OPTIONS setting can be set to DENY to 363 have the middleware use that value for the HTTP header. 364 """ 365 settings.X_FRAME_OPTIONS = 'DENY' 366 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 367 HttpResponse()) 368 self.assertEqual(r['X-FRAME-OPTIONS'], 'DENY') 369 370 settings.X_FRAME_OPTIONS = 'deny' 371 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 372 HttpResponse()) 373 self.assertEqual(r['X-FRAME-OPTIONS'], 'DENY') 374 375 def test_defaults_deny(self): 376 """ 377 Tests that if the X_FRAME_OPTIONS setting is not set then it defaults 378 to DENY. 379 """ 380 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 381 HttpResponse()) 382 self.assertEqual(r['X-FRAME-OPTIONS'], 'DENY') 383 384 def test_dont_set_if_set(self): 385 """ 386 Tests that if the X-FRAME-OPTIONS header is already set then the 387 middleware does not attempt to override it. 388 """ 389 settings.X_FRAME_OPTIONS = 'DENY' 390 response = HttpResponse() 391 response['X-FRAME-OPTIONS'] = 'SAMEORIGIN' 392 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 393 response) 394 self.assertEqual(r['X-FRAME-OPTIONS'], 'SAMEORIGIN') 395 396 settings.X_FRAME_OPTIONS = 'SAMEORIGIN' 397 response = HttpResponse() 398 response['X-FRAME-OPTIONS'] = 'DENY' 399 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 400 response) 401 self.assertEqual(r['X-FRAME-OPTIONS'], 'DENY') 402 403 def test_response_exempt(self): 404 """ 405 Tests that if the response has a xframe_options_exempt attribute set 406 to False then it still sets the header, but if it's set to True then 407 it does not. 408 """ 409 settings.X_FRAME_OPTIONS = 'DENY' 410 response = HttpResponse() 411 response.xframe_options_exempt = False 412 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 413 response) 414 self.assertEqual(r['X-FRAME-OPTIONS'], 'DENY') 415 416 response = HttpResponse() 417 response.xframe_options_exempt = True 418 r = XFrameOptionsMiddleware().process_response(HttpRequest(), 419 response) 420 self.assertEqual(r.get('X-FRAME-OPTIONS', None), None) 421 422 def test_is_extendable(self): 423 """ 424 Tests that the XFrameOptionsMiddleware method that determines the 425 X-FRAME-OPTIONS header value can be overridden based on something in 426 the request or response. 427 """ 428 class OtherXFrameOptionsMiddleware(XFrameOptionsMiddleware): 429 # This is just an example for testing purposes... 430 def get_xframe_options_value(self, request, response): 431 if getattr(request, 'sameorigin', False): 432 return 'SAMEORIGIN' 433 if getattr(response, 'sameorigin', False): 434 return 'SAMEORIGIN' 435 return 'DENY' 436 437 settings.X_FRAME_OPTIONS = 'DENY' 438 response = HttpResponse() 439 response.sameorigin = True 440 r = OtherXFrameOptionsMiddleware().process_response(HttpRequest(), 441 response) 442 self.assertEqual(r['X-FRAME-OPTIONS'], 'SAMEORIGIN') 443 444 request = HttpRequest() 445 request.sameorigin = True 446 r = OtherXFrameOptionsMiddleware().process_response(request, 447 HttpResponse()) 448 self.assertEqual(r['X-FRAME-OPTIONS'], 'SAMEORIGIN') 449 450 settings.X_FRAME_OPTIONS = 'SAMEORIGIN' 451 r = OtherXFrameOptionsMiddleware().process_response(HttpRequest(), 452 HttpResponse()) 453 self.assertEqual(r['X-FRAME-OPTIONS'], 'DENY') -
tests/regressiontests/decorators/tests.py
13 13 from django.views.decorators.http import require_http_methods, require_GET, require_POST 14 14 from django.views.decorators.vary import vary_on_headers, vary_on_cookie 15 15 from django.views.decorators.cache import cache_page, never_cache, cache_control 16 from django.views.decorators.clickjacking import xframe_options_deny, xframe_options_sameorigin, xframe_options_exempt 17 from django.middleware.clickjacking import XFrameOptionsMiddleware 16 18 17 19 18 20 def fully_decorated(request): … … 183 185 184 186 self.assertEqual(Test.method.__doc__, 'A method') 185 187 self.assertEqual(Test.method.im_func.__name__, 'method') 188 189 class XFrameOptionsDecoratorsTests(TestCase): 190 """ 191 Tests for the X-FRAME-OPTIONS decorators. 192 """ 193 def test_deny_decorator(self): 194 """ 195 Ensures @xframe_options_deny properly sets the X-FRAME-OPTIONS header. 196 """ 197 @xframe_options_deny 198 def a_view(request): 199 return HttpResponse() 200 r = a_view(HttpRequest()) 201 self.assertEqual(r['X-FRAME-OPTIONS'], 'DENY') 202 203 def test_sameorigin_decorator(self): 204 """ 205 Ensures @xframe_options_sameorigin properly sets the X-FRAME-OPTIONS 206 header. 207 """ 208 @xframe_options_sameorigin 209 def a_view(request): 210 return HttpResponse() 211 r = a_view(HttpRequest()) 212 self.assertEqual(r['X-FRAME-OPTIONS'], 'SAMEORIGIN') 213 214 def test_exempt_decorator(self): 215 """ 216 Ensures @xframe_options_exempt properly instructs the 217 XFrameOptionsMiddleware to NOT set the header. 218 """ 219 @xframe_options_exempt 220 def a_view(request): 221 return HttpResponse() 222 req = HttpRequest() 223 resp = a_view(req) 224 self.assertEqual(resp.get('X-FRAME-OPTIONS', None), None) 225 self.assertTrue(resp.xframe_options_exempt) 226 227 r = XFrameOptionsMiddleware().process_response(req, resp) 228 self.assertEqual(r.get('X-FRAME-OPTIONS', None), None) -
django/views/decorators/clickjacking.py
1 from django.utils.decorators import available_attrs 2 3 try: 4 from functools import wraps 5 except ImportError: 6 from django.utils.functional import wraps # Python 2.4 fallback. 7 8 def xframe_options_deny(view_func): 9 """ 10 Modifies a view function so its response has the X-FRAME-OPTIONS HTTP 11 header set to 'DENY' as long as the response doesn't already have that 12 header set. 13 14 e.g. 15 16 @xframe_options_deny 17 def some_view(request): 18 ... 19 20 """ 21 def wrapped_view(*args, **kwargs): 22 resp = view_func(*args, **kwargs) 23 if resp.get('X-FRAME-OPTIONS', None) is None: 24 resp['X-FRAME-OPTIONS'] = 'DENY' 25 return resp 26 return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view) 27 28 def xframe_options_sameorigin(view_func): 29 """ 30 Modifies a view function so its response has the X-FRAME-OPTIONS HTTP 31 header set to 'SAMEORIGIN' as long as the response doesn't already have 32 that header set. 33 34 e.g. 35 36 @xframe_options_sameorigin 37 def some_view(request): 38 ... 39 40 """ 41 def wrapped_view(*args, **kwargs): 42 resp = view_func(*args, **kwargs) 43 if resp.get('X-FRAME-OPTIONS', None) is None: 44 resp['X-FRAME-OPTIONS'] = 'SAMEORIGIN' 45 return resp 46 return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view) 47 48 def xframe_options_exempt(view_func): 49 """ 50 Modifies a view function by setting a response variable that instructs 51 XFrameOptionsMiddleware to NOT set the X-FRAME-OPTIONS HTTP header. 52 53 e.g. 54 55 @xframe_options_exempt 56 def some_view(request): 57 ... 58 59 """ 60 def wrapped_view(*args, **kwargs): 61 resp = view_func(*args, **kwargs) 62 resp.xframe_options_exempt = True 63 return resp 64 return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view) -
django/middleware/clickjacking.py
1 """ 2 Clickjacking Protection Middleware. 3 4 This module provides a middleware that implements protection against a 5 malicious site loading your site in a hidden iframe. 6 """ 7 8 from django.conf import settings 9 10 class XFrameOptionsMiddleware(object): 11 """ 12 Middleware that sets the X-Frame-Options HTTP header in HTTP responses. 13 14 Does not set the header if it's already set or if the response contains 15 a xframe_options_exempt value set to True. 16 17 By default, sets the X-Frame-Options header to 'DENY'. To have this 18 middleware set it to 'SAMEORIGIN' instead, set X_FRAME_OPTIONS in 19 Django settings to 'SAMEORIGIN'. 20 21 Note: older browsers will quietly ignore this header, thus other 22 clickjacking protection techniques should be used if protection in those 23 browsers is required. 24 25 http://en.wikipedia.org/wiki/Clickjacking#Server_and_client 26 """ 27 def process_response(self, request, response): 28 # Don't set it if it's already in the response 29 if response.get('X-FRAME-OPTIONS', None) is not None: 30 return response 31 32 # Don't set it if they used @xframe_options_exempt 33 if getattr(response, 'xframe_options_exempt', False): 34 return response 35 36 response['X-FRAME-OPTIONS'] = self.get_xframe_options_value(request, 37 response) 38 return response 39 40 def get_xframe_options_value(self, request, response): 41 """ 42 Gets the value to set for the X_FRAME_OPTIONS header. 43 44 By default uses the value from the X_FRAME_OPTIONS Django settings. If 45 not found in settings, defaults to 'DENY'. 46 47 This method can be overridden if needing to flex based on the request 48 or response. 49 """ 50 return getattr(settings, 'X_FRAME_OPTIONS', 'DENY').upper()