DRF用户权限和Django发送邮件、itsdangerous模块的使用
DRF的用户权限
看官方文档:https://www.django-rest-framework.org/api-guide/permissions/
全局设置权限
DEFAULT_PERMISSION_CLASSES用来设置默认权限策略
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
# 默认都需要登录验证
'rest_framework.permissions.IsAuthenticated',
)
}
如果未指定,则此设置默认为允许不受限制的访问:
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
单个视图设置
APIView:
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
或者,如果您使用的是@api_view具有基于功能的视图的装饰器。
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@api_view(['GET'])
@permission_classes((IsAuthenticated, ))
def example_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
Django的发送邮件功能
需要开通邮箱里的POP3/SMTP服务,以qq邮箱为例:在设置-账户里开通
会获取一个独立授权码,填到下面的EMAIL_HOST_PASSWORD即可
先在自己的设置settings.py文件配置
# 默认邮箱配置
EMAIL_USE_SSL = True
EMAIL_HOST = 'smtp.qq.com' # smtp服务器地址,163是smtp.163.com
EMAIL_PORT = 465 # 端口号25 or 465
EMAIL_HOST_USER = '792221733@qq.com' # 帐号
EMAIL_HOST_PASSWORD = 'bftekkiohcuybfei' # QQ邮箱的独立授权码
EMAIL_FROM = 'SHANGHUI<792221733@qq.com>' # 收件人看到的发件人,尖括号中的必须与上面的user一致
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
在serializers.py文件发送邮件
from django.core.mail import send_mail
from shanghuishop.settings import dev
# 发送邮件
# 发送邮件
from_email = settings.DEFAULT_FROM_EMAIL
url = 'http://127.0.0.1:8000/users/email_verify/'+token+'/'
html_msg = '<a href=' + url + '>激活链接地址</a>'
# 可以用html_message然后加个a标签确认可以点击
# 必填四个参数,1是邮件主题,2是邮件信息,可以为空用html_message代替
# 3是发件人,4是收件人,类型为一个列表
send_mail('用户邮件激活', '点击链接激活邮箱:'+ url, from_email, ['paul0926@foxmail.com', ], html_message='点击这个激活:'+html_msg)
发送效果为:
Django的itsdangerous模块
先pip安装
pip install itsdangerous
使用加密token
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSS
from shanghuishop.settings import dev
# # tjwss = TJWSS(秘钥, 有效期(单位秒)) 不写的话默认时间为3600秒
# Django项目中setting中自带了一个秘钥直接使用,其他地方 可以先生成一个秘钥,再使用
tjwss = TJWSS(dev.SECRET_KEY, 60*10)
# 要加密的数据
data = {
"email": validated_data['email'],
}
# 加密 tjwss.dumps(数据), 返回bytes类型
token = tjwss.dumps(data).decode()
解密token
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSS
from shanghuishop.settings import dev
# 解密 需要跟加密使用一样的秘钥以及有效期
tjwss = TJWSS(dev.SECRET_KEY, 300)
try:
data = tjwss.loads(token)
# 验证失败,会抛出itsdangerous.BadData异常
except BadData:
return None
发送验证邮件的逻辑和实例
基本逻辑:
- 利用itsdangerous模块对链接中的用户信息加密,生成加密后的用户信息token;
- 调用Django发送邮件的相关方法,进行发送邮件(邮件的配置已经配置好);
- 邮件发送的链接中有一个可变参数,包含着用户id加密后的信息;
- 用户接收到邮件之后,点击链接,跳转到对应的视图类进行处理;
- 负责激活的视图类,解密用户的信息,获取用户id,查询到对应用户(在这个过程会判断被加密的信息是否超时);
- 将对应用户中数据库中用户表中 is_active 字段的值改为1,表示此用户被激活;
- 跳转到首页;
利用put请求发送更新或者验证原邮件
在views.py写一个put请求视图类:
class EmailView(UpdateAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = EmailSerClass
# 获取到email,校验邮箱,数据更新,发送邮件
def get_object(self):
return self.request.user
写一个序列化器,这里发送的是我们要使用的验证地址,下面继续写验证地址的逻辑
class EmailSerClass(serializers.ModelSerializer):
class Meta:
model = Users
fields = ('id', 'email')
def validate(self, attrs):
return attrs
def update(self, instance, validated_data):
'''
:param instance: 视图传递过来的实例对象,get_object获取的
:param validated_data: 校验完的数据
:return:
'''
print('1111111111111111111111111')
print(validated_data)
instance.email = validated_data['email']
instance.save()
# 生成激活链接
# # tjwss = TJWSS(秘钥, 有效期(单位秒)) 不写的话默认时间为3600秒
# Django项目中setting中自带了一个秘钥直接使用,其他地方 可以先生成一个秘钥,再使用
tjwss = TJWSS(settings.SECRET_KEY, 60*60)
# 要加密的数据
data = {
'id': instance.id,
"email": instance.email,
}
# 加密 tjwss.dumps(数据), 返回bytes类型
token = tjwss.dumps(data).decode()
# 发送邮件
from_email = settings.DEFAULT_FROM_EMAIL
url = 'http://127.0.0.1:8000/users/email_verify/'+token+'/'
html_msg = '<a href=' + url + '>激活链接地址</a>'
# 可以用html_message然后加个a标签确认可以点击
# 必填四个参数,1是邮件主题,2是邮件信息,可以为空用html_message代替
# 3是发件人,4是收件人,类型为一个列表
send_mail('用户邮件激活', '点击链接激活邮箱:'+ url, from_email, ['paul0926@foxmail.com', ], html_message='点击这个激活:'+html_msg)
return instance
激活邮箱
先写序列化器:
class EmailVerifySerClass(serializers.ModelSerializer):
class Meta:
model = Users
fields = ('id', 'email', 'is_email_active')
def update(self, instance, validated_data):
instance.id = validated_data['id']
instance.email = validated_data['email']
instance.is_email_active = validated_data['is_email_active']
return instance
再写激活视图类逻辑,先校验再设置Users对象的is_email_active为1
class EmailVerifyView(APIView):
# 激活邮箱
def get(self, request, token):
# 用itsdangerou模块的方法进行解密
ts_obj = TJWSS(settings.SECRET_KEY, 60 * 30)
user_obj = ts_obj.loads(token)
# 设置邮箱验证成功
user_obj['is_email_active'] = 1
print('hhhhhhhhhhhhhhhhhhhh:')
print(user_obj)
# 反序列化验证
ser = EmailVerifySerClass(data=user_obj)
# 验证并打印是否验证成功
print(ser.is_valid())
print('ser.errors:', ser.errors)
print(ser.validated_data)
# 根据id值获取用户
user = Users.objects.get(id=user_obj['id'])
# 设置激活状态为1,保存
user.is_email_active = 1
user.save()
return Response('ok')