如何在Django中使用TimestampSigner反向匹配网址?

时间:2019-05-24 15:24:16

标签: django

要在我的Django Web应用程序中注册用户,我创建了功能,该功能发送一个密码签名的链接到已验证的电子邮件地址,使他们可以访问用户注册页面。现在的下一步是确保链接在设置的时间后过期,但这比预期的要难。

通过这个,我一直在使用内置的Django Signer函数,现在的想法是将其转换为TimestampSigner函数。为此,我已阅读并遵循: https://docs.djangoproject.com/en/2.2/topics/signing/#verifying-timestamped-values

这是我的代码:

在models.py中:

class GenerateUserRegistration(models.Model):
    signer = TimestampSigner(sep='/', salt='users.GenerateUserRegistration')

    def get_registration_url(self, pk):
        signed_pk = self.signer.sign(pk)
        domain = Site.objects.get_current().domain
        path = str(reverse('register', kwargs={'signed_pk': signed_pk}))
        registration_url = 'http://{domain}{path}'.format(domain=domain, path=path)
        return registration_url

在views.py中:

def register(request, signed_pk):
    try:
        pk = GenerateUserRegistration.signer.unsign(signed_pk, max_age=30)
        confirmed = Program.objects.get(id=pk)
    except (BadSignature, GenerateUserRegistration.DoesNotExist):
        raise Http404(signed_pk)

def generate_user_registration_email(request):
...
        UserGenerator = GenerateUserRegistration()
        user_registration_url = UserGenerator.get_registration_url(pk)
        send_mail('app specific data')
...        

在urls.py中:

urlpatterns = [
...
        re_path(r'register/(?P<signed_pk>[0-9]+/[A-Za-z0-9_=-]+)/$', user_views.register,name='register'),
...

当使用TimestampSigner而不是Signer运行程序时(它的工作原理与预期的一样),它引发以下错误:

  

“ NoReverseMatch位于/ admin / generate-user-registration   找不到带有关键字参数'{'signed_pk':'1 / 1hUBvf / 3EiPZDorfNCqovGyDjoO--9oyTQ'}的'register'。尝试了1个模式:['register /(?P [0-9] + / [A-Za-z0-9 _ =-] +)/ $']“

这使我相信我必须以某种方式修改URL以适应TimestampSigner,但是我在文档中找不到任何内容。在那里需要修改什么才能使其起作用?

谢谢!

1 个答案:

答案 0 :(得分:0)

urlpatterns中的正则表达式必须与带符号的字符串的格式匹配。如the documentation中所述,带有时间戳的带符号字符串的格式与常规带符号字符串的格式不同;具体来说,它“将签名时间戳附加到该值上。”

因此您需要更改url模式以使其匹配,即:

r'register/(?P<signed_pk>[0-9]+/[A-Za-z0-9_=-]+/[A-Za-z0-9_=-]+)/$'

但是,我建议您不要使用/作为分隔符,因为该字符在URL中具有语义。使用$之类的URL safe字符。