токен csrf для ajax в django2 - PullRequest
       17

токен csrf для ajax в django2

0 голосов
/ 03 июля 2018

Я изучаю Django2 и пытаюсь создать страницу входа с помощью csrf_token и ajax.

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

Я читаю документы Django2 и пытаюсь кодировать, как показано ниже, однако, когда я нажимаю кнопку «ВХОД», он просто обновляет страницу входа и не выдает ошибку

Я запутался и понятия не имею. Пожалуйста, помогите.

просмотров:

def login(request):
    if request.is_ajax():
        uf = UserForm(request.POST)
        if uf.is_valid():
            # get info from form
            username = uf.cleaned_data['username']
            password = uf.cleaned_data['password']
            user = auth.authenticate(request, username=username, password=password)
            if user is not None:  # user match
                auth.login(request, user)
                if request.GET.get('next'):
                    next_url = request.GET.get('next')
                    return JsonResponse({'redirect_url': next_url})
                    # return redirect(request.GET.get('next'))
                else:
                    return JsonResponse({'redirect_url': 'home'})
            else:  # user not match
                error_msg = ["username or pwd mistake"]
                return JsonResponse({'error_msg': error_msg})
    else:
        uf = UserForm()
    return render(request, 'login.html', {'uf': uf})

HTML:

    <form>
      {% csrf_token %}
       {{ uf.username }}
       {{ uf.password }}
      <div id="errorMsg"></div>
        <button type="submit" class="btn btn-default" id="loginButton">login</button>
     <input type="hidden" name="next" id="redirect-next" value="{{ next|escape }}"/>
   </form>

JQuery:

       $("#loginButton").click(function () {
    $.ajax({
        url: "",
        type: 'POST',
        dataType: "json",
        data: {username: $("#inputEmail3").val(), password: $("#inputPassword3").val()},
        beforeSend: function (xhr, settings) {
            var csrftoken = Cookies.get('csrftoken');
            function csrfSafeMethod(method) {
                // these HTTP methods do not require CSRF protection
                return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
            }
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        },
        success: function (result) {
            if (result.error_msg) {
                $('#errorMsg').show().text('user info error') //print an alert on the page
            }
            else {
                location.href = result.redirect_url //turn to homepage or page before login
            }
        }
    })
});

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

Вам не нужно прилагать усилия для написания собственного вида входа в систему, подобного этому. Django предоставляет более простые методы для его реализации.

Сначала убедитесь, что в ваше settings.py

включено следующее
MIDDLEWARE_CLASSES = [
    ...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ...
]
INSTALLED_APPS = [
    ...
    'django.contrib.auth',
    'django.contrib.contenttypes',
    ...
]

Добавьте все URL-адреса для входа на главную urls.py:

from django.urls import path
from django.conf.urls import include


urlpatterns = [
....
    path('accounts/', include('django.contrib.auth.urls')),
....
]

Не забудьте запустить python manage.py migrate, чтобы создать таблицы, необходимые для приложения auth. Теперь, когда приложение и URL-адреса готовы, необходимо создать шаблоны. Все шаблоны для приложения должны быть помещены в папку с именем registration в каталоге templates. Структура каталогов должна быть примерно такой.

your_django_app/
    templates/
        registration/
            login.html
    __init__.py
    apps.py
    settings.py
    urls.py
    views.py
    wsgi.py

Содержимое login.html должно быть примерно таким:

<form id="loginform" action="{% url 'login' %}" method="POST">
{% csrf_token %}
{% if next %}
    <input type="hidden" name="next" value="{{ next }}" />
{% endif %}
    <input name="username" id="id_username" type="text">
    <label>Username</label>
    <input name="password" id="id_password" type="password">
    <label>Password</label>
{% if form.errors %}
    Error! Wrong credentials.
{% endif %}
    <button type="submit">Login</button>
</form>

После этого включите их в файл settings.py для правильного перенаправления пользователей после входа в систему.

LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/accounts/login'

Вы все готовы идти. Обязательно создайте хотя бы одного пользователя, прежде чем попробовать это, запустив python manage.py createsuperuser. Для всех страниц, требующих входа пользователей перед их просмотром, вы можете использовать декоратор @login_required над их соответствующими функциями просмотра, чтобы перенаправить их на страницу входа перед отображением страницы. Пример: * +1028 *

from django.shortcuts import render
from django.contrib.auth.decorators import login_required

@login_required
def home(request):
    return render(request, 'home/index.html')
0 голосов
/ 03 июля 2018

Здесь есть короткий и простой способ разбора csrf_token с помощью ajax:

Внутри тега скрипта.

    $.ajax({
           url: window.location.pathname,
           type: 'POST',
           data: {
                 ......,
                // Note this step.
                'csrfmiddlewaretoken': "{{ csrf_token }}"
                },
                success: function() {
                   .....
                }
    });

Надеюсь, все работает хорошо, так как я использовал эту вещь для анализа csrf_token в моих проектах на основе Django. Ура!

0 голосов
/ 03 июля 2018

Это может быть связано с проблемой

Поскольку ваша кнопка пытается отправить форму, но вы хотите, чтобы она была обработана сценарием.

попробуйте изменить тип кнопки на

type="button" 
...