zoukankan      html  css  js  c++  java
  • 设计模式实现三方登录

    1 开发模式和设计模式

    1.1 开发模式

    • mvc mtv,能够帮我们解耦

    1.2 设计模式

    • 基于开发模式,设计理念(一种境界)
    • 工厂模式(一种设计模式)将创建模式更加抽象化,只关心参数,至于怎么变化实现不关心

    1.3 静态方法和类方法的不同

    • 静态方法不需要实例化对象,直接通过类方法调用
    • 类方法需要实例化,再调用

    1.4 面向接口开发

    • 逻辑类似,但是本质又不一样的适合工厂模式

    2 设计模式实现三方登录

    • 钉钉三方登录
    • gitee三方登录

    2.1Django端

    • views.py
    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")) + "&timestamp=" + 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})
    
    • utils.py
    # -*- 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端

    • Login.vue
    <template>
        <div style="margin-top:200px">
            <center><h1 style="margin-top:50px">登&emsp;录</h1></center>
            <div style="margin:0 auto;500px;height:200px">
                用户名:
                    <a-input placeholder="input your username" style="300px" v-model="username"/>
                <br>
                <br>
                密&ensp;&ensp;码:
                    <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"/>&emsp;<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>&emsp;&emsp;<a-button @click="DingDingGo">DingDing</a-button>&emsp;&emsp;<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>
    
    • Index.vue
    <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端

    • views.py
    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")) + "&timestamp=" + 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)
    
    • utils.py
    # -*- 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端

    • Login.vue
    <template>
        <div style="margin-top:200px">
            <center><h1 style="margin-top:50px">登&emsp;录</h1></center>
            <div style="margin:0 auto;500px;height:200px">
                用户名:
                    <a-input placeholder="input your username" style="300px" v-model="username"/>
                <br>
                <br>
                密&ensp;&ensp;码:
                    <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"/>&emsp;<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>&emsp;&emsp;<a-button @click="DingDingGo">DingDing</a-button>&emsp;&emsp;<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>
    
    • Index.vue
    <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 跨域问题

    image-20201217092343364

    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
    
  • 相关阅读:
    (三)java程序的编译和执行
    (二)java环境搭建
    (一)java概述
    (一)mvc与mvvm设计模式
    小程序 开发之向左滑动实现删除功能
    小程序开发之三级联动
    (效果五)js获取客户端ip地址及浏览器信息
    (六)js常见四大排序
    小程序开发之组件的使用
    Nodejs实现爬虫抓取数据
  • 原文地址:https://www.cnblogs.com/mapel1594184/p/14169401.html
Copyright © 2011-2022 走看看