def authorized(): """ 授权回调路由 此路由地址:/oauth2/gitee/authorized """ # 加密的sso参数值 sso = request.args.get("sso") or None # 换取access_token resp = gitee.authorized_response() print resp if resp and isinstance(resp, dict) and "access_token" in resp: # 根据access_token获取用户基本信息 user = gitee.get_userinfo(resp["access_token"]) if not "id" in user: flash(user.get("status", "Gitee error")) return redirect(g.redirect_uri) # 处理第三方登录逻辑 auth = Authentication(g.mysql, g.redis) # 第三方账号登录入口`oauth2_go` goinfo = auth.oauth2_go(name=name, signin=g.signin, tokeninfo=resp, userinfo=dict(openid=user["id"], nick_name=user["name"], gender=2, avatar=user["avatar_url"], domain_name=user["login"], signature=user["bio"]), uid=g.uid) goinfo = dfr(goinfo) if goinfo["pageAction"] == "goto_signIn": """ 未登录流程->已经绑定过账号,需要设置登录态 """ uid = goinfo["goto_signIn_data"]["guid"] # 记录登录日志 auth.brush_loginlog(dict(identity_type=oauth2_name2type(name), uid=uid, success=True), login_ip=g.ip, user_agent=request.headers.get("User-Agent")) # 设置登录态 return gitee.goto_signIn(uid=uid, sso=sso) elif goinfo["pageAction"] == "goto_signUp": """ 未登录流程->执行注册绑定功能 """ return gitee.goto_signUp( openid=goinfo["goto_signUp_data"]["openid"], sso=sso) else: # 已登录流程->正在绑定第三方账号:反馈绑定结果 if goinfo["success"]: # 绑定成功,返回原页面 flash(u"已绑定") else: # 绑定失败,返回原页面 flash(goinfo["msg"]) # 跳回绑定设置页面 return redirect(url_for("front.userset", _anchor="bind")) else: flash(u'Access denied: reason=%s error=%s' % (resp.get('error'), resp.get('error_description'))) return redirect(g.redirect_uri)
def authorized(): """ 授权回调路由 此路由地址:/oauth2/qq/authorized """ # 加密的sso参数值 sso = request.args.get("sso") or None # 换取access_token resp = qq.authorized_response() if "callback" in resp: resp = json.loads(resp[10:-3]) else: resp = qq.url_code(resp) if resp and isinstance(resp, dict) and "access_token" in resp: # 获取用户唯一标识 openid = json.loads(qq.get_openid(resp["access_token"])[10:-3]).get("openid") # 根据access_token获取用户基本信息 user = qq.get_userinfo(resp["access_token"], openid=openid, oauth_consumer_key=PLUGINS[name]["APP_ID"]) if int(user.get("ret", 0)) < 0: flash(user.get("msg")) return redirect(g.redirect_uri) # 处理第三方登录逻辑 auth = Authentication(g.mysql, g.redis) # 第三方账号登录入口`oauth2_go` goinfo = auth.oauth2_go(name=name, signin=g.signin, tokeninfo=resp, userinfo=dict(openid=openid, nick_name=user["nickname"], gender=oauth2_genderconverter(user["gender"]), avatar=user["figureurl_qq_2"] or user["figureurl_qq_1"], location="%s %s" %(user.get("province"), user.get("city"))), uid=g.uid) goinfo = dfr(goinfo) if goinfo["pageAction"] == "goto_signIn": """ 未登录流程->已经绑定过账号,需要设置登录态 """ uid = goinfo["goto_signIn_data"]["guid"] # 记录登录日志 auth.brush_loginlog(dict(identity_type=oauth2_name2type(name), uid=uid, success=True), login_ip=g.ip, user_agent=request.headers.get("User-Agent")) # 设置登录态 return qq.goto_signIn(uid=uid, sso=sso) elif goinfo["pageAction"] == "goto_signUp": """ 未登录流程->openid没有对应账号,执行注册或绑定功能 """ return qq.goto_signUp(openid=goinfo["goto_signUp_data"]["openid"], sso=sso) else: # 已登录流程->正在绑定第三方账号:反馈绑定结果 if goinfo["success"]: # 绑定成功,返回原页面 flash(u"已绑定") else: # 绑定失败,返回原页面 flash(goinfo["msg"]) # 跳回绑定设置页面 return redirect(url_for("front.userset", _anchor="bind")) else: flash(u'Access denied: reason=%s error=%s' % ( resp.get('error'), resp.get('error_description') )) return redirect(g.redirect_uri)
def unbind(): # 解绑账号 identity_name = request.args.get("identity_name") if identity_name: auth = Authentication(g.mysql, g.redis) res = auth.unbind(g.uid, oauth2_name2type(identity_name)) res = dfr(res) if res["code"] == 0: flash(u"解绑成功") else: flash(res["msg"]) else: flash(u"无效参数") return redirect(url_for("front.userset", _anchor="bind"))
def authorized(): """ 授权回调路由 此路由地址:/oauth2/coding/authorized """ # 加密的sso参数值 sso = request.args.get("sso") or None # 换取access_token resp = coding.authorized_response() if resp and isinstance(resp, dict) and "access_token" in resp: # 根据access_token获取用户基本信息 user = coding.get_userinfo(resp["access_token"]) if user["code"] != 0: flash(user["msg"].keys()) return redirect(g.redirect_uri) user = user["data"] # 处理第三方登录逻辑 auth = Authentication(g.mysql, g.redis) # 第三方账号登录入口`oauth2_go` avatar = "https://coding.net" + user["avatar"] if user["avatar"].startswith("/") else user["avatar"] goinfo = auth.oauth2_go(name=name, signin=g.signin, tokeninfo=resp, userinfo=dict(openid=user["id"], nick_name=user["name"], gender=oauth2_genderconverter(user["sex"]), avatar=avatar, domain_name=user["global_key"], signature=user["slogan"], location=user.get("location")), uid=g.uid) goinfo = dfr(goinfo) if goinfo["pageAction"] == "goto_signIn": """ 未登录流程->已经绑定过账号,需要设置登录态 """ uid = goinfo["goto_signIn_data"]["guid"] # 记录登录日志 auth.brush_loginlog(dict(identity_type=oauth2_name2type(name), uid=uid, success=True), login_ip=g.ip, user_agent=request.headers.get("User-Agent")) # 设置登录态 return coding.goto_signIn(uid=uid, sso=sso) elif goinfo["pageAction"] == "goto_signUp": """ 未登录流程->执行注册绑定功能 """ return coding.goto_signUp(openid=goinfo["goto_signUp_data"]["openid"], sso=sso) else: # 已登录流程->正在绑定第三方账号:反馈绑定结果 if goinfo["success"]: # 绑定成功,返回原页面 flash(u"已绑定") else: # 绑定失败,返回原页面 flash(goinfo["msg"]) # 跳回绑定设置页面 return redirect(url_for("front.userset", _anchor="bind")) else: flash(u'Access denied: reason=%s error=%s' % ( request.args.get('error'), request.args.get('error_description') )) return redirect(g.redirect_uri)
def authorized(): """ 授权回调路由 此路由地址:/oauth2/baidu/authorized """ # 换取access_token resp = baidu.authorized_response() print "authorized_response:",resp if resp and isinstance(resp, dict) and "access_token" in resp: # 根据access_token获取用户基本信息 user = baidu.get_userinfo(resp["access_token"]) if user.get("error"): flash("{} error_description: {}".format(user.get("error"), user.get("error_description"))) return redirect(url_for("front.index")) # 处理第三方登录逻辑 auth = Authentication(g.mysql, g.redis) avatar = "http://tb.himg.baidu.com/sys/portrait/item/" + user["portrait"] # 第三方账号登录入口`oauth2_go` goinfo = auth.oauth2_go(name=name, signin=g.signin, tokeninfo=resp, userinfo=dict(openid=user["userid"], nick_name=user["username"], gender=user["sex"], avatar=avatar, signature=user["userdetail"], location=user.get("location")), uid=g.uid) goinfo = dfr(goinfo) if goinfo["pageAction"] == "goto_signIn": """ 未登录流程->执行登录 """ # 记录登录日志 auth.brush_loginlog(dict(identity_type=oauth2_name2type(name), uid=goinfo["goto_signIn_data"]["guid"], success=True), login_ip=request.headers.get('X-Real-Ip', request.remote_addr), user_agent=request.headers.get("User-Agent")) # 设置登录态 return baidu.goto_signIn(uid=goinfo["goto_signIn_data"]["guid"]) elif goinfo["pageAction"] == "goto_signUp": """ 未登录流程->执行注册绑定功能 """ return baidu.goto_signUp(openid=goinfo["goto_signUp_data"]["openid"]) else: # 已登录流程->反馈绑定结果 if goinfo["success"]: # 绑定成功,返回原页面 flash(u"已绑定") else: # 绑定失败,返回原页面 flash(goinfo["msg"]) # 跳回原页面 return redirect(url_for("front.index")) else: flash(u'Access denied: reason=%s error=%s' % ( request.args.get('error'), request.args.get('error_description') )) return redirect(url_for("front.index"))
def authorized(): """ 授权回调路由 此路由地址:/oauth2/github/authorized """ # 换取access_token resp = github.authorized_response() resp = github.url_code(resp) print "authorized_response:",resp if resp and isinstance(resp, dict) and "access_token" in resp: # 根据access_token获取用户基本信息 user = github.get_userinfo(resp["access_token"]) # 处理第三方登录逻辑 auth = Authentication(g.mysql, g.redis) # 第三方账号登录入口`oauth2_go` goinfo = auth.oauth2_go(name=name, signin=g.signin, tokeninfo=resp, userinfo=dict(openid=user["id"], nick_name=user["name"], gender=2, avatar=user["avatar_url"], domain_name=user["login"], signature=user["bio"], location=user.get("location")), uid=g.uid) goinfo = dfr(goinfo) if goinfo["pageAction"] == "goto_signIn": """ 未登录流程->执行登录 """ # 记录登录日志 auth.brush_loginlog(dict(identity_type=oauth2_name2type(name), uid=goinfo["goto_signIn_data"]["guid"], success=True), login_ip=request.headers.get('X-Real-Ip', request.remote_addr), user_agent=request.headers.get("User-Agent")) # 设置登录态 return github.goto_signIn(uid=goinfo["goto_signIn_data"]["guid"]) elif goinfo["pageAction"] == "goto_signUp": """ 未登录流程->执行注册绑定功能 """ return github.goto_signUp(openid=goinfo["goto_signUp_data"]["openid"]) else: # 已登录流程->反馈绑定结果 if goinfo["success"]: # 绑定成功,返回原页面 flash(u"已绑定") else: # 绑定失败,返回原页面 flash(goinfo["msg"]) # 跳回原页面 return redirect(url_for("front.index")) else: flash(u'Access denied: reason=%s error=%s' % ( request.args.get('error'), request.args.get('error_description') )) return redirect(url_for("front.index"))
def oauth2_go(self, name, signin, tokeninfo, userinfo, uid=None): """第三方账号登录入口 参数: @param name str: 开放平台标识,参见`oauth2_name2type`函数 @param signin bool: 是否已登录 @param tokeninfo dict: access_token数据,格式: { "access_token": "ACCESS_TOKEN", "expires_in": "可选,到期时间戳,默认0不限制", "refresh_token": "可选,刷新TOKEN" } @param userinfo dict: 用户数据,包含用户基本信息及用户在第三方网站唯一标识,主要用于注册流程,格式: { "openid": "用户唯一标识", "nick_name": "昵称", "avatar": "头像地址", "gender": "可选,性别",默认2, "signature": "可选,签名,针对github" } @param uid str: 系统本地用户id,当`signin=True`时,此值必须为实际用户id 流程: 1. signin字段判断是否登录 - 已登录,说明已有账号,只需绑定账号即可 1. 判断uid参数,有意义则查询openid是否绑定uid,否则返回失败信息。 2. 如果openid返回uid,说明已经绑定,然后判断绑定账号与uid参数是否一致,一致则尝试更新绑定数据,完成绑定;不一致表示已经绑定其他账号,拒绝操作并返回原页面。 3. 如果openid返回None,说明没有绑定,则直接注册并绑定uid参数。 - 未登录,可能无账号、可能有账号,需要直接注册或绑定已有 1. 查询openid是否绑定uid。 2. 如果openid返回uid,说明已经绑定,转入登录流程,需要设置cookie登录状态。 3. 如果openid返回None,说明没有绑定,此时需要设置是否页面绑定本地账号或直接注册。 """ res = dict(msg=None, success=False, pageAction=None) if isinstance(name, (str, unicode)) and \ signin in (True, False) and \ isinstance(tokeninfo, dict) and \ isinstance(userinfo, dict) and \ "access_token" in tokeninfo and \ "openid" in userinfo and \ "nick_name" in userinfo and \ "avatar" in userinfo: # openid是第三方平台用户唯一标识,微博是uid,QQ是openid,Github是id,统一更新为openid access_token = tokeninfo["access_token"] expires_in = tokeninfo.get("expires_in") or 0 # 重新定义openid规则->加上开放平台前缀 openid = "{}.{}".format(oauth2_name2type(name), userinfo["openid"]) # 覆盖原openid userinfo.update(openid=openid) if signin is True: # 已登录->绑定流程 logger.debug("signin true, uid: {}".format(uid)) if uid: guid = self.__oauth2_getUid(openid) logger.debug("signin true, openid: {}, guid: {}, is equal: {}".format(openid, guid, uid == guid)) if guid: if uid == guid: # 更新绑定的数据 res.update(success=True) else: res.update(msg="Has been bound to other accounts") else: # 此openid没有绑定任何本地账号,更新用户资料 upts = self.__signUp_transacion(guid=uid, identifier=openid, identity_type=oauth2_name2type(name), certificate=access_token, verified=1, expire_time=expires_in, use_profile_sql=False) res.update(upts) else: res.update(msg="Third-party login binding failed") else: # 未登录->注册绑定流程 guid = self.__oauth2_getUid(openid) if guid: # 已经绑定过账号,需要设置登录态 res.update(pageAction="goto_signIn", goto_signIn_data=dict(guid=guid)) else: # 尚未绑定,需要绑定注册 userinfo.update(identity_type=oauth2_name2type(name), access_token=access_token, expires_in=expires_in) if self.__oauth2_setUserinfo(userinfo): res.update(pageAction="goto_signUp", goto_signUp_data=dict(openid=cbc.encrypt(openid))) else: res.update(msg="System is abnormal") else: res.update(msg="Check failed") logger.info(res) return res