1.創建apps/oauth模塊進行oauth認證
'''2.1 在apps文件夾下新建應用: oauth'''
cd syl/apps
python ../manage.py startapp oauth # 切換到apps文件夾下執行創建命令
'''2.2 添加子路由: oauth/urls.py'''
from django.urls import path
from . import views
urlpatterns = [
]
'''2.3 在syl/settings.py中添加應用'''
INSTALLED_APPS = [
'oauth.apps.OauthConfig',
]
'''2.4 在syl/urls.py主路由中添加'''
urlpatterns = [
path('oauth/', include('oauth.urls')),
]
2.生成微博授權URL接口
1.1 添加子路由: oauth/urls.py
urlpatterns = [
path('weibo/', views.WeiboUrl.as_view()), # /oauth/weibo/ 返回微博登錄地址
]
1.2 syl/settings.py 中配微博地址
WEIBO_CLIENT_ID = '3516473472'
WEIBO_REDIRECT_URL = 'http://127.0.0.1:8888/oauth/callback/'
1.3 視圖函數: oauth/views.py
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from urllib.parse import urlencode
# 生成前端跳轉到微博掃碼頁面的url
class WeiboUrl(APIView):
'''
生成微博的登陸頁面路由地址
https://api.weibo.com/oauth2/authorize? # 微博oauth認證地址
client_id=4152203033& # 注冊開發者id
response_type=code&
redirect_uri=http://127.0.0.1:8888/oauth/callback/ # 獲取code后將code回
調給后端地址
'''
# 自定義權限類
permission_classes = (AllowAny,)
def post(self, request):
url = 'https://api.weibo.com/oauth2/authorize?' # 微博授權的url地址
data = {
'client_id': '3847987228', #settings.WEIBO_CLIENT_ID
'response_type': 'code',
'redirect_uri': 'http://127.0.0.1:8888/oauth/callback/', # VUE的回調,微博后台授權的回調地址
}
weibo_url = url + urlencode(data)# https://api.weibo.com/oauth2/authorize?
# client_id = 4152203033 & response_type = code & redirect_uri = http: // 127.0.0.1: 8000 / api / weibo_back /
# return Response({'weibo_url': weibo_url})
return Response({'code': '0', 'msg': '成功', 'data': {'url': weibo_url}})
3.測試生成微博售前URL接口
- 測試接口獲取新浪微博地址
http://192.168.56.100:8888/oauth/weibo/
1.在Vue頁面加載時動態發送請求獲取微博授權url
1.1 在 components\common\lab_header.vue 中寫oauth動態獲取微博授權URL
// 獲取微博登錄地址
oauth() {
// 從后端獲取 微博登錄地址
oauth_post().then((resp) => {
console.log(resp)
//{'code': '0', 'msg': '成功', 'data': {'url': url}}
let url = resp.data.url;
this.weibo_url = url;
})
},
1.2 在vue的mounted函數中調用獲取微博授權url函數
mounted() {
this.oauth()
},
1.3 點擊"登錄"彈出的form表單中加入url
<form
action="/login"
method="post"
>
<div class="form-group widget-signin">
<a :href="weibo_url"><i class="fa fa-weibo"></i></a>
</div>
</form>
1.微博回調接口
1.1 oauth/urls.py 中添加路由
urlpatterns = [
path('weibo/callback/', views.OauthWeiboCallback.as_view()), #/oauth/weibo/callback/
]
1.2 oauth/views.py 中添加試圖函數
http://192.168.56.100:8888/oauth/weibo/callback/
from .models import OauthUser
from rest_framework_jwt.serializers import jwt_payload_handler,
jwt_encode_handler
from user.utils import jwt_response_payload_handler
# 通過vue前端傳入的code,微博身份驗證
class OauthWeiboCallback(APIView):
# 自定義權限類
permission_classes = (AllowAny,)
def post(self, request):
# 接收vue端傳過來的code(微博的用戶code)
# 1.使用微博用戶code+微博開發者賬號信息換取微博的認證access_token
code = request.data.get('code')
data = {
'client_id': '3847987228',
'client_secret': '538c1fb220cdad5cd35bafe26e80ec03',
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'http://127.0.0.1:8888/oauth/callback/',
}
url = 'https://api.weibo.com/oauth2/access_token'
data = requests.post(url=url, data=data).json() # 拿取請求的返回結果
# access_token = data.get('uid') # 獲取到的微博token
weibo_uid = data.get('uid') # 獲取到少碼用戶的id
# 2. 根據uid 查詢綁定情況
try:
oauth_user = OauthUser.objects.get(uid=weibo_uid, oauth_type='1')
except Exception as e:
oauth_user = None
# 返回動作, 登錄成功/需要綁定用戶 type 0 登錄成功, 1, 授權成功, 需要綁定
if oauth_user:
# 4. 如果綁定了, 返回token, 登錄成功
user = oauth_user.user
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
# jwt_response_payload_handler為user模塊定義的jwt返回的信息
data = jwt_response_payload_handler(token, user)
#1.3 oauth/models.py 中添加用戶綁定模型
#1.4 遷移數據庫
data['type'] = '0' # 指定為登錄成功
return Response({'code': 0, 'msg': '登錄成功', 'data': data})
else:
# 5. 如果沒綁定, 返回標志, 讓前端跳轉到綁定頁面
return Response({'code': 0, 'msg': '授權成功', 'data': {'type': '1','uid': weibo_uid}})
1.3 oauth/models.py 中添加用戶綁定模型
# 把三方的用戶信息,和本地的用戶信息進行綁定
class OauthUser(models.Model):
OAUTHTYPE = (
('1', 'weibo'),
('2', 'weixin'),
)
uid = models.CharField('三方用戶id', max_length=64)
# 三方用戶id
user = models.ForeignKey('user.User', on_delete=models.CASCADE)
# 本地用戶外鍵,關聯User表
oauth_type = models.CharField('認證類型', max_length=10, choices=OAUTHTYPE)
1.4 遷移數據庫
python manager.py makemigrations
python manager.py migrate
1.vue微博回調空頁面
- 注:微博回調空頁面為: http://127.0.0.1:8888/oauth/callback/
1.1 頁面路徑 components\oauth.vue
<template>
<div>
<p>跳轉中....</p>
</div>
</template>
<script>
import { oauth_callback_post, oauth_binduser_post, user_count } from './axios_api/api'
export default {
data() {
return {
visiable: false, // 綁定用戶窗口
uid: '', // weibo_uid
username: '',
password: '',
username_message: '',
username_error: false
}
},
mounted() {
this.getCode()
},
methods: {
// 2.判斷用戶名是否合法
check_username() {
console.log('判斷用戶名')
console.log(this.username == '')
var reg = new RegExp(/^[a-zA-Z0-9_-]{3,16}$/); //字符串正則表達式 4到14位(字母,數字,下划線,減號)
if (this.username == '') {
this.username_message = '用戶名不能為空'
this.username_error = true
return false
}
if (!reg.test(this.username)) {
this.username_message = '用戶名格式不正確'
this.username_error = true
return false
} else {
// 去后端檢查用戶名使用數量
user_count({ type: 'username', data: this.username }).then((res) => {
console.log(res)
if (res.data.count > 0) {
this.username_message = '用戶名已存在, 請輸入密碼'
this.username_error = false
} else {
this.username_message = '用戶名可用, 將創建新用戶,請輸入密碼'
this.username_error = false
}
})
}
},
// 1.1當頁面被掛載時就自動調用,通過url獲取微博的code,發送code給django端
// 1.2 如果已經綁定,返回 type='0',登錄成功,直接跳轉到首頁
// 1.3 如果未綁定,返回type='1',顯示綁定用戶的頁面
getCode() {
// 獲取url中的code 信息,code信息是微博端返回的
// 當前url 是 http://127.0.0.1:8888/oauth/callback/?code=424db5805abb50ed5e0ba97325f54d0f
let code = this.$route.query.code
console.log(this.$route.query)
// 給后端發送code
let params = { code: code }
oauth_callback_post(params).then((resp) => {
console.log(resp)
// code: 0
// msg: "授權成功"
// data: {type: "1", uid: "7410919278"}
// 如果type=0代表以前已經綁定過,直接登錄成功
if (resp.data.type == '0') {
// code: 0
// msg: "登錄成功"
// data: {
// authenticated: "true"
// email: ""
// id: 1
// name: "admin"
// role: null
// token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoxNTk3OTAwNTcyLCJlbWFpbCI6IiIsIm9yaWdfaWF0IjoxNTk3ODE0MTcyfQ.aQT7GSR_xQBPMlB4_k8-zTHnx0ow3OC2KHa3C8MgilY"
// type: "0"
// username: "admin"}
let res = resp.data
localStorage.setItem('username', res.username)
// localStorage.setItem('img', res.img)
localStorage.setItem('token', res.token)
localStorage.setItem('uid', res.id)
this.login_username = res.username
this.opened = false
// alert(res.message)
this.$router.push('/') // 跳轉到首頁
}
// 如果用戶·沒有綁定過,顯示綁定頁面
if (resp.data.type == '1') {
this.visiable = true
this.uid = resp.data.uid
}
})
},
// 3.綁定微博用戶與實驗樓本地用戶
bindUser() {
if(this.username_error){
return
}
// 發送 用戶名, 密碼, weibo_uid 到后端接口, 進行綁定
let params = { username: this.username, password: this.password, weibo_uid: this.uid }
oauth_binduser_post(params).then((resp) => {
console.log(resp)
let res = resp.data
localStorage.setItem('username', res.username)
// localStorage.setItem('img', res.img)
localStorage.setItem('token', res.token)
localStorage.setItem('uid', res.id)
this.login_username = res.username
this.opened = false
// alert(res.message)
this.$router.push('/')
})
}
}
}
</script>