三方登陆流程:
微博开放平台设置app和key
请求用户授权Token: https://open.weibo.com/wiki/Oauth2/authorize
获取授权过的Access Token, UID: https://open.weibo.com/wiki/Oauth2/access_token
django代码
setting
-
import os
-
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
# Quick-start development settings - unsuitable for production
-
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
-
# SECURITY WARNING: keep the secret key used in production secret!
-
SECRET_KEY = 'fivz67l6ttp5jlg%$jnrinq=j72re)x-54k(q-%y^l5+(7^h6i'
-
# SECURITY WARNING: don't run with debug turned on in production!
-
DEBUG = True
-
ALLOWED_HOSTS = []
-
# Application definition
-
INSTALLED_APPS = [
-
'django.contrib.admin',
-
'django.contrib.auth',
-
'django.contrib.contenttypes',
-
'django.contrib.sessions',
-
'django.contrib.messages',
-
'django.contrib.staticfiles',
-
'appqiniu',
-
'rest_framework',
-
'corsheaders',
-
'rest_framework.authtoken',
-
'users',
-
'weiboapp',
-
"redisapp"
-
]
-
MIDDLEWARE = [
-
'django.middleware.security.SecurityMiddleware',
-
'django.contrib.sessions.middleware.SessionMiddleware',
-
'django.middleware.common.CommonMiddleware',
-
# 'django.middleware.csrf.CsrfViewMiddleware',
-
'django.contrib.auth.middleware.AuthenticationMiddleware',
-
'django.contrib.messages.middleware.MessageMiddleware',
-
'django.middleware.clickjacking.XFrameOptionsMiddleware',
-
'corsheaders.middleware.CorsMiddleware',
-
]
-
ROOT_URLCONF = 'django_online.urls'
-
TEMPLATES = [
-
{
-
'BACKEND': 'django.template.backends.django.DjangoTemplates',
-
'DIRS': [os.path.join(BASE_DIR, 'templates')]
-
,
-
'APP_DIRS': True,
-
'OPTIONS': {
-
'context_processors': [
-
'django.template.context_processors.debug',
-
'django.template.context_processors.request',
-
'django.contrib.auth.context_processors.auth',
-
'django.contrib.messages.context_processors.messages',
-
],
-
},
-
},
-
]
-
WSGI_APPLICATION = 'django_online.wsgi.application'
-
# Database
-
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
-
DATABASES = {
-
'default': {
-
'ENGINE': 'django.db.backends.mysql',
-
'HOST': '127.0.0.1', # 数据库主机
-
'PORT': 3306, # 数据库端口
-
'USER': 'root', # 数据库用户名
-
'PASSWORD': '123456', # 数据库用户密码
-
'NAME': 'drf1908a_ol' # 数据库名字
-
}
-
}
-
# Password validation
-
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
-
AUTH_PASSWORD_VALIDATORS = [
-
{
-
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
-
},
-
{
-
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
-
},
-
{
-
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
-
},
-
{
-
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
-
},
-
]
-
# Internationalization
-
# https://docs.djangoproject.com/en/2.2/topics/i18n/
-
LANGUAGE_CODE = 'en-us'
-
TIME_ZONE = 'UTC'
-
USE_I18N = True
-
USE_L10N = True
-
USE_TZ = True
-
# Static files (CSS, JavaScript, Images)
-
# https://docs.djangoproject.com/en/2.2/howto/static-files/
-
STATIC_URL = '/static/'
-
CORS_ALLOW_CREDENTIALS = True
-
CORS_ORIGIN_ALLOW_ALL = True
-
CORS_ORIGIN_WHITELIST = ()
-
CORS_ALLOW_METHODS = (
-
'DELETE',
-
'GET',
-
'OPTIONS',
-
'PATCH',
-
'POST',
-
'PUT',
-
'VIEW',
-
)
-
CORS_ALLOW_HEADERS = (
-
'XMLHttpRequest',
-
'X_FILENAME',
-
'accept-encoding',
-
'authorization',
-
'content-type',
-
'dnt',
-
'origin',
-
'user-agent',
-
'x-csrftoken',
-
'x-requested-with',
-
'Pragma',
-
)
-
SESSION_ENGINE='django.contrib.sessions.backends.cache'
-
REST_FRAMEWORK = {
-
# 身份认证
-
'DEFAULT_AUTHENTICATION_CLASSES': (
-
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
-
'rest_framework.authentication.SessionAuthentication',
-
'rest_framework.authentication.BasicAuthentication',
-
),
-
#全局配置接口权限
-
# 'DEFAULT_PERMISSION_CLASSES': (
-
# 'rest_framework.permissions.IsAuthenticated',
-
# ),
-
}
-
import datetime
-
JWT_AUTH = {
-
'JWT_AUTH_HEADER_PREFIX': 'JWT',
-
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
-
'JWT_RESPONSE_PAYLOAD_HANDLER':
-
'users.views.jwt_response_payload_handler', # 重新login登录返回函数
-
}
-
AUTH_USER_MODEL='users.User' # 指定使用users APP中的 model的User表作为系统认证时使用表
-
WEIBO_APP_KEY = '505677658'
-
WEIBO_APP_SECRET = '5689ef360f8e25c1df8a54e8e5653cd2'
-
WEIBO_CALL_BACK = 'http://127.0.0.1:8080/#/weibo_callback/' # 回调路由
urls.py
-
from django.urls import path,re_path,include
-
from weiboapp import views
-
from rest_framework_jwt.views import obtain_jwt_token # 验证密码后返回token
-
urlpatterns = [
-
path('weibourl/', views.WBUrl.as_view(), ),
-
path('call_back/', views.WBCallBack.as_view(), ),
-
path('bind_user/', views.BindUser.as_view(), ),
-
]
serializers
-
from rest_framework_jwt.settings import api_settings
-
from rest_framework import serializers
-
from users.models import User
-
class UserSerializer(serializers.Serializer):
-
id =serializers.IntegerField(read_only=True)
-
username = serializers.CharField()
-
password = serializers.CharField()
-
phone = serializers.CharField()
-
token = serializers.CharField(read_only=True)
-
def create(self, data):
-
user = User.objects.create(**data)
-
#数据库里密码的加密(固定的步骤)
-
user.set_password(data.get('password'))
-
user.save()
-
# 补充生成记录登录状态的token 固定的格式,用过来生成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)
-
#把token发放在user里返回
-
user.token = token
-
return user
-
def update(self, instance, validated_data):
-
pass
model
-
from django.db import models
-
from django.contrib.auth.models import AbstractUser
-
# Create your models here.
-
class User(AbstractUser):
-
username = models.CharField(max_length=64, unique=True)
-
password = models.CharField(max_length=255)
-
phone = models.CharField(max_length=64)
-
pic = models.CharField(max_length=512)
-
token = models.CharField(max_length=255)
-
class WbUser(models.Model):
-
user_app=(
-
(1,"微信"),
-
(2,"微博"),
-
(3,"qq"),
-
(4,"支付宝")
-
)
-
uid= models.CharField(max_length=128,unique=True)
-
users = models.ForeignKey(User,on_delete=models.SET_NULL,null=True)
-
name = models.CharField(max_length=32,null=True)
-
user_from = models.IntegerField(choices=user_app)
views
-
from django.shortcuts import render
-
from rest_framework.response import Response
-
from rest_framework.views import APIView
-
from urllib.parse import urlencode
-
from django_online import settings
-
from rest_framework.permissions import IsAuthenticated,AllowAny
-
import requests
-
from .models import WbUser
-
from rest_framework_jwt.settings import api_settings
-
from .serializers import UserSerializer
-
from django.db import transaction
-
# Create your views here.
-
class WBUrl(APIView):
-
permission_classes = [AllowAny]
-
def get(self,request):
-
url="https://api.weibo.com/oauth2/authorize?"
-
data={
-
"client_id":settings.WEIBO_APP_KEY,
-
"response_type":"code",
-
'redirect_uri': settings.WEIBO_CALL_BACK
-
}
-
weibo_url = url+urlencode(data)
-
print(weibo_url)
-
return Response({"weibo_url":weibo_url})
-
class WBCallBack(APIView):
-
def get(self,request):
-
code = request.query_params.get("code")
-
print(code)
-
data = {
-
'client_id': settings.WEIBO_APP_KEY,
-
'client_secret': settings.WEIBO_APP_SECRET,
-
'grant_type': 'authorization_code',
-
'code': code,
-
'redirect_uri': settings.WEIBO_CALL_BACK,
-
}
-
url = 'https://api.weibo.com/oauth2/access_token'
-
response = requests.post(url=url,data=data).json()
-
print(response)
-
uid = response.get('uid')
-
print(uid)
-
if not uid: # 获取不到则为微博code错误
-
return Response({'code': 201, 'error': '三方授权失败'})
-
else:
-
try:
-
user = WbUser.objects.get(uid=uid)
-
except Exception as e:
-
return Response({"code":404,"msg":"first time login","uid":uid})
-
else:
-
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
-
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
-
payload = jwt_payload_handler(user) # user指的是你查询出来的用户
-
token = jwt_encode_handler(payload)
-
data={
-
"code": 200,
-
"token": token,
-
"msg": "login sucess",
-
"username":user.users.username,
-
"user_id":user.users.id
-
}
-
return Response(data,status=200)
-
#检查参数是否齐全
-
def check_params(list,data):
-
for i in list:
-
if i in data:
-
pass
-
else:
-
return i
-
return False
-
class BindUser(APIView):
-
def post(self,request):
-
params = request.data
-
check_result = check_params(["username","password","phone","u_id"],params)
-
if check_result:
-
data={
-
"code":200,
-
"msg": "%s is lost" % check_result
-
}
-
return Response(data,status=200)
-
try:
-
ser = UserSerializer(data=params)
-
# print(ser)
-
if ser.is_valid():
-
#使用事务来处理
-
with transaction.atomic():
-
#创建还原点
-
save_id = transaction.savepoint()
-
try:
-
user = ser.save()
-
wb_res = WbUser.objects.create(uid=params["u_id"],user_from=2,users=user)
-
# transaction.savepoint_commit(save_id)
-
except Exception as e:
-
#返回还原点再次执行
-
transaction.savepoint_rollback(save_id)
-
finally:
-
#执行成功,提交到数据库
-
transaction.savepoint_commit(save_id)
-
res_data = ser.data
-
res_data["code"]=200
-
return Response(res_data, status=200)
-
else:
-
return Response({"code":500,"msg":"failed"},status=200)
-
except Exception as e:
-
# raise e
-
return Response({"code": 5001, "msg": "failed"},status=200)