Django实战-服务端登录验证-code换取openid
Django网络应用开发的5项基础核心技术包括模型(Model)的设计,URL 的设计与配置,View(视图)的编写,Template(模板)的设计和Form(表单)的使用。
在前一小节中,将小程序端登录授权后的code,通过 wx.request 的 POST 方法传给Django服务端。在服务端返回参数给小程序端时,需要再次封装请求状态。
一、封装请求状态
① 状态码
class ReturnCode:
SUCCESS = 0
FAILED = -100
UNAUTHORIZED = -500
BROKEN_AUTHORIZED_DATA = -501
WRONG_PARMAS = -101
RESOURCES_NOT_EXISTS = -102
SESSION_EXPIRED = -502
@classmethod
def message(cls, code):
if code == cls.SUCCESS:
return "success"
elif code == cls.FAILED:
return 'failed'
elif code == cls.UNAUTHORIZED:
return 'unauthorized'
elif code == cls.WRONG_PARMAS:
return 'wrong params'
elif code == cls.RESOURCES_NOT_EXISTS:
return 'this file not exists'
elif code == cls.BROKEN_AUTHORIZED_DATA:
return 'broken authorized data'
elif code == cls.SESSION_EXPIRED:
return 'session expired'
② 返回序列化数据
code 为小程序端授权登录的 js_code,对数据进行序列化。这是服务端通用的序列化数据处理器,将状态码、返回值、提示信息都保存在一个字典中,最后通过 JsonResponse 序列化。
from django.http import JsonResponse
def wrap_json_response(data=None, code=None, message=None):
response = {}
if not code:
code = ReturnCode.SUCCESS
if not message:
message = ReturnCode.message(code)
if data:
response['data'] = data
response['result_code'] = code
response["message"] = message
return response
二、处理服务端授权登录返回
服务端登录验证-code换取openid
使用 wx.login 的临时 code 到微信提供的 code2session 接口授权
1.如果没有 openid,将返回授权登录失败
response = wrap_json_response(code=ReturnCode.FAILED, message="auth failed")
2.如果在 User 模型中没有查询到 用户 openid,将会创建一个新用户。
if not User.objects.filter(open_id=openid):
# 新建用户
new_user = User(open_id=openid, nickname=nickname)
print("new user: open_id: %s, nickname: %s" % (openid, nickname))
new_user.save()
3.使用 session 标记
# 使用 session 标记
request.session["open_id"] = openid
# 是否认证
request.session["is_authorized"] = True
request.body.decode("utf-8") 接收小程序端 wx.login 授权登录后,通过 wx.request 的 POST 方法传递过来的data。
def __authorize_by_code(request):
post_data = request.body.decode("utf-8")
post_data = json.loads(post_data)
# strip() 去空格
code = post_data.get("code").strip()
app_id = post_data.get("appId").strip()
nickname = post_data.get("nickname").strip()
print(code, app_id, nickname)
response = {}
if not code or not app_id:
response["message"] = "authorized failed, need entire authorization data."
response["code"] = ReturnCode.BROKEN_AUTHORIZED_DATA
return JsonResponse(data=response, safe=False)
data = code2session(app_id, code)
openid = data.get("openid")
print("get openid: ", openid)
if not openid:
response = wrap_json_response(code=ReturnCode.FAILED, message="auth failed")
return JsonResponse(data=response, safe=False)
# 使用 session 标记
request.session["open_id"] = openid
# 是否认证
request.session["is_authorized"] = True
if not User.objects.filter(open_id=openid):
# 新建用户
new_user = User(open_id=openid, nickname=nickname)
print("new user: open_id: %s, nickname: %s" % (openid, nickname))
new_user.save()
response = wrap_json_response(code=ReturnCode.SUCCESS, message="auth success.")
return JsonResponse(data=response, safe=False)
三、路由
def authorize(request):
return __authorize_by_code(request)
from django.urls import path
from . import views
urlpatterns = [
path("authorize", views.authorize, name="authorize"),
]