Django изменяет request.path в промежуточном программном обеспечении (для аутентификации по токену в URL-адресе)

Уважаемые всезнающие существа в Stackoverflow,

В Django 1.3 я делаю промежуточное ПО process_request, которое получает токен из URL-адреса, регистрирует пользователя (если он правильный) и удаляет токен из URL-адреса. Тем не мение:

I) Django не рекомендует обращаться к данным POST/GET в промежуточном программном обеспечении, я не совсем уверен, почему так... То же самое относится к request.path ? https://docs.djangoproject.com/en/dev/topics/http/middleware/#process-view

II) Я хочу удалить токен из URL-адреса, поэтому /album3/pic42/~53Cr3t70K3n/like/ -> /album3/pic42/like/. Однако изменение request.path не работает. Страница не будет найдена, пока

  • Промежуточное ПО обрабатывает правильно (проверено печатью)

  • Прямой ввод /album3/pic42/like/ работает

  • Ошибка (с токеном) показывает Request URL: http://www.site.com/album3/pic42/like/

Есть ли исправление для этого, или я подхожу к этому с неправильной точки зрения?

Заранее спасибо!

Я только что понял, что для того, чтобы изменить его на стороне клиента, очевидно, мне нужна переадресация (почему я не подумал об этом...). Однако было бы полезно иметь возможность переписать его только на стороне сервера без нового запроса, например, для доступа к персонализированному изображению.


P.s.: подробнее, если нужно, можно пропустить

Я работаю над сайтом, который (будет) отправлять персонализированные электронные письма пользователям. Я хотел бы, чтобы пользователи могли щелкать ссылки в электронной почте и автоматически входить в систему с помощью токена в ссылке электронной почты. Это в дополнение к обычному входу в систему. (Я знаю, что это менее безопасно, потому что люди могут пересылать электронные письма, но этого достаточно для моего сайта). URL-адрес будет выглядеть примерно так: /album3/pic42/~53Cr3t70K3n/like/ (с http://www.site.com раздели, Django делает это)

Я пишу промежуточное программное обеспечение, чтобы соответствовать этому и регистрировать пользователя, когда это необходимо, серверную часть аутентификации для принятия токена в качестве действительных учетных данных и модели токена.


Функция process_request промежуточного ПО: def process_request(self, request):

    if '/~' in request.path:
        result = re.search('(.*)/~(.+?)/(.*)', request.path)
        (uidb36, token) = result.group(2).split('-', 2)
        user = authenticate(uidb36 = uidb36, token = token)
        if user: login(request, user)
        return HttpResponseRedirect('%s/%s' % (result.group(1), result.group(3)) + ('?' + '&'.join('='.join(item) for item in request.GET.items()) if request.GET else ''))
    return None

Прямо сейчас он работает с перенаправлениями, я также хотел бы иметь возможность делать это внутри.


person Mark    schedule 06.11.2011    source источник
comment
Пожалуйста, предоставьте соответствующие части кода вашего промежуточного программного обеспечения.   -  person Ivan Kharlamov    schedule 06.11.2011
comment
Я добавил, спасибо за комментарий   -  person Mark    schedule 06.11.2011
comment
Что вы имеете в виду, когда говорите, что хотели бы сделать это внутри компании?   -  person Ivan Kharlamov    schedule 07.11.2011


Ответы (2)


Если вы не хотите возиться с загрузите обработчики, у меня есть для вас лучшее решение:

  1. Создайте правило в файле urls.py для отслеживания посещений с помощью токенов

    Поместите его в начало urlpatterns, чтобы убедиться, что он будет оцениваться первым. Что-то вроде этого будет делать:

    (r'/~', 'my_app_name.my_redirect_view'),
    
  2. Создайте представление:

    def my_redirect_view(request):
        #Compiled regular expressions work much faster
        beloved_tokens = re.compile(r'(.*)/~(.+?)/(.*)')
        result = beloved_tokens.search(request.path)
        try:
            (uidb36, token) = result.group(2).split('-', 2)
            path_end = result.group(3)
        # We use "try" to be sure that no one had
        # messed with our beloved tokens:
        except AttributeError: 
            raise Http404
        else:
            user = authenticate(uidb36 = uidb36, token = token)
            if user: 
                login(request, user)
                return HttpResponseRedirect('%s/%s' % (result.group(1), result.group(3)) + ('?' + '&'.join('='.join(item) for item in request.GET.items()) if request.GET else ''))
            else:
                raise Http404
    
person Ivan Kharlamov    schedule 06.11.2011
comment
Конечно, вы можете добавить некоторую дополнительную обработку, чтобы удалить токен из request.GET. Но вся концепция остается прежней: нам не нужно ПО промежуточного слоя для решения проблемы. - person Ivan Kharlamov; 07.11.2011
comment
Использование сопоставления URL - хорошая идея, я об этом не подумал! (Хорошей идеей также является добавление try, кроме). Но есть ли способ после этого сопоставить URL-адрес, лишенный токена, потому что ему также нужен метод, который не требует перенаправления... - person Mark; 07.11.2011
comment
@Марк, почему бы тебе не добавить токен в конце URL-адреса? Есть ли конкретная причина, чтобы поставить его посередине? - person Ivan Kharlamov; 07.11.2011
comment
Вы хотите вместо этого сопоставить их с обычными представлениями и прочитать токен либо в начале представления, либо с промежуточным программным обеспечением? r'^album/' вместо r'^album/$', я думаю, это сработает, если я поставлю такие вещи, как r'^album2' перед r'^album' (или это будет соответствовать первому).. . - person Mark; 07.11.2011
comment
В любом случае, если вы используете промежуточное ПО или обычные представления, иметь токен в конце URL-адреса намного лучше. Вероятно, вам следует использовать токен в качестве параметра GET, например ?token=..., и делать так, как предложил @Anurag. - person Ivan Kharlamov; 07.11.2011

IMO изменение request.path более плохо (если его можно назвать плохим) по сравнению с доступом к параметрам GET/POST, поэтому просто передайте токен в качестве параметра GET и войдите в систему на основе токена и не перенаправляйте и не выполняйте модификации request.path

Я рассматриваю токен как добавленный атрибут к действительному URL-адресу, поэтому промежуточное ПО признает это и что-то делает с этим токеном, но URL по-прежнему обрабатывается правильным представлением, поэтому промежуточное ПО мне кажется здесь очень логичным.

person Anurag Uniyal    schedule 06.11.2011
comment
Я вообще не вижу причин использовать промежуточное ПО. - person Ivan Kharlamov; 07.11.2011
comment
Да, я вижу, что GET будет более подходящим для этого, чем request.path, но, по-видимому, это создает проблемы с обработчиками загрузки (которые я еще не знаю, понадобятся ли они мне позже). Но я думаю, что могу использовать GET по крайней мере для перенаправления, и в этом случае этой проблемы не существует! - person Mark; 07.11.2011
comment
@Ivan Kharlamov, но промежуточное ПО упрощает работу и позволяет избежать перенаправления - person Anurag Uniyal; 07.11.2011
comment
@Mark, если вы изменяете обработчики загрузки, вы можете сделать это до промежуточного программного обеспечения токена, и все будет в порядке, промежуточное программное обеспечение csrf также получает доступ к параметрам POST - person Anurag Uniyal; 07.11.2011
comment
@AnuragUniyal, наверное, вы правы, лучше использовать промежуточное ПО. И это СУХОЙ. - person Ivan Kharlamov; 07.11.2011