openid绑定用户实现
类似于用户注册的业务逻辑
- 当用户输入的手机号对应的用户已存在
- 直接将该已存在用户跟
openid绑定- 当用户输入的手机号对应的用户不存在
- 新建一个用户,并跟
openid绑定
from apps.oauth.models import OAuthQQUser
from django.contrib.auth import login
import json
import re
from apps.users.models import User
from django.db import DatabaseError
from django_redis import get_redis_connection
from .utils import check_access_token
class QQUserView(View):
"""用户扫码登录的回调处理"""
def get(self, request):
"""Oauth2.0认证"""
pass
def post(self, request):
"""美多商城用户绑定到openid"""
# 1.接收参数
data_dict = json.loads(request.body.decode())
mobile = data_dict.get('mobile')
password = data_dict.get('password')
sms_code_client = data_dict.get('sms_code')
access_token = data_dict.get('access_token')
# 2.校验参数
# 判断参数是否齐全
if not all([mobile, password, sms_code_client]):
return http.JsonResponse({'code': 400,
'errmsg': '缺少必传参数'})
# 判断手机号是否合法
if not re.match(r'^1[3-9]\d{9}$', mobile):
return http.JsonResponse({'code': 400,
'errmsg': '请输入正确的手机号码'})
# 判断密码是否合格
if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
return http.JsonResponse({'code': 400,
'errmsg': '请输入8-20位的密码'})
# 3.判断短信验证码是否一致
# 创建 redis 链接对象:
redis_conn = get_redis_connection('code')
# 从 redis 中获取 sms_code 值:
sms_code_server = redis_conn.get('sms_%s' % mobile)
# 判断获取出来的有没有:
if sms_code_server is None:
# 如果没有, 直接返回:
return http.JsonResponse({'code': 400,
'errmsg': '验证码失效'})
# 如果有, 则进行判断:
if sms_code_client != sms_code_server.decode():
# 如果不匹配, 则直接返回:
return http.JsonResponse({'code': 400,
'errmsg': '输入的验证码有误'})
# 调用我们自定义的函数, 检验传入的 access_token 是否正确:
# 错误提示放在 sms_code_errmsg 位置
openid = check_access_token(access_token)
if not openid:
return http.JsonResponse({'code': 400,
'errmsg': '缺少openid'})
# 4.保存注册数据
try:
user = User.objects.get(mobile=mobile)
except User.DoesNotExist:
# 用户不存在,新建用户
user = User.objects.create_user(username=mobile,
password=password,
mobile=mobile)
else:
# 如果用户存在,检查用户密码
if not user.check_password(password):
return http.JsonResponse({'code': 400,
'errmsg': '输入的密码不正确'})
# 5.将用户绑定 openid
try:
OAuthQQUser.objects.create(openid=openid,
user=user)
except DatabaseError:
return http.JsonResponse({'code': 400,
'errmsg': '往数据库添加数据出错'})
# 6.实现状态保持
login(request, user)
# 7.创建响应对象:
response = http.JsonResponse({'code': 0,
'errmsg': 'ok'})
# 8.登录时用户名写入到 cookie,有效期14天
response.set_cookie('username',
user.username,
max_age=3600 * 24 * 14)
# 9.响应
return response
补充:openid签名处理
oauth.utils.py
from itsdangerous import BadData
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from django.conf import settings
from apps.oauth import constants
def generate_access_token(openid):
"""
签名openid
:param openid: 用户的openid
:return: access_token
"""
serializer = Serializer(settings.SECRET_KEY, expires_in=constants.ACCESS_TOKEN_EXPIRES)
data = {'openid': openid}
token = serializer.dumps(data)
return token.decode()
def check_access_token(access_token):
"""
提取openid
:param access_token: 签名后的openid
:return: openid or None
"""
serializer = Serializer(settings.SECRET_KEY, expires_in=constants.ACCESS_TOKEN_EXPIRES)
try:
data = serializer.loads(access_token)
except BadData:
return None
else:
return data.get('openid')