所谓的第三方登录,是说基于用户在第三方平台上已有的账号和密码来快速完成己方应用的登录或者注册的功能。而这里的第三方平台,一般是已经拥有大量用户的平台,国外的比如Facebook,Twitter等,国内的比如微博、微信、QQ等。
实现等三方登录首先在第三方开发平台注册账号、注册应用。获取APPID与KEY
实现逻辑:
当用户点击第三方登录时,会跳转到第三方登录SDK内部;用户输入第三方登录用户名或密码,
分为两种情况:
第一种:
使用第三方账号直接登录,即可拥有完整的同本地注册用户相同的待遇。
第二种:
使用第三方登录后,要求绑定应用内账户(如果用户有,则直接绑定,否则需要走应用内的账号注册流程)。
实现第三方登录以钉钉登陆为例
1.接收请求构建扫码的url
class DingDingOauthResource(Resource):
def get(self):
base_url = 'https://oapi.dingtalk.com/connect/qrconnect?appid=%s&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=%s'
# print(current_app.config.get('DING_REDIRECT_URI'),current_app.config.get('DING_APP_ID'))
url = base_url % (current_app.config.get('DING_APP_ID'), current_app.config.get('DING_REDIRECT_URI'))
# print('url>>',url)
return {'url': url, 'code': 200}
用户会跳转到二维码界面,用户扫码会出跳转回调地址并返回code参数
2.后端接收code参数获取钉钉用户信息class DingdingUserInfo(Resource):
def get_ding_user(self, code):
"""获取登录的钉钉用户信息"""
base_url = "https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature="
appid = current_app.config.get('DING_APP_ID')
appSecret = current_app.config.get('DING_SECRET_KEY')
t = time.time()
# 把时间戳转换成毫秒
timestamp = str((int(round(t*1000))))
# 构造签名
signature = base64.b64encode(
hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
# params 是查询字符串参数
# data 是请求体参数
# header 指明传递参数的类型
# 拼接url
url = base_url + urllib.parse.quote(signature.decode('utf-8')) + "×tamp="+timestamp + "&accessKey=" + appid
resp = requests.post(url, data=json.dumps({'tmp_auth_code':code}), headers={'Content-Type': 'application/json'})
return resp.json()
def get(self):
"""根据前端传来的code, 获取钉钉登录的用户信息"""
parser = reqparse.RequestParser()
parser.add_argument('code')
args = parser.parse_args()
code = args.get('code')
# 根据code获取钉钉用户信息
ding_user = self.get_ding_user(code)
if ding_user['errcode'] != 0:
return jsonify(msg="获取钉钉用户信息失败", code=500)
# 获取钉钉的openid
openid = ding_user['user_info']['openid']
if openid:
# 根据openid 判定是否绑定账号
oauth_user = OauthUser.query.filter_by(uid=openid).first()
if oauth_user:
# 查询到用户,已经绑定过,
user = UserModels.query.filter_by(uid=oauth_user.user).first()
# 返回绑定成功的用户token 及id
token = _generate_token({'account': user.account, 'user_id': user.uid,
'is_superuser': user.is_superuser})
return jsonify(msg="登陆成功", data={'code': 200, 'token': token,
'account': user.account, 'uid': user.uid})
else:
return jsonify(msg="没有绑定用户,请先绑定", data={'uid':openid} )
用户登陆成功返回主页



