1 开发模式和设计模式
1.1 开发模式
1.2 设计模式
- 基于开发模式,设计理念(一种境界)
- 工厂模式(一种设计模式)将创建模式更加抽象化,只关心参数,至于怎么变化实现不关心
1.3 静态方法和类方法的不同
- 静态方法不需要实例化对象,直接通过类方法调用
- 类方法需要实例化,再调用
1.4 面向接口开发
2 设计模式实现三方登录
2.1Django端
import urllib
import requests
import hmac
import base64
import time
import json
from hashlib import sha256
from rest_framework.response import Response
from rest_framework.views import APIView
from oathapp.models import OathModel
from oathapp.utils import ChooseMethod, GITEE_CLIENT_SECRET, GITEE_CLIENT_ID, GITEE_REDIRECT_URI, DINGDING_APP_SECRET, DINGDING_APP_ID
from userapp.utils import create_token
class GetUrlView(APIView):
def get(self, request):
t = request.GET.get('type')
url = ChooseMethod.choose(str(t))
return Response({'url': str(url), 'code': 200, 'type':t})
class GiteeRedirectView(APIView):
def post(self, request):
code = request.data.get('code')
data = {
'client_id': GITEE_CLIENT_ID,
'client_secret': GITEE_CLIENT_SECRET,
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': GITEE_REDIRECT_URI,
}
url = 'https://gitee.com/oauth/token'
redirect_data = requests.post(url=url, data=data).json()
token = redirect_data['access_token']
message = requests.get('https://gitee.com/api/v5/user?access_token=' + token).json()
uid = message.get('id')
try:
oath_user = OathModel.objects.get(uid=uid, oath_type="2")
except Exception as e:
oath_user = None
if oath_user:
user = oath_user
username = user.username
token = create_token(user)
return Response({'username': username, 'token':token, 'code':200})
else:
username = message.get('name')
user = OathModel.objects.create(username=username, uid=uid, oath_type="2")
oath_token = create_token(user)
return Response({'username': username, ' oath_token': oath_token, 'code': 200})
class DingDingRedirectView(APIView):
def post(self, request):
code = request.data.get('code')
t = time.time()
timestamp = str((int(round(t * 1000))))
signature = base64.b64encode(hmac.new(DINGDING_APP_SECRET.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
payload = {'tmp_auth_code': code}
headers = {'Content-Type': 'application/json'}
message = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(
signature.decode("utf-8")) + "×tamp=" + timestamp + "&accessKey="+ DINGDING_APP_ID,data=json.dumps(payload), headers=headers)
message_dict = json.loads(message.text)
print(message_dict)
ms = message_dict.get('user_info')['unionid']
try:
oath_user = OathModel.objects.get(uid=ms, oath_type="1")
except Exception as e:
oath_user = None
if oath_user:
nick = message_dict.get('user_info')['nick']
token = create_token(oath_user)
return Response({'username': nick, 'oath_token':token, 'code':200})
else:
username = message_dict.get('user_info')['nick']
user = OathModel.objects.create(username=username, uid=ms, oath_type="1")
oath_token = create_token(user)
return Response({'username': username, ' oath_token': oath_token, 'code': 200})
# -*- coding: utf-8 -*-
# Gitee
GITEE_CLIENT_ID = '3c87c87eada7f893aa6eff464388aed8a8549a261d4289c4b112af935fd12e2e'
GITEE_REDIRECT_URI = 'http://127.0.0.1:8080/index?type=2'
GITEE_CLIENT_SECRET = '5d7e49dfb57aa15015015bef0fcf9e139fa000fe43af1ac18d9776199b15983d'
# DingDing
DINGDING_APP_ID = 'dingoayjscr9lrrmppm9en'
DINGDING_REDIRECT_URI = 'http://127.0.0.1:8080/index?type=aaa'
DINGDING_APP_SECRET = 'oczDpVdg4IGfX_JfQNMJnFA338sHrMOHvH1BrGqyM0vG8vYQGemcaAnutCTSORrT'
class GiteeFirst:
def __repr__(self):
return 'https://gitee.com/oauth/authorize?client_id={}&redirect_uri={}&response_type=code'.format(GITEE_CLIENT_ID, GITEE_REDIRECT_URI)
class DingDingFirst:
def __repr__(self):
return 'https://oapi.dingtalk.com/connect/qrconnect?appid={}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri={}'.format(DINGDING_APP_ID, DINGDING_REDIRECT_URI)
class FaceBookFirst:
def __repr__(self):
return 222
class ChooseMethod:
@staticmethod
def choose(type):
if type == '2':
num = GiteeFirst()
return num
if type == '3':
return FaceBookFirst()
if type == '1':
return DingDingFirst()
2.2 Vue端
<template>
<div style="margin-top:200px">
<center><h1 style="margin-top:50px">登 录</h1></center>
<div style="margin:0 auto;500px;height:200px">
用户名:
<a-input placeholder="input your username" style="300px" v-model="username"/>
<br>
<br>
密  码:
<a-input-password placeholder="input your password" style="300px" v-model="password"/>
<br>
<br>
<p>
<a-input type="text" v-model="message_code" style="200px"/> <a-button type="primary" @click="getMessageCode">钉钉获取验证码</a-button>
</p>
<a-button type="primary" @click="login">登录</a-button>
</div>
<a-button @click="giteeGo">Gitee</a-button>  <a-button @click="DingDingGo">DingDing</a-button>  <a-button>Facebook</a-button>
</div>
</template>
<script>
import { get_message_code, user_login, get_oath_url } from '@/http/apis'
export default {
data() {
return {
username:'',
password:'',
message_code:'',
}
},
methods: {
// 获取验证码
getMessageCode(){
get_message_code().then(res=>{
console.log(res)
res.code == 200?alert('获取验证码成功')&sessionStorage.setItem('session_key', res.session_key):alert('失败失败')
// res.code == 200?alert('获取验证码成功'):alert('失败失败')
})
},
// 登录
login(){
let user_info = {
'username':this.username,
'password':this.password,
'num':this.message_code,
'session_key': sessionStorage.getItem('session_key')
}
user_login(user_info).then(
res=>{
console.log(res)
res.code == 200?alert('登录成功'):alert('登录失败')
}
)
},
// gitee获取三方地址
giteeGo(){
get_oath_url({'type': '2'}).then(res=>{
console.log(res)
window.location.href = res.url
})
// window.location.href='http://127.0.0.1:8080/index'
},
// dingding获取三方地址
DingDingGo(){
get_oath_url({'type':'1'}).then(res=>{
console.log(res.url)
window.location.href=res.url
})
}
},
created() {
}
}
</script>
<style scoped>
</style>
<template>
<div>
<h3>欢迎您访问,亲爱的{{username}}</h3>
</div>
</template>
<script>
// import { get_gitee_redirect_url, get_dingding_redirect_url } from '@/http/apis'
export default {
data() {
return {
// 后端自动跳转,所以不用这种方法啦
username:'',
token:this.$route.query.code,
type:this.$route.query.type,
}
},
methods: {
getGiteeRedirectUrl(){
get_gitee_redirect_url({'code': this.code}).then(res=>{
console.log(res)
this.username = res.username
sessionStorage.setItem('oath_token', res.oath_token)
})
},
getDingDingRedirectUrl(){
get_dingding_redirect_url({'code': this.code}).then(res=>{
console.log(res)
this.username = res.username
sessionStorage.setItem('oath_token', res.oath_token)
})
},
},
created() {
if(this.type==2){
this.getGiteeRedirectUrl()
}else if(this.type==null){
this.getDingDingRedirectUrl()
}else{
console.log(2222222222222)
}
sessionStorage.setItem('oath_token', this.oath_token)
}
}
</script>
<style scoped>
</style>
3 设计模式实现三方登录(改进版)
- 回调地址写第二个视图函数地址,第一次拼接地址直接跳转第二个方法,第二次视图函数返回值是一个拼接好的路由,直接跳转前端页面,这种改良少了一个接口!!!
3.1 Django端
import urllib
import requests
import hmac
import base64
import time
import json
from hashlib import sha256
from django.shortcuts import redirect
from rest_framework.response import Response
from rest_framework.views import APIView
from oathapp.models import OathModel
from oathapp.utils import ChooseMethod, GITEE_CLIENT_SECRET, GITEE_CLIENT_ID, GITEE_REDIRECT_URI, DINGDING_APP_SECRET, DINGDING_APP_ID
from userapp.utils import create_token
class GetUrlView(APIView):
def get(self, request):
t = request.GET.get('type')
url = ChooseMethod.choose(str(t))
return Response({'url': str(url), 'code': 200, 'type':t})
class GiteeRedirectView(APIView):
def get(self, request):
code = request.GET.get('code')
data = {
'client_id': GITEE_CLIENT_ID,
'client_secret': GITEE_CLIENT_SECRET,
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': GITEE_REDIRECT_URI,
}
url = 'https://gitee.com/oauth/token'
redirect_data = requests.post(url=url, data=data).json()
token = redirect_data['access_token']
message = requests.get('https://gitee.com/api/v5/user?access_token=' + token).json()
uid = message.get('id')
try:
oath_user = OathModel.objects.get(uid=uid, oath_type="2")
except Exception as e:
oath_user = None
if oath_user:
user = oath_user
username = user.username
oath_token = create_token(user)
return redirect('http://127.0.0.1:8080/index/?token=' + oath_token + "&username=" + username)
else:
username = message.get('name')
user = OathModel.objects.create(username=username, uid=uid, oath_type="2")
oath_token = create_token(user)
return redirect('http://127.0.0.1:8080/index/?token=' + oath_token + "&username=" + username)
class DingDingRedirectView(APIView):
def get(self, request):
code = request.GET.get('code')
t = time.time()
timestamp = str((int(round(t * 1000))))
signature = base64.b64encode(hmac.new(DINGDING_APP_SECRET.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
payload = {'tmp_auth_code': code}
headers = {'Content-Type': 'application/json'}
message = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(
signature.decode("utf-8")) + "×tamp=" + timestamp + "&accessKey="+ DINGDING_APP_ID,data=json.dumps(payload), headers=headers)
message_dict = json.loads(message.text)
print(message_dict)
ms = message_dict.get('user_info')['unionid']
try:
oath_user = OathModel.objects.get(uid=ms, oath_type="1")
except Exception as e:
oath_user = None
if oath_user:
nick = message_dict.get('user_info')['nick']
oath_token = create_token(oath_user)
return redirect('http://127.0.0.1:8080/index/?token=' + str(oath_token) + "&username=" + nick)
else:
nick = message_dict.get('user_info')['nick']
user = OathModel.objects.create(username=nick, uid=ms, oath_type="1")
oath_token = create_token(user)
return redirect('http://127.0.0.1:8080/index/?token=' + str(oath_token) + "&username=" + nick)
# -*- coding: utf-8 -*-
# Gitee
GITEE_CLIENT_ID = '3c87c87eada7f893aa6eff464388aed8a8549a261d4289c4b112af935fd12e2e'
GITEE_REDIRECT_URI = 'http://192.168.56.100:4184/oath/redirect_gitee_url/'
GITEE_CLIENT_SECRET = '5d7e49dfb57aa15015015bef0fcf9e139fa000fe43af1ac18d9776199b15983d'
# DingDing
DINGDING_APP_ID = 'dingoayjscr9lrrmppm9en'
DINGDING_REDIRECT_URI = 'http://192.168.56.100:4184/oath/redirect_dingding_url/'
DINGDING_APP_SECRET = 'oczDpVdg4IGfX_JfQNMJnFA338sHrMOHvH1BrGqyM0vG8vYQGemcaAnutCTSORrT'
class GiteeFirst:
def __repr__(self):
return 'https://gitee.com/oauth/authorize?client_id={}&redirect_uri={}&response_type=code'.format(GITEE_CLIENT_ID, GITEE_REDIRECT_URI)
class DingDingFirst:
def __repr__(self):
return 'https://oapi.dingtalk.com/connect/qrconnect?appid={}&response_type=code&scope=snsapi_login&state=STATE&redirect_uri={}'.format(DINGDING_APP_ID, DINGDING_REDIRECT_URI)
class FaceBookFirst:
def __repr__(self):
return 222
class ChooseMethod:
@staticmethod
def choose(type):
if type == '2':
num = GiteeFirst()
return num
if type == '3':
return FaceBookFirst()
if type == '1':
return DingDingFirst()
3.2 Vue端
<template>
<div style="margin-top:200px">
<center><h1 style="margin-top:50px">登 录</h1></center>
<div style="margin:0 auto;500px;height:200px">
用户名:
<a-input placeholder="input your username" style="300px" v-model="username"/>
<br>
<br>
密  码:
<a-input-password placeholder="input your password" style="300px" v-model="password"/>
<br>
<br>
<p>
<a-input type="text" v-model="message_code" style="200px"/> <a-button type="primary" @click="getMessageCode">钉钉获取验证码</a-button>
</p>
<a-button type="primary" @click="login">登录</a-button>
</div>
<a-button @click="giteeGo">Gitee</a-button>  <a-button @click="DingDingGo">DingDing</a-button>  <a-button>Facebook</a-button>
</div>
</template>
<script>
import { get_message_code, user_login, get_oath_url } from '@/http/apis'
export default {
data() {
return {
username:'',
password:'',
message_code:'',
}
},
methods: {
// 获取验证码
getMessageCode(){
get_message_code().then(res=>{
console.log(res)
res.code == 200?alert('获取验证码成功')&sessionStorage.setItem('session_key', res.session_key):alert('失败失败')
// res.code == 200?alert('获取验证码成功'):alert('失败失败')
})
},
// 登录
login(){
let user_info = {
'username':this.username,
'password':this.password,
'num':this.message_code,
'session_key': sessionStorage.getItem('session_key')
}
user_login(user_info).then(
res=>{
console.log(res)
res.code == 200?alert('登录成功'):alert('登录失败')
}
)
},
// gitee获取三方地址
giteeGo(){
get_oath_url({'type': '2'}).then(res=>{
console.log(res)
window.location.href = res.url
})
},
// dingding获取三方地址
DingDingGo(){
get_oath_url({'type':'1'}).then(res=>{
console.log(res.url)
window.location.href=res.url
})
}
},
created() {
}
}
</script>
<style scoped>
</style>
<template>
<div>
<h3>欢迎您访问,亲爱的{{username}}</h3>
</div>
</template>
<script>
export default {
data() {
return {
username:this.$route.query.username,
oath_token:this.$route.query.oath_token
}
},
methods: {
},
created() {
sessionStorage.setItem('oath_token', this.oath_token)
}
}
</script>
<style scoped>
</style>
4 跨域问题
4.1 解决方案
改为
CORS_ORIGIN_WHITELIST = (
'http://127.0.0.1:8080',
'http://localhost:8080',
)
CORS_ALLOW_CREDENTIALS = True
不能写
CORS_ORIGIN_ALLOW_ALL = True
4.2 用终端运行
^C(syl) root@dev:gogogo# python manage.py runserver 192.168.56.100:4184