3

Here's my goal:

  • the user wants to login
  • I make a button on each page with the urlback as a parameter, for example if we are on the page http://olivier.life/today, the button to login will have an url like http://olivier.life/login?back=today
  • the user logs in
  • once the user is logged in, i check if there's a "back" in the "GET" request. if so then I make a redirect to the url in the GET

My problem is a security problem: I just want to know if the URL in the GET is part of my application (is valid for one of the URLs in the urls.py file).

How to do this?

Olivier Pons
  • 15,363
  • 26
  • 117
  • 213

2 Answers2

1

You can use the urlresolver's resolve method, the method throws an exception if it can't resolve an URL, you can read more about urlresolver here:

from django.core.urlresolvers import resolve, Resolver404

def yourView(request):
  try:
    if hasattr(request.GET, 'back'):
      resolve(request.GET['back'])
      return HttpResponseRedirect(request.GET['back'])
  except Resolver404:
      return Response('some other thing')
fixmycode
  • 8,220
  • 2
  • 28
  • 43
  • 2
    Use `in` rather than `hasattr` if you want to test for presence in a dict-like object such as `request.GET`. – Peter DeGlopper Sep 21 '15 at 22:58
  • @PeterDeGlopper it's more a question of personal preference, there is no benefit in it :) http://stackoverflow.com/questions/9748678/which-is-the-best-way-to-check-for-the-existence-of-an-attribute – fixmycode Sep 21 '15 at 23:00
  • 3
    You're not checking for an attribute. `request.GET.back` is not expected to work. `request.GET` is an instance of a subclass of `dict`, and `in` is the correct way to test for membership in a dict. – Peter DeGlopper Sep 21 '15 at 23:02
  • 2
    Just to be explicit for anyone else reading this - this is not just a disagreement about style. The posted code is incorrect. `hasattr` will not report `True` when checking a `QueryDict` object such as `request.GET` for a key. I am not downvoting because the important part of the answer (using `resolve`) is correct, but the `if hasattr(request.GET, 'back')` check will always return `False` – Peter DeGlopper Sep 22 '15 at 05:20
1

Use resolve. There's an example that's very close to this use case in the docs. I think for your case you want something like:

def some_view(request):
    redirect_target = request.GET.get('back')
    if redirect_target:
        try:
            resolve_match = django.core.urlresolvers.resolve(redirect_target)
        except django.core.urlresolvers.Resolver404:
            # do something on bad input
        else:
            return django.shortcuts.redirect(redirect_target)
    else:
        # empty string redirect target, or not provided at all
        # do something else
Peter DeGlopper
  • 36,326
  • 7
  • 90
  • 83
  • I'm having a problem: if you use the translation url system here https://docs.djangoproject.com/en/1.8/topics/i18n/translation/ you will see you add patterns like `urlpatterns += i18n_patterns(...)`. The problem is that the base url **without** the language is not taken in account ie: `resolve('/fr/produits/')` works, `resolve('/uk/produits/')` works, but `resolve('/produits/')` doesnt work and raises 404. – Olivier Pons Sep 23 '15 at 11:48
  • 2
    For the sake of any future readers - this answer will not work easily with the i18n framework, but the answer here looks good to me: http://stackoverflow.com/a/32739937/2337736 – Peter DeGlopper Sep 25 '15 at 05:18