三方登陆流程:
微博开放平台设置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)