vue&django微博第三方登录

首先进去新浪微博开放平台注册应用
vue&django微博第三方登录_第1张图片
点击其他进入
vue&django微博第三方登录_第2张图片
点击创建
vue&django微博第三方登录_第3张图片
微博会给你 App Key和App Secret,这两个要保存下来
vue&django微博第三方登录_第4张图片
点击左侧高级信息,然后进去点击编辑
vue&django微博第三方登录_第5张图片
这时会让你自己设置回调路由和取消授权的路由,回调路由是当你用第三方登录时,微博会给你返回 一个code,这个code会返回到这个路由上,这个路由是vue路由,也就是一个vue前端页面
将回调路由保存下来(这里只用到了回调路由)
好啦,现在准备工作已经做好了,开始做咯
先给大家看一幅流程图vue&django微博第三方登录_第6张图片
流程大概是这样

  1. 客户端访问微博登录页面,微博认证成功会将 code 返回给回调页面
  2. 回调页面拿着 code 访问后台
  3. 后台将 App Key,App Secret,回调路由,code封装好,发起获取uid的post请求时一起将这些参数带去
  4. 微博会将 uid和access_token返回给后台,后台用uid去三方社交表查询是否有这个uid,有就代表以前登录过,直接创建token,username,user_id返回给回调页,如果表里没有uid,说明第一次登录就先将uid和access_token返回给回调页
  5. 回调页以200状态判定返回的是token等参数,将token等数据保存,跳首页面,登录成功。
  6. 回调页判定返回的是uid,access_token,这时其实用户是被第三方认证过的,我们需要在自己本地数据库保存用户基本信息,所以讲uid等参数保存浏览器跳到用户绑定页面。
  7. 用户绑定页面携带uid,access_token再次访问后台,后台带着这些参数访问微博获取用户基本信息
  8. 得到相应,后台将用户基本信息入库用户表,用户社交表,然后生成token,username,user_id返回绑定页面,绑定页面将token等数据保存到浏览器跳首页,登录成功

token,username,user_id保存的位置
vue&django微博第三方登录_第7张图片
下面该实现代码了
用户表就不说啦,上面说到设计到三方登录,需要一个第三方社交表关联用户表

# 第三方社交表
class SocialUser(models.Model):
	# 这个字段是关联用户表的外键
    user = models.ForeignKey(Users,on_delete=models.CASCADE,verbose_name='用户',related_name='user_info')
    # 这个不是个字段,属于二元组,1就代表的PC,真正入库的是 int
    platfrom_type_choices = (
        (1,'PC'),
        (2,'Androia'),
        (3,'IOS'),
    )
    platfrom_id = models.IntegerField(max_length=1,choices=platfrom_type_choices,verbose_name='平台类型')

    platfrom_choices = (
        (1,'QQ'),
        (2,'微博'),
        (3,'微信'),
    )
    platfrom_type = models.IntegerField(max_length=1,choices=platfrom_choices,verbose_name='社交平台')
    uid = models.CharField(max_length=100,verbose_name='用户社交id')

    class Meta:
        db_table = 'socialuser'
        verbose_name_plural = '用户社交表'

数据库迁移:

python manage.py makemigrations
python manage.py migrate

把微博返回的几个参数配置到settings里

# 配置微博返回的参数
WEIBO_APP_KEY = '3312233733'
WEIBO_APP_SECRET = 'c88e0c5e4abe66e89f48897ddef4be3a'
WEIBO_CALL_BACK = 'http://127.0.0.1:8080/#/come_back'   # 回调路由

vue微博登录链接是向后台获取的
在这里插入图片描述
url先给个默认值为空
vue&django微博第三方登录_第8张图片
利用钩子函数向后台获取微博登录页链接

// 获取第三方登录链接
    mounted() {
        this.axios({
        method: "get", // 以post方式访问接口
        url: "http://127.0.0.1:8000/api/get_weibo_login/",
       
      }).then(res=>{
      		// 给微博链接赋值
            this.weibo_login_url = res.data.weibo_url

      }).catch(error=>{
        console.log(error)
      })
        
    },

后台拼接微博登录链接

