【软软软-技术博客】使用邮箱验证并激活账户

为什么需要使用邮箱验证账户?

我们的项目的特殊之处在于,是通过向用户邮箱发送邮件的方式来实现DDL的提醒的,因此需要确保用户的邮箱是正确的,如果注册时使用的邮箱是错误的,不仅会导致用户收不到DDL提醒邮件,也会打扰到别人。

此外,我们选择使用北航邮箱进行验证,这样做还有一个好处在于,北航邮箱是绑定学号的,即可以直接使用“学号@buaa.edu.cn”的格式来发送邮件。这样在创建账户时,可以确保用户输入的是自己的学号,而不能冒名顶替使用他人的学号注册。

技术原理

1. 在数据库中为User增加is_active字段

为了实现没有完成邮箱验证的用户不能登陆,我们在数据库中的User实体中添加了is_active字段,以标识用户好是否激活,并在用户登录时检查账户是否激活,如果未激活就不能登陆。在用户完成邮箱验证后,将该用户的is_active字段设置为True(已激活)。

class User(models.Model):
    '''
    Other attributes...
    '''
    is_active = models.BooleanField(default=False)   

2. 生成激活链接并发送激活邮件

为了给每个用户生成其独立的激活链接,我们新建了一个Token类,通过itsdangerous中的URLSafeTimedSerializer类来生成和验证Token。调用Token类,使用用户的uid+SECRET_KEY结合生成token,并将这个token加入激活链接的url部分。

class Token():
    def __init__(self, security_key):
        self.security_key = security_key
        self.salt = base64.b64encode(security_key.encode(encoding='utf-8'))

    def generate_validate_token(self, username):
        serializer = utsr(self.security_key)
        return serializer.dumps(username, self.salt)

    def confirm_validate_token(self, token, expiration=3600):
        serializer = utsr(self.security_key)
        return serializer.loads(token, salt=self.salt, max_age=expiration)
def create_user(request): # 用户注册
    '''
    Other codes...
    '''
		token_confirm = Token(settings.SECRET_KEY)
		token = token_confirm.generate_validate_token(data["uid"]) # 根据uid生成token
  	message = "\n".join([
            u'亲爱的 {0} {1}, 欢迎使用ddl_killer'.format(data["uid"], data['username']),
            u'请访问该链接,完成用户验证: <a href="http://123.57.67.161:8000/api/activate/?							token={0}">ddl_killer 注册链接</a>'.format(token),
            u'ddl_killer 团队致上.'])

在发送邮件部分,我们使用了yagmail来发送邮件。

# 四个参数从左到右分别是:收件邮箱地址,邮件标题,邮件内容,附件
settings.YAG.send([data['email']], u'ddl_killer 注册用户验证信息', message, None)

3. 响应激活链接并激活用户

在Django后端收到激活链接格式的url请求时,将进入active_user视图,完成用户的激活。

def active_user(request): 
    token = request.GET['token']
    token_confirm = Token(settings.SECRET_KEY)
    try:
        uid = token_confirm.confirm_validate_token(token)
        print(uid)
    except:
        return HttpResponse(u'对不起,验证链接已经过期')
    try:
        user = User.objects.get(uid=uid)
    except User.DoesNotExist:
        return HttpResponse(u'对不起,您所验证的用户不存在,请重新注册')
    user.is_active = True
    user.save()
    confirm = u'验证成功,请进行登录操作。'
    return HttpResponseRedirect('/', {'msg':confirm}) # 重定向回登陆页面

其他应用

了解邮箱验证的原理之后,就可以使用邮箱+token的组合完成许多其他功能了,例如:

  1. 忘记密码时,可以通过向北航邮箱发送邮件的方式重设密码;
  2. 用户更改提醒邮箱时,需要向新邮箱发送邮件确认。
posted @ 2020-05-22 10:38  杨久春  阅读(302)  评论(0编辑  收藏  举报