定义 QQ 登录模型类
1. 定义模型类基类
在内层 meiduo_mall 中 添加新的包 utils
在这个包中增加 BaseModel.py 文件.
在这个文件里,添加如下的代码,这里的代码主要作为别的模型类的基类来使用.
增加数据新建时间和更新时间:
from django.db import models class BaseModel(models.Model): """为模型类补充字段""" # 创建时间: create_time = models.DateTimeField(auto_now_add=True,verbose_name="创建时间") 更新时间: update_time = models.DateTimeField(auto_now=更新时间) Meta: 说明是抽象模型类(抽象模型类不会创建表) abstract = True
上面代码中相关参数解读: auto_now_add: 创建或添加对象时自动添加时间,修改或更新对象时,不会更改时间 auto_now: 凡是对对象进行操作(创建/添加/修改/更新),时间都会随之改变 abstract: 声明该模型类仅继承使用,数据库迁移时不会创建 BaseModel 的表
2. 定义 QQ 需要使用的登录模型类
在 oauth.models.py 中添加如下模型类,用于存放 user 和 openid:
导入: models from meiduo_mall.utils.BaseModel BaseModel 定义QQ登录的模型类: OAuthQQUser(BaseModel): QQ登录用户数据 user 是个外键,关联对应的用户 user = models.ForeignKey('users.User',on_delete=models.CASCADE,1)">用户 qq 发布的用户身份id openid = models.CharField(max_length=64openidTrue) Meta: db_table = tb_oauth_qq verbose_name = verbose_name_plural = verbose_name
QQLoginTool 使用说明
1. 导入
使用时,需要导入该包: # 我们可以从下载的 QQLoginTool 中导入 OAuthQQ: from QQLoginTool.QQtool import OAuthQQ
2. 初始化 OAuthQQ 对象
创建对象 创建对象的时候,需要传递四个参数: oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,client_secret=settings.QQ_CLIENT_SECRET,redirect_uri=settings.QQ_REDIRECT_URI,state=next)
相关参数解读:
client_id: 在 QQ 互联申请到的客户端 id
client_secret: 我们申请的客户端秘钥
redirect_uri: 我们申请时添加的: 登录成功后回调的路径
state: 就是我们之前接收的 next 参数
3. 对象提供的方法一: 获取 QQ 地址.
获取 QQ 登录扫码页面,扫码后得到 Authorization Code( 特许码 )
调用对象的 get_qq_url() 函数,获取对应的扫码页面:
login_url = oauth.get_qq_url()
4. 对象提供的方法二: 获取 QQ 的 access_token.
通过上面一个函数获取的 Authorization Code
再获取 Access Token
调用对象的方法,根据 code 获取 access_token:
access_token = oauth.get_access_token(code)
5. 对象提供的方法二: 获取 QQ 的 access_token.
通过上面一个函数获取的 Access Token
再获取 OpenID
QQ 登录接口的制定
获取 QQ 登录扫码页面接口
OAuthQQ
from django.conf settings
from django http
from django.views View
QQFirstView(View):
提供QQ登录页面网址def get(self,request):
next 表示从哪个页面进入到的登录页面
将来登录成功后,就自动回到那个页面
next = request.GET.get(next)
获取 QQ 登录页面网址
创建 OAuthQQ 类的对象
oauth = OAuthQQ(client_id=next)
调用对象的获取 qq 地址方法
login_url = oauth.get_qq_url()
返回登录地址
return JsonResponse({code: 0,errmsg': OKlogin_url':login_url})
QQ 登录参数
QQ登录参数 我们申请的 客户端id
QQ_CLIENT_ID = 101474184'
我们申请的 客户端秘钥
QQ_CLIENT_SECRET = c6ce949e04e12ecc909ae6a8b09b637c 我们申请时添加的: 登录成功后回调的路径
QQ_REDIRECT_URI = http://www.meiduo.site:8080/oauth_callback.html'
添加子路由
获取 QQ 扫码登录链接
re_path(r^qq/authorization/$',views.QQFirstView.as_view()),
第二个接口
from oauth.models OAuthQQUser
logging
logger = logging.getLogger(django)
from django.contrib.auth login
from oauth.utils generate_access_token
QQUserView(View):
用户扫码登录的回调处理Oauth2.0认证"""
获取前端发送过来的 code 参数:
code = request.GET.get(if not code:
判断 code 参数是否存在
return http.JsonResponse({': 400缺少code参数})
调用我们安装的 QQLoginTool 工具类
创建工具对象
oauth = OAuthQQ(client_id=settings.QQ_REDIRECT_URI)
try:
携带 code 向 QQ服务器 请求 access_token
access_token = oauth.get_access_token(code)
携带 access_token 向 QQ服务器 请求 openid
openid = oauth.get_open_id(access_token)
except Exception as e:
如果上面获取 openid 出错,则验证失败
logger.error(e)
返回结果
oauth2.0认证失败,即获取qq信息失败})
pass
给上面的接口增加子路由:
QQ用户部分接口:
re_path(r^oauth_callback/$openid 是否绑定用户的处理
判断 openid 是否绑定过用户
使用 openid 查询该 QQ 用户是否在美多商城中绑定过用户。
:
oauth_qq = OAuthQQUser.objects.get(openid=openid)
Exception as e:
如果 openid 没绑定美多商城用户
pass
else:
如果 openid 已绑定美多商城用户
pass
openid 已绑定用户的处理
如果 openid 已绑定美多商城用户
直接生成状态保持信息,登录成功,并重定向到首页。
查看是否有 openid 对应的用户
oauth_qq = OAuthQQUser.objects.get(openid=openid)
请查看: openid 未绑定用户的处理
根据 user 外键,获取对应的 QQ 用户(user)
user = oauth_qq.user
实现状态保持
login(request,user)
创建重定向到主页的对象
response = JsonResponse({:0,1)">':ok})
将用户信息写入到 cookie 中,有效期14天
response.set_cookie(username 返回响应
return response
openid 未绑定用户的处理
为了能够在后续的绑定用户操作中前端可以使用 openid,
在这里将 openid 签名后响应给前端。
openid 属于用户的隐私信息,所以需要将 openid 签名处理,避免暴露。
如果 openid 没绑定美多商城用户,进入这里:
调用我们自定义的方法,对 openid 进行加密
把 openid 变为 access_token
access_token = generate_access_token(openid)
把 access_token 返回给前端
注意: 这里一定不能返回 0 的状态码. 否则不能进行绑定页面
':300access_token:access_token})
:
...
补充 itsdangerous 的使用
from itsdangerous TimedJSONWebSignatureSerializer
settings
generate_access_token(openid):
对传入的 openid 进行加密处理,返回 token"""
QQ 登录保存用户数据的 token 有效期
settings.SECRET_KEY: 加密使用的秘钥
过期时间: 600s = 10min
serializer = TimedJSONWebSignatureSerializer(settings.SECRET_KEY,expires_in=600)
data = {: openid}
对 dict 进行加密
token = serializer.dumps(data)
加密完之后,解码返回.
return token.decode()
绑定用户接口实现
Oauth2.0 认证"""
......
post(self,1)">美多商城用户绑定到openid 1.接收参数
dict = json.loads(request.body.decode())
mobile = dict.get(mobile)
password = dict.get(password)
sms_code_client = dict.get(sms_code)
access_token = dict.get( 2.校验参数
判断参数是否齐全
all([mobile,password,sms_code_client]):
':400缺少必传参数 判断手机号是否合法
not re.match(r^1[3-9]\d{9}$请输入正确的手机号码})
判断密码是否合格
^[0-9A-Za-z]{8,20}$请输入8-20位的密码 3.判断短信验证码是否一致
创建 redis 链接对象:
redis_conn = get_redis_connection(verify_code 从 redis 中获取 sms_code 值:
sms_code_server = redis_conn.get(sms_%s' % mobile)
判断获取出来的有没有:
if sms_code_server is None:
如果没有,直接返回:
验证码失效 如果有,则进行判断:
if sms_code_client != sms_code_server.decode():
如果不匹配,则直接返回:
输入的验证码有误})
调用我们自定义的函数,检验传入的 access_token 是否正确:
错误提示放在 sms_code_errmsg 位置
openid = check_access_token(access_token)
openid:
缺少openid 4.保存注册数据
:
user = User.objects.get(mobile=mobile)
用户不存在,新建用户
user = User.objects.create_user(username=mobile,password=password,mobile= 如果用户存在,检查用户密码
user.check_password(password):
输入的密码不正确 5.将用户绑定 openid
:
OAuthQQUser.objects.create(openid=openid,user=user)
往数据库添加数据出错 6.实现状态保持
login(request,user)
7.创建响应对象:
response = JsonResponse({ 8.登录时用户名写入到 cookie,有效期14天
response.set_cookie( 9.响应
return response
BadData
定义函数,检验传入的 access_token 里面是否包含有 openid
check_access_token(access_token):
检验用户传入的 token
:param token: token
:return: openid or None
调用 itsdangerous 中的类,生成对象
serializer =:
尝试使用对象的 loads 函数
对 access_token 进行反序列化( 类似于解密 )
查看是否能够获取到数据:
data = serializer.loads(access_token)
BadData:
如果出错,则说明 access_token 里面不是我们认可的.
返回 None
return None
:
如果能够从中获取 data,则把 data 中的 openid 返回
return data.get(')
原文地址:https://www.cnblogs.com/tracydzf
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。