# 拼接微博登录页面链接返回前端
class Get_weibo_login(APIView):

    '''  
        微博的登陆页面地址:https://api.weibo.com/oauth2/authorize?
        链接需要携带三个参数,是我们注册应用时微博给的参数还有一回调地址
        我们在settings配置好,哪里用哪里取

        client_id = 4152203033
        reponse_type=code
        redirect_uri=http://127.0.0.1:8000/api/weibo_back/  
    '''
    
    def get(self,request):
        url = 'https://api.weibo.com/oauth2/authorize?'
        data = {'client_id':WEIBO_APP_KEY,'reponse_type':'code','redirect_uri':WEIBO_CALL_BACK}
        weibo_url = url + urlencode(data)   # urlencode 能将dict 解析成路由拼接

        return Response({'weibo_url':weibo_url})

用户点击微博登录,微博将 code 返回到回调路由上,创建vue回调页面
vue&django微博第三方登录_第9张图片
页面将携带 code 访问后台获取响应



后台代码

创建token
from rest_framework_jwt.settings import api_settings

# 创建payload的函数   载荷
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
# 创建 token 函数
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
# 获取vue 传来的code 向微博获取 uid,access_token
class Get_weibo_uid(APIView):
    '''
        这次访问微博是获取 uid,access_token
        url = https://api.weibo.com/oauth2/access_token?
        连接需要拼接一些必要的参数方便微博认证
       
    '''
    
    def get(self,request):
        code = request.query_params.get('code')
        url = 'https://api.weibo.com/oauth2/access_token?'
        data = {
            'client_id':WEIBO_APP_KEY,
            'client_secret':WEIBO_APP_SECRET,
            'grant_type': 'authorization_code',
            'code':code,
            'redirect_uri':WEIBO_CALL_BACK
        }
        # 这次是发起的 post 请求 返回的响应是json字符串,需要解析取值
        response = json.loads(requests.post(url,data).text)
        
        '''
            这是返回的 response 数据
            {'access_token': '2.00jqYNTGfgNAXEbd85e6c672uTGF8E',
            'remind_in': '157679999', 'expires_in': 157679999,
            'uid': '5928542965', 'isRealName': 'true'}
        '''
        uid = response.get('uid')
        if not uid:
            # 如果没有返回 uid 证明第三方授权失败
            data = {'code':202,'mes':'三方授权失败'}
        else:
            '''
                有uid的话就拿uid去三方社交表去查表里有没有这个uid,如果有就可以直接返回token登录,没有就需要前端引导用户去绑定自己的信息
            '''
            try:
                socialuser = models.SocialUser.objects.get(uid=uid)
                # 将查询出来的 socialuser 生成载荷 创建 token
                payload = jwt_payload_handler(socialuser.user)   # 创建载荷
                token = jwt_encode_handler(payload)              # 创建 token
                data = {'code':200,'token':token,'username':socialuser.user.username,'user_id':socialuser.user.id}

            except:
                '''
                    将response返回前端,前端保存access_token,uid再通过后台访问微博获取用户信息入库
                '''
                data = {'code':201,'mes':json.dumps(response)}

        return Response(data)

上面说到有两种情况,社交表里有 uid 和没有 uid,有uid 的直接返回 token 前端保存登录成功,没有 uid 前端就该跳到用户绑定页面
vue&django微博第三方登录_第10张图片
vue绑定页面代码


后台代码

