Django搭建个人博客:重置用户密码

4723阅读 · 24评论 · 2018/11/04发布   前往评论

随着技术的发展,验证用户身份的手段越来越多,指纹、面容、声纹应有尽有,但密码依然是最重要的手段。

互联网处处都有密码的身影,甚至变成了现代人的一种负担。像笔者这样的,动辄几十个账号密码,忘记其中几个简直太正常了。

本章讲如何帮助健忘症患者,重置用户密码。

安装第三方库

前面我们已经知道如何修改文章标题、正文等内容,但是密码作为验证身份的重要口令,必须以更加稳妥的方式修改。一种比较常用的方式是发送一封修改密码的邮件到用户事先绑定的邮箱里

业务流程分析如下:

  • 向用户邮箱发送包含重置密码地址的邮件。邮件的地址需要动态生成,防止不怀好意的用户从中捣乱;
  • 向网站用户展示一条发送邮件成功的信息;
  • 用户点击邮箱中的地址后,转入重置密码的页面;
  • 向用户展示一条重置成功的信息。

上面4个步骤包含了4个视图和模板,自己写代码看来有些繁琐。

可能你会想,Django这种以开发效率著称的框架,重置密码这种常用功能是不是内置了呢?答案是肯定的。事实上内置模块的流程和上面的是完全相同的,你只需要将上面4个步骤的url配置好就可以使用了。当然内置的模板很简陋,你可以覆写模板变成自己网站的风格。

实际上Django不仅内置了密码重置,还包括登录、登出、密码修改等功能。建议读者到一定水平后多阅读Django的源码,学习其中的编程技巧。另外这部分内容Django是用类视图写的,现在阅读可能有一定困难。

源码位置:/env/Lib/site-packages/django/contrib/auth/views.py

官方文档:Django 的验证系统

使用内置的模块似乎要简单多了,那还能不能更简单呢?确实是可以的。

Django作为优秀的Web框架,有很多优秀的第三方库(即APP)被世界各地的程序员们打包发布在网上,免费供你使用。成功从来都是站在巨人的肩膀上的,既然已经有了“轮子”,何必要自己再造一个呢。

我们这里就可以用到一个叫Django-password-reset的第三方库。

打开虚拟环境,输入指令pip install -U django-password-reset

(env) E:\django_project\my_blog>pip install -U django-password-reset

Collecting django-password-reset
...
Installing collected packages: django-password-reset
Successfully installed django-password-reset-2.0

看到以上信息说明安装成功了。

快速使用

既然第三方库也是app,那肯定需要在/my_blog/settings.py中注册了:

/my_blog/settings.py

...
INSTALLED_APPS = [
    ...

    'password_reset',    # 新增

    'article',
    'userprofile',
]
...

在根路由/my_blog/urls.py中添加app的地址:

/my_blog/urls.py

...
urlpatterns = [
    ...
    path('password-reset/', include('password_reset.urls')),
]

修改/templates/userprofile/login.html,提供一个重置密码的入口:

/templates/userprofile/login.html

...
<div class="col-12">
    ...
    <form method="post" action=".">
        ...
    </form>

    <!-- 新增 -->
    <br>
    <h5>忘记密码了?</h5>
    <h5>点击<a href='{% url "password_reset_recover" %}'>这里</a>重置密码</h5>
</div>
...

邮件不能凭空产生,目前为止我们并没有配置发件邮箱的账号密码,也没有配置发送邮件的端口、发件人等信息。

因此还需要在/my_blog/settings.py末尾添加发送邮箱的相关配置:

/my_blog/settings.py

...

# SMTP服务器,改为你的邮箱的smtp!
EMAIL_HOST = 'smtp.qq.com'
# 改为你自己的邮箱名!
EMAIL_HOST_USER = 'your_email_account@xxx.com'
# 你的邮箱密码
EMAIL_HOST_PASSWORD = 'your_password'
# 发送邮件的端口
EMAIL_PORT = 25
# 是否使用 TLS
EMAIL_USE_TLS = True
# 默认的发件人
DEFAULT_FROM_EMAIL = 'xxx的博客 <your_email_account@xxx.com>'

简单邮件传输协议 (Simple Mail Transfer Protocol, SMTP) 是在Internet传输Email的协议标准。

SMTP是基于文本的协议。在其之上指定了一条消息的一个或多个接收者,然后消息文本会被传输。SMTP使用TCP端口25。

SMTP是一个“推”的协议(发送邮件),它不允许从远程服务器上“拉”来消息(接收邮件)。要接收邮件,客户端必须使用POP3IMAP

