Python PyQt5应用程序的替代OAuth2登录
我有一个带有Google登录的PyQt5应用程序,它是使用实现的。使用Python PyQt5应用程序的替代OAuth2登录,python,pyqt5,google-oauth,Python,Pyqt5,Google Oauth,我有一个带有Google登录的PyQt5应用程序,它是使用实现的。使用QWebEngineView在嵌入式浏览器中显示登录页面。但是,对于,我的应用程序中需要进行更改,以打开系统浏览器,然后接收来自该浏览器的授权响应。为此,我正在使用,这也在中使用 我创建了一个小型POC,它只是实现了这个工作流,但我面临着几个问题: 登录页面将在新浏览器窗口或选项卡中打开。但这可能不是一个好的用户体验,因为用户必须在登录后关闭浏览器,然后返回应用程序。在这里打开弹出式浏览器似乎是更好的用户体验。我检查了负责打开
QWebEngineView
在嵌入式浏览器中显示登录页面。但是,对于,我的应用程序中需要进行更改,以打开系统浏览器,然后接收来自该浏览器的授权响应。为此,我正在使用,这也在中使用
我创建了一个小型POC,它只是实现了这个工作流,但我面临着几个问题:
run\u local\u server
方法的源代码,他们似乎使用了webbrowser
模块,不幸的是,该模块没有打开弹出窗口的方法
run\u local\u server
方法打开的浏览器,则调用它的应用程序将冻结,需要强制退出。我也没有注意到任何控制台错误。我正在使用的库是否有办法处理这个问题
QWebEngineView可用作浏览器进行身份验证,但必须设置有效的用户代理。另一方面,google auth oauthlib请求正在阻塞,因此它们必须在不同的线程中执行,并通过信号通知结果:
导入工具
导入日志记录
导入操作系统
进口泡菜
导入系统
导入线程
从PyQt5导入QtCore、QtGui、QtWidgets、QtWebEngineWidgets
从google_auth_oauthlib.flow导入安装的应用程序流
从google.auth.transport.requests导入请求
从GoogleAppClient.discovery导入生成
作用域=[
"https://www.googleapis.com/auth/userinfo.profile",
“openid”,
"https://www.googleapis.com/auth/userinfo.email",
]
CURRENT_DIR=os.path.dirname(os.path.realpath(uu文件_uu))
logging.basicConfig(级别=logging.DEBUG)
班级回复(QtCore.QObject):
finished=QtCore.pyqtSignal()
def(self,func,args=(),kwargs=None,parent=None):
super()。\uuuu init\uuuu(父级)
self.\u结果=无
self.\u is\u finished=False
self._error_str=“”
穿线,穿线(
target=self.\u execute,args=(func,args,kwargs),daemon=True
).start()
@财产
def结果(自我):
返回self.\u结果
@财产
def错误_str(自身):
返回self.\u错误\u str
def已完成(自):
返回自我。完成
def有错误(自身):
返回布尔值(自身错误)
def_execute(self、func、args、kwargs):
如果kwargs为无:
kwargs={}
尝试:
self._results=func(*args,**kwargs)
例外情况除外,如e:
自我错误,自我错误=str(e)
self.\u已完成=真
self.finished.emit()
def转换为应答(func):
def包装(*args,**kwargs):
回复=回复(func、args、kwargs)
回覆
返回包装器
类后端(QtCore.QObject):
started=QtCore.pyqtSignal(QtCore.QUrl)
finished=QtCore.pyqtSignal()
def uuu init uuu(self,parent=None):
super()。\uuuu init\uuuu(父级)
自助服务=无
@财产
def服务(自助):
如果自助服务为无:
回复=self.\u更新\u凭证()
loop=QtCore.QEventLoop()
reply.finished.connect(循环.退出)
loop.exec()
如果没有,请答复。有错误()
self.\u service=reply.results
其他:
logging.debug(reply.error\u str)
返回自助服务
@将_转换为_回复
def_更新_凭证(自我):
信誉=无
如果os.path.exists(“token.pickle”):
以open(“token.pickle”、“rb”)作为令牌:
creds=pickle.load(令牌)
如果没有信用或信用无效:
如果creds和creds.expired和creds.refresh\u令牌:
creds.refresh(请求())
其他:
flow=InstalledAppFlow.from_client_secrets_文件(
“credentials.json”,作用域
)
host=“localhost”
端口=8080
state=“default”
QtCore.QTimer.singleShot(
0,functools.partial(self.get_url、流、主机、端口、状态)
)
creds=flow.run\u本地\u服务器(
主机=主机,端口=端口,打开浏览器=错误,状态=状态