绑定用户身份接口
如果用户是首次使用QQ登录,则需要绑定用户,页面如下:
业务逻辑:
- 用户需要填写手机号、密码、图片验证码、短信验证码
- 如果用户未在美多商城注册过,则会将手机号作为用户名为用户创建一个美多账户,并绑定用户
- 如果用户已在美多商城注册过,则检验密码后直接绑定用户
绑定QQ身份的处理流程
后端接口设计
请求方式: POST /oauth/qq/user/
请求参数: JSON 或 表单
参数 | 类型 | 是否必须 | 说明 |
---|---|---|---|
mobile | str | 是 | 手机号 |
password | str | 是 | 密码 |
sms_code | str | 是 | 短信验证码 |
access_token | str | 是 | 凭据 (包含openid) |
返回数据: JSON
返回值 | 类型 | 是否必须 | 说明 |
---|---|---|---|
token | str | 是 | JWT token |
user_id | int | 是 | 用户id |
username | str | 是 | 用户名 |
在OAuthQQ辅助类中增加
@staticmethod
def check_save_user_token(token):
"""
检验保存用户数据的token
:param token: token
:return: openid or None
"""
serializer = Serializer(settings.SECRET_KEY, expires_in=constants.SAVE_QQ_USER_TOKEN_EXPIRES)
try:
data = serializer.loads(token)
except BadData:
return None
else:
return data.get('openid')
新建oauth/serializers.py文件,
class OAuthQQUserSerializer(serializers.Serializer):
"""
QQ登录创建用户序列化器
"""
access_token = serializers.CharField(label='操作凭证')
mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
password = serializers.CharField(label='密码', max_length=20, min_length=8)
sms_code = serializers.CharField(label='短信验证码')
def validate(self, data):
# 检验access_token
access_token = data['access_token']
openid = OAuthQQ.check_save_user_token(access_token)
if not openid:
raise serializers.ValidationError('无效的access_token')
data['openid'] = openid
# 检验短信验证码
mobile = data['mobile']
sms_code = data['sms_code']
redis_conn = get_redis_connection('verify_codes')
real_sms_code = redis_conn.get('sms_%s' % mobile)
if real_sms_code.decode() != sms_code:
raise serializers.ValidationError('短信验证码错误')
# 如果用户存在,检查用户密码
try:
user = User.objects.get(mobile=mobile)
except User.DoesNotExist:
pass
else:
password = data['password']
if not user.check_password(password):
raise serializers.ValidationError('密码错误')
data['user'] = user
return data
def create(self, validated_data):
user = validated_data.get('user')
if not user:
# 用户不存在
user = User.objects.create_user(
username=validated_data['mobile'],
password=validated_data['password'],
mobile=validated_data['mobile'],
)
OAuthQQUser.objects.create(
openid=validated_data['openid'],
user=user
)
return user
在oauth/views.py修改QQAuthUserView 视图,增加post方法
class QQAuthUserView(GenericAPIView):
"""
QQ登录的用户
"""
serializer_class = OAuthQQUserSerializer
def post(self, request):
"""
保存QQ登录用户数据
"""
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.save()
# 生成已登录的token
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
response = Response({
'token': token,
'user_id': user.id,
'username': user.username
})
return response
前端
在oauth_back.js中实现
// 保存
on_submit: function(){
this.check_pwd();
this.check_phone();
this.check_sms_code();
if(this.error_password == false && this.error_phone == false && this.error_sms_code == false) {
axios.post(this.host + '/oauth/qq/user/', {
password: this.password,
mobile: this.mobile,
sms_code: this.sms_code,
access_token: this.access_token
}, {
responseType: 'json',
})
.then(response => {
// 记录用户登录状态
sessionStorage.clear();
localStorage.clear();
localStorage.token = response.data.token;
localStorage.user_id = response.data.user_id;
localStorage.username = response.data.username;
location.href = this.get_query_string('state');
})
.catch(error=> {
if (error.response.status == 400) {
this.error_sms_code_message = error.response.data.message;
this.error_sms_code = true;
} else {
console.log(error.response.data);
}
})
}
}