设置好后就可以开启服务器测试了。

点击登录页面:

点击最后一行的链接“这里”:

按照要求输入用户名或者Email,点击确认按钮:

提示已经把重置密码的链接发到邮箱中了。

前往Email中查看新邮件:

居然神奇的收到了邮件!继续点击邮件中的链接:

按照提示输入新密码后:

密码重置就成功了。

尝试一下新密码登录是没问题的,顺利完成了任务。

篇幅关系就没有去挨个覆写原有的模板文件了。如果有兴趣可以仔细阅读官方文档,尝试去改写模板文件,让页面更加匹配自己网站的风格。

官方文档在这里:docs

GitHub:django-password-reset

相信读者也尝到使用三方库的甜头了:只需要写很少的代码,就可以完成大量的功能。笔者是推荐在开发中多使用优秀的三方库的,可以极大的提高效率,减少重复劳动。当然使用三方库也有一些缺点,比如会因为一知半解而维护困难、不能量身定制等。在实践中到底用还是不用,就根据实际情况再做权衡了。

后面陆续还会介绍更多的三方库,还是贯彻那句话:成功是站在巨人肩膀上的。

常见错误

发送邮件因为涉及到了发送邮箱的相关设置和权限,所以容易出各种各样奇怪的问题。

好比说你的发送邮箱设置是xxx@sina.com。项目代码都是对的,但是新浪禁止了smtp服务,那邮件也会发送不成功。如果报错请尝试以下方法:

  • 设置发送邮箱为允许smtp服务
  • 检查账号、密码是否正确
  • 有的发送端口需要额外的设置,尝试更换端口
  • 更换其他服务商的邮箱

如果还不行,就请根据报错页面,搜索一下类似问题的解决方案了。

总结

本章学习了使用第三方库django-password-reset,高效完成了重置密码的功能。

下一章学习扩展并更新用户资料。




本文作者: 杜赛
发布时间: 2018年11月04日 - 18:03
最后更新: 2019年01月28日 - 16:21
知识共享许可协议   转载请保留原文链接及作者


登录 后回复

共有24条评论

avatar
用户5512072591 么么哒! 3

你好,文中的这个:

DEFAULT_FROM_EMAIL = '杜赛的个人网站 <dusaiphoto@foxmail.com>'

应该设置为认证用户的邮箱,否则报错smtplib.SMTPSenderRefused: (501, b'mail from address must be same as authorization user')

还有这里的:

{% url "password_reset_recover" %} 

为什么不要加password_reset:?

11个月前 回复


avatar
杜赛 [博主] 用户5512072591 么么哒! 4

对的,需要改成自己的email,我这里描述得不清楚,有空改过来。

Url反向解析冒号前面的是应用命名空间,即namespace,定义了url所在的app。在实践中建议使用,但也不是必须的。

教程最后一章读者来信中有解释。

11个月前 回复


avatar
jl1014171068 用户5512072591 么么哒! 3

这里好像只能写邮箱,加上其他的会报错surprise,卡了好一会儿,开始还以为是ssl和tsl的设置问题

正常运行代码如下:

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.qq.com' 
EMAIL_PORT = 465
EMAIL_HOST_USER = 'xx@qq.com' # 帐号
EMAIL_HOST_PASSWORD = 'sssssss' # 密码 qq为设置=>账户=>POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务=> 开启服务POP3/SMTP服务=> 生成授权码
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

然后还有遇到一个问题,就是如果数据库中有多个同样email的话,用此email恢复密码会报错 :

  • Unable to find user.

    需要到数据库查看,email不能重复

4个月前 回复


avatar
77777qazxsw7 么么哒! 6

如果是使用QQ邮箱来发送邮件的话,/my_blog/settings.py这里的密码是你的授权码(你开启smtp的时候有给你),不是你的邮箱密码

# 你的邮箱密码
EMAIL_HOST_PASSWORD = 'your_password'

给后来的人提个醒哈~

7个月前 回复


avatar
77777qazxsw7 77777qazxsw7 么么哒! 3

顺便感谢下博主,教程好全,对我这种萌新太友好了angel

7个月前 回复


avatar
杜赛 [博主] 77777qazxsw7 么么哒! 3

不客气。

对的,QQ邮箱比较特别,它有两个密码,登陆密码独立密码..实在搞不清楚就两个密码都试一试吧。

感谢提醒~

7个月前 回复


avatar
pidada 77777qazxsw7 么么哒! 3

提醒太到位了!是到里面去设置进行获取的,不是QQ密码也不是QQ邮箱的独立密码

