django实现,微博第三方登录超详细
登录流程
- 前端获取认证code
- 在Vue页面加载时动态发送请求获取微博授权url
- django收到请求的url后,通过微博应用ID(client_id)和回调地址(redirect_uri)动态生成授权url返回给Vue
- 当用户点击上面的url进行扫码,授权成功会跳转我们的回调界面并附加code参数
- Vue获取到微博返回的code后,会将code发送给django后端(上面的redirect_uri)
获取微博access_token
后端获取code后,结合client_id、client_secret、redirect_uri参数进行传递,获取微博access_token获取微博用户基本信息并保存到数据库
使用获得的access_token调用获取用户基本信息的接口,获取用户第三方平台的基本信息
用户基本信息保存到数据库,然后关联本地用户,然后将用户信息返回给前端生成token给Vue
django后端借助微博认证成功后,可以使用JWT生成token,返回给Vue
Vue将token存储到localStorage中,以便用户访问其他页面进行身份验证
前言:Vue Django 的跨域已经解决,Vue 是一个已经存在的项目 美化后的页面都是已经存在的,数据库的表格都已存在。
核心思想:
- 在微博开放平台 创建网页应用
- 通过微博规定的 规格参数换取
- 审核全部通过 登录信息入库
- 判断登录的 新老用户 是否绑定邮箱
登录微博开放平台,如果是新用户会审核一些东西,可以略过那些,选择性填写。。
注册好应用后我们不需要 填写那些 信息,我们主要用到的是这两个参数,是会用它去调取微博的各项参数最后换取 登录权
设置回调页,就是说登陆之后的跳转页面
查看获取第三方登录权限的文档
(这里很重要)
我们只会用到这三个授权,看一下里面的文档。(将三个文档全部观看)
这些文档中的返回值字段,只要是 True 形式的就必须填写,执行流程就是 这三个图片中的字段,在接口中对应的去请求。
比如第一张图片所需的参数,去请求给定的 url,就会获取到 对应的参数 然后在去请求下一个url。第三方登录就完成了。
首先 已知的条件
App Key:2851645393
App Secret:e646691419daa4bcb80c1bd95164b583
Url:https://api.weibo.com/oauth2/authorize (第一个文档中 给定好的)
CallBack: http://127.0.0.1:8080/course_index
由文档可知(文档在上面的截图) :
1. client_id true string 申请应用时分配的AppKey。
2. redirect_uri true string 授权回调地址,站外应用需与设置的回调地址一致,站内应用需填写canvas page的地址。
注:文档中的参数 字段 必须要遵守,字段名也要一致
我们预热一下,点击查看我拼接查看好的地址 https://api.weibo.com/oauth2/authorize?client_id=2851645393&redirect_uri=http://127.0.0.1:8080/course_index。
可以点击扫描二维码,毕竟登陆快、哈哈
如果:
再多次尝试登陆之后会出现这样的页面代表着,浏览器已经存储了登录的Cookie Token 清楚浏览器数据缓存就 OK。像下面这样
当然你也可以直接授权,但是 后期的 保存登录状态就 不好设置了 会重叠 不利于 浏览。
好了现在写后台接口请求对应的 url
写 接口之前 先把前台的 扫码前地址和扫码后的地址 写好。这里我用的是 Vue.js 前端框架。
//这是项目首页的 a 标签
<a href="https://api.weibo.com/oauth2/authorize?client_id=598520287&redirect_uri=http://127.0.0.1:8080/weibo_callback
"><i class="fa fa-weibo"></i></a>
看一下 效果
我们点击扫码登陆后 (没写跳转后的页面肯定有报错)发现 url 收到了 code 参数
写一个 Vue 页面接收这个 code 然后发送给后台 Django。
<template><div id="weibo_callback"><h3>{{message}}</h3></div>
</template><script>
import axios from 'axios'export default {name: "weibo_callback",data() {return{message:''}},mounted() {var code = this.$route.query.code;var form_data = new FormData();form_data.append('code', code);console.log(code);axios({'url': 'api/user/get_weibo_code/','method': 'post','data': form_data})
我们通过 Vue 的 this.$route.query 获取到 code 值,然后存放到 FormData 发送到后台。
到这里我 有一个 思想,定义一个 类 然后 去换取参数的用另外定义的方法–(此时用到的函数试图是不配置路由的,他们只是换取所需值的方法,最终都是类试图进行调取)
用类试图接收 code 值,再用函数方法去请求 weibo api接口
# 接收 微博回调页面 发送的 code
class Get_WeiBo_Code(APIView):def post(self, request):code = request.data['code']
# views.py
# Vue 发送的 不是这个接口 在下面 那个类试图
# 通过 授权过的 token 获取 Access_tokendef get_weibo_accesstoken(code):# 获取 access_token 的必要参数 ↓url = 'https://api.weibo.com/oauth2/access_token'data = {'client_id': '2851645393', # 创建应用的 App Key'client_secret': '646691419daa4bcb80c1bd95164b583', # 创建应用的 App Secret'grant_type': 'authorization_code', # 文档 写死'redirect_uri': 'http://127.0.0.1:8080/course_index', # 回调地址'code': code # 接收到的编码}# 构造 post 对 weibo 的 url 发起请求res = requests.post(url=url, data=data).text`在这里插入代码片`print('<206>Token 换取的结果:', res)# 得到请求转换为 字典 然后 取 键return json.loads(res)['access_token']
因为要换取的东西有多个,accesstoken userinfo 等 所以 定义对应的请求方法,然后在 类方法调用 就简单很多了。
def get_weibo_accesstoken(code):, post 携带参数去请求,res 转成文本 取出 取出access_token 返回。
拿到 access_token 参数请求微博,他会返回我们 uid ,这个 uid 是 用户的唯一标识符。每次用户 扫码 发送的 uid 都是固定的,写一张表建立一个这样的字段然后保存他。
同时再去用刚才微博返回过来的 accesstoken 请求微博换取token
# 查询 Access_token 的相关信息 (获取 weibo 唯一标识符 uid)
def get_weibo_userinfo(access_token):url = 'https://api.weibo.com/oauth2/get_token_info'data = {'access_token': access_token,}res = requests.post(url=url, data=data).textprint('<218>Access 的相关信息:', res)return json.loads(res)['uid']# 接收 微博回调页面 发送的 code
class Get_WeiBo_Code(APIView):def post(self, request):code = request.data['code']print(code)# 通过 code 获取授权的 access_tokenaccess_token = get_weibo_accesstoken(code)uid = get_weibo_userinfo(access_token)
# models.py
# 第三方平台登陆标识 表
class Social(models.Model):# 这里说一下 uid 是 每个平台都会 拥有的 是为了标明用户的身份uid = models.CharField(max_length=100, verbose_name='uid')user = models.ForeignKey('User', on_delete=models.CASCADE)THIRD_PARTY_CHOICE = {(1, 'QQ'),(2, 'WX'),(3, 'WB'),}third_party = models.IntegerField(choices=THIRD_PARTY_CHOICE)def __str__(self):return self.user.name
创建好 表后 迁移。
# terminal
python manage.py makemigrations
python manage.py migrate
判断 用户之前 是否绑定过 微博,绑定过 就直接登录,没绑定过 重新 绑定一下。
class Get_WeiBo_Code(APIView):def post(self, request):code = request.data['code']print(code)# 通过 code 获取授权的 access_tokenaccess_token = get_weibo_accesstoken(code)uid = get_weibo_userinfo(access_token)# 从数据库 取 数据判断 用户是否 注册过try:s = models.Social.objects.get(third_party=3, # 直接绑定微博uid=uid)except:# 当 抛出异常就代表没有(微博用户)# 给出对应的 数据return Response({'code': '10030','message': '用户不存在,请绑定本站','uid': uid})else:# 没有 异常 代表曾经注册过# 生成 token 保存登录状态data = {'id': s.user.id,'email': s.user.email}jwt_token = create_JWT_(data)# 发送到前台return Response({'code': 200,'message': '您是本站的老用户','token': jwt_token,'email': s.user.email})
补充 这个 jwt 是我 给用户加密的方法 自己生成的 伪随机数。
# 生成 JWT 加密
def create_JWT_(data):jwt_ = Risk_Serializer(SECRET_KEY, JWT_EXPIRE)return jwt_.dumps(data).decode()# 解除 JWT 加密
def remove_JWT_(jwt_):try:jwt_ = Risk_Serializer(SECRET_KEY, JWT_EXPIRE)except SignatureExpired:return Nonereturn jwt_.loads(jwt_)
写完 逻辑之后 要给 前台 一个响应了。
axios({'url': 'api/user/get_weibo_code/','method': 'post','data': form_data}).then((res)=>{// 判断用户是否 登陆成功, 如果成功 保持用户的 token 状态,然后直接 跳转到 首页(在后台 批判断过是否 绑定过 微博)if(res.data.code == 200){var token = res.data.tokenwindow.localStorage.setItem('token', token)this.$router.push({name : 'course_index'})}else {// 如没成功 就代表着 没 绑定过微博。跳转 然后携带我们的 唯一标识this.message = res.data.messagethis.$router.push({name: 'bind_weibo',query: {'uid': res.data.uid}})}})
// 绑定微博的页面
<template>
<div id="bind_weibo"><form @submit.prevent="register_"><input type="email" v-model="register_email" @blur="check_email" class="form-control" placeholder="请输入邮箱"><input type="password" v-model="register_pwd" class="form-control" placeholder="请输入密码"></form><button @click="bind_weibo">绑定</button><h3>{{ message }}</h3></div>
</template>
定义点击事件,请求接口。
<script>import axios from 'axios'export default {name: "bind_weibo",data() {return {register_email: '',register_pwd: '',Can_be_bound: false,message: ''}},methods: {check_email() {var form_data = new FormData()form_data.append('email', this.register_email)axios({'url': 'api/user/check_email/','method': 'post','data': form_data}).then((res) => {if (res.data.code == 200) {this.Can_be_bound = true}this.message = res.data.message})},
很简单吧,请求个接口,并同时判断 密码长度是否 足够长。看着代码很臃肿,多 且 乱 一步一步看 都是简单的。我们 用到了 @blur。
@blur 是什么?
@blur 是当元素失去焦点时所触发的事件
当页面失去焦点的时候,触发 验证一下 邮箱是否可以被使用
# 检查邮箱是否被使用 过
class Check_email(APIView):def post(self, request):email = request.data['email']try:models.User.objects.get(email=email)except:return Response({'code': 200,'message': '邮箱可以被使用'})else:return Response({'code': 10200,'message': '邮箱被占用'})
点击绑定微博 触发的事件,
bind_weibo() {if (!this.Can_be_bound) {this.message = '邮箱不可以被绑定'} else {var register_pwd = this.register_pwd.lengthconsole.log(register_pwd)if (register_pwd < 6) {this.message = '邮箱密码不得小于7位'} else {var form_data = new FormData()form_data.append('email', this.register_email)form_data.append('pwd', this.register_pwd)form_data.append('uid', this.$route.query.uid);axios({'url': 'api/user/bind_weibo/','method': 'post','data': form_data}).then((res) => {if (res.data.code == 200) {window.localStorage.setItem('token', res.data.token)this.$router.push({name: 'course_index'})}})}}},mounted() {this.uid = this.$route.query.uid}}
</script>
看注释
# 当是新用户的时候 绑定 邮箱
class Bind_weibo(APIView):def post(self, request):# 获取前台数据email = request.data['email']pwd = request.data['pwd']uid = request.data['uid']# 生成新的用户user = models.User.objects.create(email=email,pwd=pwd)# 由接口 获取 判断是 weibo 的用户data = {'third_party': 3,'uid': uid,}# 反序列化 数据 存入 Social 表s = SocialSerializer(data=data, context={'user': user})if s.is_valid():s.save()# 生成 需要加密的数据data = {'id': user.id,'email': user.email}# 加密 发送到前台 保存登录状态jwt_token = create_JWT_(data)return Response({'code': 200,'token': jwt_token,'email': user.email})else:return Response({'code': 10300,'message': '数据填写不完整'})
# 序列化器
class SocialSerializer(Serializer):uid = serializers.CharField(max_length=190)third_party = serializers.IntegerField()def create(self, data):print(self.context)s = models.Social.objects.create(user=self.context['user'],**data)return s
呼 这样的话 就都完成了 收工。
django实现,微博第三方登录超详细相关推荐
- java 微博第三方登录_java第三方登录(微博,QQ)详细代码
第三方登录,首先需要设计扩展性的表结构.参照如下:本文主要写第三方登录的代码. 浅谈数据库用户设计:http://www.cnblogs.com/jiqing9006/p/5937733.html 可 ...
- 瞬间心情愉悦,头发都少掉了几根!---Django+uwsgi+Nginx项目部署超详细步骤
文章目录 瞬间心情愉悦,头发都少掉了几根!---Django+uwsgi+Nginx项目部署超详细步骤 先决条件 步骤 本地运行测试 上传服务器 环境安装 准备django程序 完美解决! 瞬间心情愉 ...
- web接入微博第三方登录
微博第三方登录 最近刚好在学习第三方登录,这里先做一下微博第三方登录的记录,因为qq第三方登录必须要完成网站备案后才能进行,后面再进行补充. 大致可以分成下面几个步骤 下面根据我自己的实现过程做一下总 ...
- 微博第三方登录,拿捏了
什么是第三方登录? 用户登录操作不是基于自身建设账号体系,而是基于用户在第三方平台上已有的账号和密码来快速完成登录的过程.下面我列举了几点第三方登录的优点. 极大的简化登录注册的流程. 方便用户快捷登 ...
- 关于微博第三方登录的Javascript的实现方法
微博官方API支离破碎,仿佛都是实习生的练手之作.让我这种大菜鸟郁闷不已,搜网上的微博第三方登录,基本都是只有问题没有解决结果.最后解决了,所以写下这篇文章,已祭奠我的一上午. 首先,登录http:/ ...
- yii 框架微博第三方登录
Yii2集成第三方微博登录(包含账号申请.建表和常用业务逻辑全套流程) 第三方登录 yii php 星空幻颖 2016年09月28日发布 赞 | 0 收藏 | 8 1.5k 次浏览 微博登录 ...
- java判断用户是否在某一个区域登录_Java实现QQ登录和微博第三方登录
来源:http://www.cnblogs.com/liuxianan转自公众号:Java后端 1. 前言 个人网站最近增加了评论功能,为了方便用户不用注册就可以评论,对接了 QQ 和微博这 2 大常 ...
- java 微博第三方登录_Connect/login - 微博API
微博登录 微博登录包括身份认证.用户关系以及内容传播.允许用户使用微博帐号登录访问第三方网站,分享内容,同步信息.它有如下特点: • 直接用微博账号登录你的应用或网站: • 获得高质量微博活跃用户: ...
- java qq微信微博第三方登录界面_android 实现第三方登录(微博、微信、QQ登录)
[实例简介]此案例是演示案例,大家可以看到Bmob的第三方登录和信息获取如何工作的 实现了 qq.微信.微博的 第三方登录功能 [实例截图] [核心代码] package com.bmob.demo. ...
最新文章
- kendoui仪表盘和柱状图 示例
- CentOS 6.5 安装与配置LAMP
- 如何在 IntelliJ IDEA 中整合 Maven、Tomcat 部署 Web 应用
- 【mac开发环境】第1篇:ITerm2+Oh My Zsh
- nutshell_Nutshell中的Java 8语言功能-第1部分
- 基于redis购物车java代码_基于redis实现购物车基本功能
- md5 java .net_.net, java MD5 加密 互换
- 毕设日志——TensorFlow安装的numpy覆盖?掉了pytorch的numpy
- 计算机应用技术老师全国计算机应用技术考试,全国计算机应用证书 全国计算机应用技术证书考试作业.doc...
- 字典的增删改查 daty 5
- 谁说 Java 不能用来跑 Serverless?
- 为Laravel的artisan指令增加bash脚本
- 异步消息队列Celery
- 机械设计专业课程C语言,c语言项目总结ppt[工作范文](20页)-原创力文档
- 使用命令强制关闭端口进程
- echarts3力引导布局,固定某节点
- 裴礼文数学分析中的典型问题与方法第3章一元微分学练习
- 如何解决Worm.Win32.AutoRun.bqn(文件夹改exe病毒)
- 职场险恶,程序员看完都惊呆了
- 空间换时间小例子(2)
热门文章
- Bash技巧:介绍 $0、$1、$2、$#、$@、$*、$? 的含义
- Siege压力测试工具的安装及使用+python flask的四种wsgi方式对比
- 卡波姆对皮肤的作用副作用_玻尿酸对皮肤怎么样?有伤害吗?
- 安装 Intel RST (Intel Rapid Storage Technology) 磁盘阵列驱动时,提示 “此产品有一个挂起的重新启动” 的解决方法
- Android 背景虚化
- miui7 usb计算机连接网络,MIUI7怎么打开usb调试 MIUI7 usb调试找不到怎么办
- echarts柱状图+折线图实例
- 微信公众平台开发入门教程(1)-百度云服务器和微信公众服务器注册申请
- Python_列表解析【i for循环 if i】
- LeetCode刷题-独一无二的出现次数