# 拿到前端的 access_token,uid向微博获取用户信息 入库返回前端 token/
class Bind_user(APIView):

    def post(self,request):
        from django.http import QueryDict
        
        username = request.data['username']
        password = request.data['password']
        password2 = request.data['password2']
        try:
            access_token_object = json.loads(request.data.get('access_token_object'))
        except:
            return Response({'code':201,'mes':'没有第三方认证'})

        if not all([username,password,access_token_object]):
            mes = {'code':201,'mes':'输入不能为空'}
            return Response(mes)
        else:
			# 拼接访问微博获取用户基本信息链接
            get_user_url = "https://api.weibo.com/2/users/show.json?access_token=%s&uid=%s"%(
                access_token_object['access_token'],access_token_object['uid']
            )
            # 获取到了用户信息  准备入库
            data = requests.get(url=get_user_url).text
            data_user = {'username':username,'password':password,'password2':password2,'email':'***@qq.com','mobile':'***'}
            # 反序列化器只接收 QueryDict 对象,这里转了类型
            queryDict_user = QueryDict('', mutable=True)
            queryDict_user.update(data_user)
            try:
                with transaction.atomic():
                  # 其实可以入库了,这里多事了,用了反序列化器
                    user = serializer.userSerializer(data=queryDict_user)
                    if user.is_valid():
                        user.save()
                        
                    users = models.Users.objects.filter(username=username).first()
                    
                    data_socialuser = {'platfrom_id':1,'platfrom_type':2,'uid':access_token_object['uid']}
                    queryDict_socialuser = QueryDict('', mutable=True)
                    queryDict_socialuser.update(data_socialuser)
                                                                                # 涉及到外键就要把对象传过去反序列器接受
                    socialuser = serializer.socialuserSerializer(data=queryDict_socialuser,context={'outer_key':users})
                    if socialuser.is_valid():
                        socialuser.save()
                        payload = jwt_payload_handler(users)   # 创建载荷
                        token = jwt_encode_handler(payload)              # 创建 token
                        mes = {'token':token,'username':users.username,'user_id':users.id}
                        return Response(mes)
                    
            except:       
                  return Response('授权失败')

这里用反序列化器入库,要在 serialializer.py 里创建反序列化器

# 用户社交表 反序列化器
class socialuserSerializer(serializers.Serializer):
	# 要入什么字段就在这里写什么字段,字段名一定要和表里的一致
    platfrom_id = serializers.IntegerField()
    platfrom_type = serializers.IntegerField()
    uid = serializers.CharField()
    
    class Meta:

        fields = "__all__"
        model = models.SocialUser   # 指定的表
        related_name='user_info'
    def create(self,validated_data):
        
        # 这个表关联着用户的外键,   user:是社交表的外键字段   self.context['outer_key']:views传过来		的users对象
        users = models.SocialUser.objects.create(user=self.context['outer_key'],**validated_data)   # 创建用户

        return users

下面这些就是微博返回的 用户基本信息,自己也可以打印出来看看

‘’’
{“id”:6211711885,“idstr”:“6211711885”,“class”:1,“screen_name”:“用户6211711885”,“name”:“用户6211711885”,“province”:“100”,“city”:“1000”,“location”:“其他”,“description”:"",“url”:"",“profile_image_url”:“http://tvax2.sinaimg.cn/default/images/default_avatar_male_50.gif",“cover_image_phone”:“http://ww1.sinaimg.cn/crop.0.0.640.640.640/549d0121tw1egm1kjly3jj20hs0hsq4f.jpg”,“profile_url”:“u/6211711885”,“domain”:"",“weihao”:"",“gender”:“m”,“followers_count”:1,“friends_count”:1,“pagefriends_count”:0,“statuses_count”:0,“video_status_count”:0,“favourites_count”:0,“created_at”:"Sun Apr 23 20:46:07 +0800 2017”,“following”:false,“allow_all_act_msg”:false,“geo_enabled”:true,“verified”:false,“verified_type”:-1,“remark”:"",“insecurity”:{“sexual_content”:false},“ptype”:0,“allow_all_comment”:true,“avatar_large”:“http://tvax2.sinaimg.cn/default/images/default_avatar_male_180.gif",“avatar_hd”:“http://tvax2.sinaimg.cn/default/images/default_avatar_male_180.gif”,“verified_reason”:"",“verified_trade”:"",“verified_reason_url”:"",“verified_source”:"",“verified_source_url”:"",“follow_me”:false,“like”:false,“like_me”:false,“online_status”:0,“bi_followers_count”:0,“lang”:“zh-cn”,“star”:0,“mbtype”:0,“mbrank”:0,“block_word”:0,“block_app”:0,“credit_score”:80,“user_ability”:0,“urank”:0,“story_read_state”:-1,“vclub_member”:0,“is_teenager”:0,“is_guardian”:0,"is_teenager_list”:0}
‘’’

终于写完了,太麻烦了

你可能感兴趣的:(Django,vue)