6个月前 回复


avatar
ac1864 77777qazxsw7 么么哒! 3

https://service.mail.qq.com/cgi-bin/help?subtype=1&&no=1001256&&id=28

qq 邮箱的文档还是比较全,一下子就搞定了。

6个月前 回复


avatar
台风利齐马 77777qazxsw7 么么哒! 3

感谢提醒啊,哈哈一开始真不行,就是需要那个码,而且还得发短信!我还发了好几次。yes

3个月前 回复


avatar
ac1864 么么哒! 3

这个模块被qq邮箱的授权码卡了一下。

6个月前 回复


avatar
pengshilin 么么哒! 3

今天先做到这里
博主的教程涉及到的都是博客实实在在的功能,做起来比较有成就感blush

6个月前 回复


avatar
杜赛 [博主] pengshilin 么么哒! 3

我自己也比较适合这种做实践的学习方式。

基础知识学久了就会感觉很枯燥,还是把知识应用起来有意思

6个月前 回复


avatar
jl1014171068 么么哒! 3
本回复已被 jl1014171068 删除

4个月前 回复


avatar
luoluoluol 么么哒! 1

当你主机名有中文的时候会报UnicodeEncodeError

3个月前 回复


avatar
xuzhiyi1998 么么哒! 1

请问这个{% url 'password_reset_recover' %}是哪里来的

1个月前 回复


avatar
杜赛 [博主] xuzhiyi1998 么么哒! 1

模块提供的

1个月前 回复


avatar
dfr 么么哒! 1

博主你好,我输入完需要重置密码的地址之后,点击recover my password,之后跳转的页面是错误的。页面是这个样子的,不知道怎么解决了

gaierror at /password-reset/recover/

[Errno 11001] getaddrinfo failed

Request Method:POSTRequest URL:http://127.0.0.1:8000/password-reset/recover/Django Version:2.2.6Exception Type:gaierrorException Value:

[Errno 11001] getaddrinfo failed

Exception Location:C:\Users\hp\AppData\Local\Programs\Python\Python37\lib\socket.py in getaddrinfo, line 748Python Executable:C:\Users\hp\PycharmProjects\django_project\venv\Scripts\python.exePython Version:3.7.1Python Path:

['C:\\Users\\hp\\PycharmProjects\\django_project',
 'C:\\Users\\hp\\PycharmProjects\\django_project\\venv\\Scripts\\python37.zip',
 'C:\\Users\\hp\\AppData\\Local\\Programs\\Python\\Python37\\DLLs',
 'C:\\Users\\hp\\AppData\\Local\\Programs\\Python\\Python37\\lib',
 'C:\\Users\\hp\\AppData\\Local\\Programs\\Python\\Python37',
 'C:\\Users\\hp\\PycharmProjects\\django_project\\venv',
 'C:\\Users\\hp\\PycharmProjects\\django_project\\venv\\lib\\site-packages',
 'C:\\Users\\hp\\PycharmProjects\\django_project\\venv\\lib\\site-packages\\setuptools-40.8.0-py3.7.egg',
 'C:\\Users\\hp\\PycharmProjects\\django_project\\venv\\lib\\site-packages\\pip-19.0.3-py3.7.egg']

Server time:Thu, 24 Oct 2019 03:03:07 +0000

1个月前 回复


avatar
杜赛 [博主] dfr 么么哒! 1

搞不定就先跳过吧,这个模块在后面的教程中有更好的替代

1个月前 回复


avatar
一瓶红枣酸奶 么么哒! 2

要下源码,改模板吗

26天前 回复


avatar
Ghost 么么哒! 1

你好

在Django搭建个人博客:重置用户密码时输入pip install -U django-password-reset  命令后

结果为:Traceback (most recent call last):

  File "d:\python37\lib\runpy.py", line 192, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "d:\python37\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "D:\Python37\Scripts\pip.exe\__main__.py", line 4, in <module>
ModuleNotFoundError: No module named 'pip._internal.main'

求解决方法

16天前 回复


avatar
杜赛 [博主] Ghost 么么哒! 1

安装其他的库也有这个问题?换一个 pip 版本试试

16天前 回复


avatar
Ghost 杜赛 [博主] 么么哒! 1

都有问题,已经试过

16天前 回复


avatar
杜赛 [博主] Ghost 么么哒! 1

考虑是否 python 或 pip 安装问题,试试换个版本重新安装

15天前 回复


avatar
Ghost 杜赛 [博主] 么么哒! 1

好的,谢谢,已经弄好

14天前 回复