之前用小程序做项目,因为后台使用的java开发,一切顺利,但切换成django做RESTful API接口时,在登陆注册时一直出现问题,网上搜索,借助一个网友的回答,找到了一种可行的解决方案,现记录如下。
具体流程
- 用户点击小程序页面上的登录授权认证
- 通过微信自带的认证获取code
- 调取登录接口,将code传入后台
- 后台拿到code调用微信接口获取openid等用户信息
- 后台将openid作为用户名,若存在则去校验用户信息,否则以此用户名创建新用户,密码随机生成
- 将校验结果或者创建信息返回给微信小程序端
- 根据返回的信息完成用户登录校验
django的用户权限认证
django有一套自己的完善用户模型,由于Django Auth自带的User模型字段有限,我们需要对其进行拓展(直接使用也可以)
1
2
3
4
5
6
7
8
|
nickname = models.CharField(verbose_name = u '昵称' ,max_length = 50 , blank = True )
user_avatar = models.ImageField(verbose_name = u '用户头像' , upload_to = 'image/%Y/%m/%d' , default = u 'image/default.png' , max_length = 500 )
user_email = models.EmailField(verbose_name = u '用户邮箱' ,max_length = 254 )
user_phone = models.BigIntegerField(verbose_name = u '手机号' , null = True ,blank = True )
user_birthday = models.DateField(verbose_name = u '出生日期' , default = timezone.now)
user_sex = models.CharField(verbose_name = u '性别' ,max_length = 6 ,choices = (( 'male' , '男' ),( 'female' , '女' )),default = 'male' )
user_address = models.CharField(verbose_name = u '地址' ,max_length = 550 , blank = True ,null = True )
signature = models.CharField(verbose_name = u '个性签名' ,max_length = 550 , blank = True ,null = True )
|
用户接口序列化
1
2
3
4
5
6
|
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
|
登陆接口设计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
class UserLogin(APIView):
def post( self ,request):
params = request.data
userName = get_openid(params.get( 'code' ))
userInfo = params.get( 'userinfo' )
try :
user = User.objects.get(username = userName)
except Exception as e:
user = None
if user:
# 更新用户信息
user = User.objects.get(username = userName)
else :
#注册新用户
user = User.objects.create_user(username = userName,password = random_str( 10 ))
#手动生成JWT
# 手动生成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)
ret = { 'code' : '00000' , 'msg' : None , 'data' :{}}
ret[ 'msg' ] = '授权成功'
ret[ 'data' ] = {
'token' : token,
'user_id' : user. id ,
'nickname' : user.nickname
}
return JsonResponse(ret)
|
解析code获取openid
1
2
3
4
5
6
7
8
9
10
11
12
|
class OpenidUtils( object ):
def __init__( self , jscode):
self .url = "https://api.weixin.qq.com/sns/jscode2session"
self .appid = APPID
self .secret = SECRET
self .jscode = jscode # 前端传回的动态jscode
def get_openid( self ):
url = self .url + "?appid=" + self .appid + "&secret=" + self .secret + "&js_code=" + self .jscode + "&grant_type=authorization_code"
r = requests.get(url)
openid = r.json()[ 'openid' ]
return openid
|
小程序的登陆验证
具体登录流程可以查阅官方文档。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
function getWXUserInfo() {
const login = promisify(wx.login);
const getUserInfo = promisify(wx.getUserInfo);
return new Promise( function (resolve, reject) {
_wxLogin();
function _wxLogin() {
login().then( function (res) {
getUserInfo().then( function (r) {
let userInfo = r;
userInfo.code = res.code;
try {
wx.setStorageSync( 'userInfo' , userInfo);
} catch (e) {
console.log(e)
}
if (userInfo && userInfo.code && userInfo.iv) {
resolve(userInfo);
}
else {
reject( 'wx login fail' );
}
}). catch ( function (error) {
reject(error);
});
}). catch ( function (error) {
reject(error);
});
}
});
}
//登录接口验证
getWXUserInfo().then( function (data) {
var result = {
code: 0,
data: {}
};
var params = {
'code' :data.code,
'userinfo' :data.userInfo
}
wx.request({
url: '/api/login' ,
data: params,
dataType: 'json' ,
method: 'POST' ,
success: function (response) {
// 返回成功
if (response.data && response.data.code == '00000' ) {
try {
var resData = {
custNo: data.user_id,
nickname: data.nickname
};
result.code = 0;
result.data = resData;
resolve(result);
}
catch (e) {
console.warn(result)
// 登录失败
result.code = 2;
resolve(result);
}
}
else {
// 获取 customNum 失败
console.warn(result)
result.code = 1;
result.data = 'get customNum fail' ;
resolve(result);
}
}
})
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://juejin.im/post/5c6b64bde51d457fa31e6a30