Как повторно отправить электронное письмо с подтверждением в Django из внешнего интерфейса React, используя allauth и rest-auth - PullRequest
0 голосов
/ 03 февраля 2019

Я использую Django 2.0.10 с каркасом rest, rest-auth и allauth, с интерфейсом React.Rest-auth предоставляет функции входа и выхода с использованием аутентификации токена JWT, но я не могу понять, как разрешить пользователю запрашивать повторную отправку подтверждающего электронного письма.

Я хочу, чтобы пользователь мог войти в системуи нажмите кнопку с надписью «Отправить письмо с подтверждением».Например, если они случайно удалили электронное письмо, они должны иметь возможность запросить другое.

Я видел сообщения, в которых предлагается использовать send_email_confirmation от allauth, но при этом ожидается, что токен CSRF будет сгенерированшаблон.Я пытался , следуя документам , освободить от csrf, но это ничего не изменило.Я также попытался установить authentication_classes = () , как предложено здесь .Вот мой код:

настройки:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
}

urls.py

from users.views import EmailConfirmation

urlpatterns = [
...
url(r'^/sendconfirmationemail/', EmailConfirmation.as_view(), name='send-email-confirmation')
]

views.py

from rest_framework.views import APIView
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator

class EmailConfirmation(APIView):
    @method_decorator(csrf_exempt)
    authentication_classes = ()

    def post(self):
        send_email_confirmation(user=self.request.user)

Когда я публикую вконечная точка '/ api / v1 / rest-auth / sendconfirmationemail /', я получаю сообщение об ошибке Запрещено:

<p>You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.</p>
<p>If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for &#39;same-origin&#39; requests.</p>

Редактировать: я также пытался добавить токен CSRF в свой запрос, следуя инструкциям какэтот .Но у меня та же проблема.Вот что я попробовал:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            //var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

И затем я строю свой запрос на использование API выборки следующим образом:

curl 'http://localhost:3000/api/v1/rest-auth/sendconfirmationemail/' -H 'Authorization: Token 55c8da5de68b657cf9dafd820a7f02f997fa3d64' -H 'Origin: http://localhost:3000' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' -H 'Content-Type: text/plain;charset=UTF-8' -H 'Accept: */*' -H 'Referer: http://localhost:3000/account' -H 'Connection: keep-alive' -H 'X-CSRFToken: YOHB6RXqpZMFIXKT31T9tAjaUsH0w3eIjaaCvbgAqmP64SWeVNd3Sz3g8nZUEmVS' --data-binary 'csrfmiddlewaretoken=YOHB6RXqpZMFIXKT31T9tAjaUsH0w3eIjaaCvbgAqmP64SWeVNd3Sz3g8nZUEmVS' --compressed

Когда я смотрю на рабочие примеры из шаблонов Django, я вижучто значение csrfmiddlewaretoken, отправленное с данными формы, не совпадает с значением X-CSRFToken, отправленным в заголовке - я думаю, что значение, предоставляемое шаблонами Django, является соленым, и это может иметь значение.Но никакие инструкции, которые я могу найти, не подскажут, как получить правильное значение?Или я получаю запрос на выборку в неправильной форме?

Если я использую эту форму на своей странице React:

<form action="api/v1/sendconfirmationemail" method="post">
<Input type="hidden" name="csrfmiddlewaretoken"  value={this.getCookie('csrftoken')} />
<button type="submit">Send</button>
</form>

Когда я отправляю ее, я получаю сообщение об ошибке "Способ неРазрешено (POST): / api / v1 / sendconfirmationemail ".CURL из этого запроса:

curl 'http://localhost:3000/api/v1/sendconfirmationemail' -H 'Cookie: csrftoken=YOHB6RXqpZMFIXKT31T9tAjaUsH0w3eIjaaCvbgAqmP64SWeVNd3Sz3g8nZUEmVS; sessionid=uslpdgd5npa6wyk2oqpwkhj79xaen7nw' -H 'Origin: http://localhost:3000' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8' -H 'Cache-Control: max-age=0' -H 'Referer: http://localhost:3000/account' -H 'Connection: keep-alive' --data 'csrfmiddlewaretoken=YOHB6RXqpZMFIXKT31T9tAjaUsH0w3eIjaaCvbgAqmP64SWeVNd3Sz3g8nZUEmVS' --compressed

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

1 Ответ

0 голосов
/ 07 февраля 2019

Я думаю, что часть моей проблемы заключалась в том, что сервер, по-видимому, показывает Forbidden (CSRF cookie not set.) error, если запрос на выборку имеет неправильный URL-адрес и поэтому не указывает на действительный URL-адрес структуры отдыха.Это заставило меня гоняться за проблемами CSRF вместо двойной проверки моего URL.

Я надеюсь, что это поможет кому-то еще.Вот мой рабочий код:

users / views.py

from allauth.account.signals import email_confirmed
from django.dispatch import receiver
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated

from allauth.account.utils import send_email_confirmation
from rest_framework.views import APIView

from . import models
from . import serializers

from rest_framework.authentication import TokenAuthentication
from rest_framework import status
from rest_framework.response import Response

class UserListView(generics.ListCreateAPIView):
    queryset = models.CustomUser.objects.all()
    serializer_class = serializers.UserSerializer
    authentication_classes = (TokenAuthentication,)

# when the email is confirmed, set a field on the user
# so the UI can check whether to show the "Resend confirmation email" button
@receiver(email_confirmed)
def email_confirmed_(request, email_address, **kwargs):
    user = email_address.user
    user.email_verified = True

    user.save()

# request a new confirmation email
class EmailConfirmation(APIView):
    permission_classes = [IsAuthenticated] 

    def post(self, request):
        if request.user.email_verified:
            return Response({'message': 'Email already verified'}, status=status.HTTP_201_CREATED)

        send_email_confirmation(request, request.user)
        return Response({'message': 'Email confirmation sent'}, status=status.HTTP_201_CREATED)

api / urls.py

from users.views import EmailConfirmation

urlpatterns = [
...
    path('sendconfirmationemail/', EmailConfirmation.as_view(), name='send-email-confirmation')
]

Я отправляю запрос POST с помощью JavaScript fetch (), с токеном аутентификации в заголовке, как это:

-H 'Authorization: Token 98254e6004e4a28b9d8cf61e7a7a9ee2fc61009a' 
...