如何使用 allauth 和 rest-auth 从 React 前端在 Django 中重新发送确认电子邮件
How to resend confirmation email in Django from a React front end, using allauth and rest-auth
我正在使用 Django 2.0.10 和 rest 框架,rest-auth 和 allauth,以及 React 前端。 Rest-auth 使用 JWT 令牌身份验证提供登录和注销功能,但我不知道如何让用户请求重新发送验证邮件。
我希望用户能够登录并按下 "Resend confirmation email" 按钮。例如,如果他们不小心删除了电子邮件,他们需要能够请求另一个。
我看到 post 建议您可以使用来自 allauth 的 send_email_confirmation,但这需要一个由模板生成的 CSRF 令牌。我试过了following the docs to excempt from csrf, but it doesn't make any different. I also tried setting authentication_classes = () as suggested here。这是我的代码:
设置:
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)
当我 post 到端点 '/api/v1/rest-auth/sendconfirmationemail/' 时,我收到错误 Forbidden:
<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 'same-origin' requests.</p>
编辑:我还尝试按照教程 like this one 将 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;
}
然后我构造我的请求来使用 fetch 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 值与 header 中发送的 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>
提交时出现错误"Method Not Allowed (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 前端请求重新发送电子邮件吗?
我认为我的部分问题是服务器似乎显示 Forbidden (CSRF cookie not set.) error
如果获取请求有不正确的 URL 并且因此没有指向有效的 rest-framework 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')
]
我正在使用 JavaScript fetch() 发送 POST 请求,在 header 中使用身份验证令牌,如下所示:
-H 'Authorization: Token 98254e6004e4a28b9d8cf61e7a7a9ee2fc61009a'
我正在使用 Django 2.0.10 和 rest 框架,rest-auth 和 allauth,以及 React 前端。 Rest-auth 使用 JWT 令牌身份验证提供登录和注销功能,但我不知道如何让用户请求重新发送验证邮件。
我希望用户能够登录并按下 "Resend confirmation email" 按钮。例如,如果他们不小心删除了电子邮件,他们需要能够请求另一个。
我看到 post 建议您可以使用来自 allauth 的 send_email_confirmation,但这需要一个由模板生成的 CSRF 令牌。我试过了following the docs to excempt from csrf, but it doesn't make any different. I also tried setting authentication_classes = () as suggested here。这是我的代码:
设置:
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)
当我 post 到端点 '/api/v1/rest-auth/sendconfirmationemail/' 时,我收到错误 Forbidden:
<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 'same-origin' requests.</p>
编辑:我还尝试按照教程 like this one 将 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;
}
然后我构造我的请求来使用 fetch 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 值与 header 中发送的 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>
提交时出现错误"Method Not Allowed (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 前端请求重新发送电子邮件吗?
我认为我的部分问题是服务器似乎显示 Forbidden (CSRF cookie not set.) error
如果获取请求有不正确的 URL 并且因此没有指向有效的 rest-framework 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')
]
我正在使用 JavaScript fetch() 发送 POST 请求,在 header 中使用身份验证令牌,如下所示:
-H 'Authorization: Token 98254e6004e4a28b9d8cf61e7a7a9ee2fc61009a'