【问题标题】:Djanog with React how to reset user password by sending user an email带有 React 的 Django 如何通过向用户发送电子邮件来重置用户密码
【发布时间】:2019-07-17 07:01:43
【问题描述】:

我正在使用带有 React 的 Django,我正在实现一种在用户忘记密码时重置用户密码的方法。我的基本想法是:

1) 用户提供他们的电子邮件地址

2) 向他们的电子邮件地址发送一封电子邮件,其中包含重置密码的链接(使用 SendGrid api)

3) 用户输入新密码以重置密码

下面是我的序列化器、视图、url 和 React 代码

//views.py
class PasswordResetConfirmSerializer(serializers.Serializer):
    new_password1 = serializers.CharField(max_length=128)
    new_password2 = serializers.CharField(max_length=128)
    uid = serializers.CharField()
    token = serializers.CharField()

    set_password_form_class = SetPasswordForm
    def custom_validation(self, attrs):
        pass
    def validate(self, attrs):
        self._errors = {}
        try:
            self.user = UserModel._default_manager.get(pk=attrs['uid'])
        except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist):
            raise ValidationError({'uid': ['Invalid value']})
        self.custom_validation(attrs)
        self.set_password_form = self.set_password_form_class(
            user=self.user, data=attrs
        )
        if not self.set_password_form.is_valid():
            raise serializers.ValidationError(self.set_password_form.errors)
        return attrs
    def save(self):
        return self.set_password_form.save()

// serializers.py
class PasswordResetConfirmView(GenericAPIView):
    serializer_class = PasswordResetConfirmSerializer
    permission_classes = (AllowAny,)

    @sensitive_post_parameters_m
    def dispatch(self, *args, **kwargs):
        return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(
            {"detail": ("Password has been reset with the new password.")}
       )

//urls.py
path('api/passwordreset/confirm/',views.PasswordResetConfirmView.as_view(), name = 'password_reset_confirm')

// React 
    const config = {
    headers: {
      "Content-Type": "application/json"
      }
    };

    const body = JSON.stringify({ 
        new_password1: this.state.new_password,
        new_password2: this.state.confirm_password,
        uid: this.state.fetched_data.pk,
        token: this.state.fetched_data.token
    })

    axios.post(API_URL + 'users/api/passwordreset/confirm/', body, config)

我的重置密码功能本身可以正常工作。但我在这里遇到的主要问题是重置密码 API 需要“uid”和“token”。为了获得这两个值,用户必须要么登录,因为他们忘记了密码,这没有任何意义,要么调用 api 来获取“uid”和“token”。我尝试了以下方法来获取这两个值:

// views.py
class CustomObtainAuthToken(ObtainAuthToken):
    def post(self, request, *args, **kwargs):
        response = super(CustomObtainAuthToken, self).post(request, *args, **kwargs)
        token = Token.objects.get(key=response.data['token'])
        return Response({'token': token.key, 'id': token.user_id})

// urls.py
path('api/authenticate/', CustomObtainAuthToken.as_view())

// React 
const body = { 
    password: 'mike',
    username: 'Abcd1234'
  }

  await axios.post(API_URL + 'users/api/authenticate/', body)

该函数确实返回了正确的“uid”和“token”,但问题是我从用户那里得到的唯一信息是电子邮件地址。我无法同时获取密码和用户名来调用此 API。所以我不太确定该怎么做。

有人可以告诉我完成这项工作的正确方法吗?非常感谢。

【问题讨论】:

    标签: django reactjs django-rest-framework


    【解决方案1】:

    首先,您可以从请求密码重置流程的用户的电子邮件中获取uid。其次,此令牌与您的已验证用户的令牌不同。这个令牌can be generated with django's default_token_generator

    这是通常的流程:

    1. 用户给email
    2. 前端命中是一个带有 email 的 API(即 /api/password_reset/
    3. a) API 确定是哪个useremail,从而获得uid
      b) 为该user 生成一个token
      c) 发送带有 url 的电子邮件。 url 必须包含 uidtoken 作为其一部分(例如,https://example.com/password-reset-confirm/<uid>/<token>
    4. 这个链接被用户点击,它在前端显示一个页面,要求一个新的password这里注意:这个url包含一个uid和一个稍后将使用的令牌)
    5. 用户提供了一个新的password
    6. 前端使用新提供的密码以及 uidtoken(它们是 URL 的一部分)进行 API 调用(即 /api/password_reset_confirm/
    7. API 接收uidtoken 和新的password
      a) 它检查uidtoken 是否有效(即token 与它先前为uid 的相同user 生成的匹配)
      b) 它设置了uiduser 的新密码
      c) 可选地,它可以将该用户从系统中注销

    由于您使用的是 DRF,请查看implementation of an authentication library named Djoser。这可能是一次很好的学习体验。

    【讨论】:

    猜你喜欢
    • 2011-04-16
    • 2021-03-08
    • 1970-01-01
    • 2015-06-10
    • 2022-11-24
    • 2018-12-05
    • 2015-03-12
    • 2019-12-15
    • 2015-07-31
    相关资源
    最近更新 更多