admin管理员组文章数量:1568305
一、什么是第三方登录
是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目。
本文将以QQ登录为例进行详解第三方登录的过程。
二、实现QQ登录
1、准备工作
接入QQ登录前,网站需首先进行申请,获得对应的appid与appkey,以保证后续流程中可正确对网站与用户进行验证与授权。
(1)需要成为QQ互联的开发者,审核通过才可实现;
(2)成为QQ互联开发者后,还需创建应用,即获取本项目对应与QQ互联的应用ID;
appid:应用的唯一标识。在OAuth2.0认证过程中,appid的值即为 oauth_consumer_key的值。
appkey:appid对应的密钥,访问用户资源时用来验证应用的合法性。在OAuth2.0认证过程中,appkey的值即为oauth_consumer_secret的值。
2、QQ登录的开发流程
如上图所示:
(1)当用户点击前端界面上的QQ登录的图标时,便会向后端发起一次获取QQ登录的url。为什么不把url直接放置在前端呢?原因是与用户关联的登录地址是需要与后台的appid与appkey,很显然这两个字段是不能暴露出来的,否则会被他人滥用了。以下是QQ登录的地址及参数说明:
Step1:获取Authorization Code
请求地址:
PC网站:https://graph.qq/oauth2.0/authorize
请求方法:
GET
请求参数请包含如下内容:
代码实现:
import requests
from urllib.parse import urlencode
from django.conf import settings
class OAuthQQ(object):
"""
QQ认证辅助工具类
"""
def __init__(self, app_id=None, app_key=None, redirect_uri=None, state=None):
self.app_id = app_id or settings.QQ_APP_ID
self.app_key = app_key or settings.QQ_APP_KEY
self.redirect_url = redirect_uri or settings.QQ_REDIRECT_URL
self.state = state or '/' # 用于保存登录成功后的跳转页面路径
def get_auth_url(self):
"""
获取qq登录的网址
:return: url网址
"""
params = {
'response_type': 'code',
'client_id': self.app_id,
'redirect_uri': self.redirect_url,
'state': self.state,
'scope': 'get_user_info',
}
url = 'https://graph.qq/oauth2.0/authorize?' + urlencode(params)
return url
(2) 获取到qq登录地址后,前端进一步做跳转,让用户在QQ登录平台做认证,这个过程,我们是无法操作的;如果用户成功登录并授权,则会跳转到指定的回调地址,并在redirect_uri地址后带上Authorization Code和原始的state值;如果用户在登录授权过程中取消登录流程,对于PC网站,登录页面直接关闭;对于WAP网站,同样跳转回指定的回调地址,并在redirect_uri地址后带上usercancel参数和原始的state值,其中usercancel值为非零。注意:此code会在10分钟内过期。
在用户授权登录成功后,就跳转到我们就设置好了回调地址redirect_uri,即返回了一个HTML的界面,在页面加载完成前,前端应把授权code返回到后端,后端才能发起下一步的请求:获取access_token
(3)通过Authorization Code获取Access Token
请求地址:
PC网站:https://graph.qq/oauth2.0/token
请求方法:
GET
请求参数:
代码实现:
在QQ认证辅助类中添加如下代码:
def get_access_token(self, code):
"""
获取access_token
:param code: qq提供的code
:return: access_token
"""
params = {
'grant_type': 'authorization_code',
'client_id': self.app_id,
'client_secret': self.app_key,
'code': code,
'redirect_uri': self.redirect_url
}
response_data = requests.get(url,params=params).text
data = parse_qs(response_data) # 将查询字符串转字典
access_token = data.get('access_token', None)
if not access_token:
raise QQAPIError # 自定义错误类
return access_token[0]
如果成功返回,即可在返回包中获取到Access Token。 如:
access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14
接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。
以上方式获取到的access_token存在一定的有效期(3个月),因此QQ官方也提供了一个自动自动续期,避免要求用户再次授权的操作,提升用户体验。具体可以参考QQ授权的第三步,获取access_token:(可选)http://wiki.connect.qq/%E4%BD%BF%E7%94%A8authorization_code%E8%8E%B7%E5%8F%96access_token
(4)获取用户OpenID_OAuth2.0
本步骤的作用:
通过输入在上一步获取的Access Token,得到对应用户身份的OpenID。
OpenID是此网站上或应用中唯一对应用户身份的标识,网站或应用可将此ID进行存储,便于用户下次登录时辨识其身份,或将其与用户在网站上或应用中的原有账号进行绑定。
接口说明:
代码实现:
在QQ认证辅助类中添加如下代码:
def get_openid(self, access_token):
"""
获取用户的openid
:param access_token: qq提供的access_token
:return: open_id
"""
params = {
'access_token':access_token
}
url = 'https://graph.qq/oauth2.0/me
response_data = requests.get(url,params=params)
try:
# 返回的数据 callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )\n;
data = json.loads(response_data[10:-4]) #不知道为什么要返回这么反人类的参数。。
except Exception:
raise QQAPIError
openid = data.get('openid', None)
return openid
(5)根据openID获取用户基本信息
返回上面的接口便可以拿到用户的QQ名、个人签名、头像等等信息,此处的代码实现就省略不写了。。
至此,与QQ方面相关的操作已经全部完成了,接下来的是用户与项目服务器之间的操作了。
以下步骤也可以省略,因为用户使用第三方登录,就是希望不要去填写登录注册那些恶心的东西,再去绑定的话,会奔溃的吧…
三、将openId与user_id进行关联
1、首先,创建一张QQ用户表与user表进行关联,代码如下:
from django.db import models
class OAuthQQUser(model.Model):
"""
QQ登录用户数据
"""
user = models.ForeignKey('users.User', on_delete=models.CASCADE, verbose_name='用户')
openid = models.CharField(max_length=64, verbose_name='openid', db_index=True)
class Meta:
db_table = 'tb_oauth_qq'
verbose_name = 'QQ登录用户数据'
verbose_name_plural = verbose_name
2、判断用户是否绑定
查询数据库中是否有该用户的openID,如果有则说明已经登录并绑定过了,那么按照正常的登录步骤流程往下即可;如果没有,则让前端跳到附带access_token的用户绑定界面。那么用户提交绑定界面时,把手机号、昵称密码传到后端进行处理。代码如下:
根据手机号获取user
if not user: # 做此步判断是因为用户可能已经在服务器端注册过了
# 用户不存在,则更新数据库中user的相关信息
user = User.objects.create_user(
username=validated_data['mobile'],
password=validated_data['password'],
mobile=validated_data['mobile'],
)
# 关联QQ_openId
OAuthQQUser.objects.create(
openid=openid
user=user
)
版权声明:本文标题:第三方登录(单点登录) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1726185602a1059488.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论