首页 > 编程问答 >Oauth 检查信用的有效性和服务器的可访问性

Oauth 检查信用的有效性和服务器的可访问性

时间:2024-07-23 06:29:26浏览次数:9  
标签:python flask oauth authlib

我正在使用 Google 帐户为我的网站添加 Oauth 登录,并且偶然发现了一件事 - 如何在执行登录流程之前验证 Oath 提供的信息? 首先,我有一个Flask 应用程序以这种方式创建:

是这样实现的:

import logging
import os
from datetime import datetime
from datetime import timedelta
from typing import Any, Dict

import yaml
from flask import Flask, redirect, url_for, g, flash
from flask.typing import ResponseValue
from flask_babel import gettext as _
from flask_login import current_user, logout_user
from werkzeug.wrappers.response import Response

# .. many other local imports ..

def load_config(config_path: str) -> Any:
    with open(config_path, 'r', encoding='utf-8') as config_file:
        config = yaml.safe_load(config_file)

    return config


def create_app(config_path: str = './<path>/config.yaml', config: Any = None) -> Flask:
    if config is None:
        config = load_config(config_path)

    current_app = Flask(__name__,
                        template_folder=..,
                        static_folder=..)

    current_app.config.update(config)

    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)

    db.init_app(current_app)

    with current_app.app_context():
        # ..
        init_extensions(current_app)
        # ..

    return current_app

## .. other stuff ..

if __name__ == "__main__":
    app = create_app()
    app.run()

init_extensions 并且

def init_extensions(app: Flask) -> None:
    """
    Initialize Flask extensions.

    :param app: Flask application instance
    """
    # other inits ..

    # init OAuth
    init_oauth(app)

是: init_oauth 这里棘手的问题是我想添加一个新函数,例如

from authlib.integrations.flask_client import OAuth
from flask import Flask

oauth = OAuth()


def init_oauth(app: Flask) -> None:
    oauth.init_app(app)
    oauth.register(
        name='google',
        client_id=app.config['GOOGLE_OAUTH_CLIENT_ID'],
        client_secret=app.config['GOOGLE_OAUTH_CLIENT_SECRET'],
        server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
        client_kwargs={
            'scope': 'openid email profile'
        }
    )

check_accessibility 这将允许我可以即时检查并打开/关闭登录选项,而不需要为用户尝试登录并发现服务器不工作或其他什么增加额外的麻烦。

oauth = OAuth()


def init_oauth(app: Flask) -> None:
    # same as above

def check_accessibility() -> bool:
    # True, if everything is ok; 
    # False - if >0 creds are incorrect OR 
    # 3rd party server is inaccessible OR 
    # whatever else ..

是否有任何简单的方法来实现此功能?如果没有,如何实现?

Check server accessibility -> Check creds (how)? -> Return bool ?


当然,可以添加一个函数来检查 OAuth 提供程序的可用性和凭据的有效性。以下是如何执行此操作的方法:

import requests
from authlib.integrations.flask_client import OAuth
from flask import Flask, current_app

oauth = OAuth()

def init_oauth(app: Flask) -> None:
    oauth.init_app(app)
    oauth.register(
        name='google',
        client_id=app.config['GOOGLE_OAUTH_CLIENT_ID'],
        client_secret=app.config['GOOGLE_OAUTH_CLIENT_SECRET'],
        server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
        client_kwargs={
            'scope': 'openid email profile'
        }
    )

def check_oauth_accessibility(provider_name: str = 'google') -> bool:
    """
    检查 OAuth 提供程序的可访问性和凭据的有效性。

    Args:
        provider_name: OAuth 提供程序的名称(例如,'google')。

    Returns:
        如果提供程序可访问且凭据有效,则为 True,否则为 False。
    """
    try:
        provider = oauth.create_client(provider_name)
        # 获取服务器元数据以验证连接和凭据。
        response = requests.get(provider.load_server_metadata_url())
        response.raise_for_status()  # 如果状态码不是 200,则引发异常
        return True
    except requests.exceptions.RequestException as e:
        current_app.logger.error(f"无法访问或验证 {provider_name} OAuth 提供程序: {e}")
        return False
    except Exception as e:
        current_app.logger.error(f"检查 {provider_name} OAuth 提供程序时出错: {e}")
        return False

说明:

  1. check_oauth_accessibility 函数:
  2. 接收 provider_name 作为参数,允许检查不同的提供程序。
  3. 使用 oauth.create_client 创建一个 OAuth 客户端实例。
  4. 使用 requests.get 获取提供程序的服务器元数据。
  5. response.raise_for_status() 检查请求是否成功(状态码 200)。如果请求不成功,则引发异常,导致函数返回 False
  6. 如果没有异常,则表示提供程序可访问且凭据有效,函数返回 True

  7. 错误处理:

  8. 使用 try...except 块捕获 requests.exceptions.RequestException 和其他可能发生的异常。
  9. 使用 current_app.logger.error 记录发生的任何错误,以便于调试。

如何使用:

可以在应用程序启动时或需要时调用 check_oauth_accessibility 函数:

@app.route('/login')
def login():
    if not check_oauth_accessibility():
        flash('OAuth 登录当前不可用。请稍后再试。', 'error')
        return redirect(url_for('index'))
    # ... 继续 OAuth 登录流程 ...

其他注意事项:

  • 可能希望实现一个缓存机制,以避免每次都检查 OAuth 提供程序的可访问性。
  • 考虑为不同的错误情况提供更具体的错误消息,例如凭据无效或服务器不可访问。
  • 确保在生产环境中妥善处理错误,例如将用户重定向到错误页面或提供其他登录选项。

标签:python,flask,oauth,authlib
From: 78780920

相关文章

  • AWS Elastic Beanstalk chown PythonPath 错误
    我正在AWS的elasticbeanstalk上部署一个Web应用程序,遇到了同样的错误:[StageApplication].Stoprunningthecommand.Error:chown/var/app/staging/venv/bin/python:nosuchfileordirectory.我在我的环境配置中看到属性:PYTHONPATH:/var/......
  • Python:支持索引的内存对象数据库?
    我正在做一些数据整理,如果我可以将一堆字典放入内存数据库中,然后对其运行简单的查询,这会简单得多。例如,类似:people=db([{"name":"Joe","age":16},{"name":"Jane","favourite_color":"red"},])over_16=db.filter(age__g......
  • 如何构建一维数组的二维数组的特定 Python 结构?
    如何构建一维数组(即行向量)的二维数组的特定结构以满足特定我正在维护的遗留程序的结构?我可以在此结构中生成正确的内容all_measurements[:12]array([[0.,0.,0.,2.],[0.02,0.334,0.04,2.24],[0.04,0.668,0.08,2.48],...........
  • 如何使用 Python Flask 将新的咖啡馆(元素)添加到数据库(SQLite)?
    这是我的代码:@app.route("/add",methods=["POST"])defpost_new_cafe():new_cafe=Cafe(name=request.form.get("name"),map_url=request.form.get("map_url"),img_url=request.form.get("img......
  • 使用 tkinter 为 python 创建 GUI 时如何解决语法错误?
    我是一名Python初学者,决定使用tkinter制作一个小型GUI,该GUI接受用户(潜在餐馆)的3个输入,然后单击按钮后随机输出其中一家餐馆。我不断收到语法错误,并认为它与我的buttonfunc或调用它的命令有关。此代码尚未包含在GUI上输出餐厅的任何位置。任何帮助将不胜感激#Pyth......
  • 在 python 中打开 gnome 终端立即显示为僵尸
    作为背景,我正在编写一个脚本来训练多个pytorch模型。我有一个训练脚本,我希望能够在gnome终端中作为子进程运行。这样做的主要原因是我可以随时关注训练进度。如果我可能有多个GPU,我想在单独的窗口中多次运行我的训练脚本。为了实现这一点,我一直在使用popen。以下代码用于打......
  • python threading.Condition 的意外行为
    我正在尝试同步多个线程。我期望使用threading.Condition和threading.Barrier时的脚本输出大致相同,但事实并非如此。请解释一下为什么会发生这种情况。一般来说,我需要线程在一个无限循环中执行工作(一些IO操作),但是每个循环都是以主线程的权限开始的,而权限是仅在......
  • Python - 逆透视数据框
    我有一个按日期时间索引的表,每个日期时间都有多个层(中心和交货间隔):日期时间中心交货间隔结算点价格2024-01-0101:00:00休斯顿中心1......
  • 试图理解这个错误:致命的Python错误:PyEval_RestoreThread:该函数必须在持有GIL的情况下
    我有一个小型tkinter应用程序,我一直在其中实现最小的“拖放”,主要作为学习实验。我真正关心的是删除文件的文件路径。一切实际上都工作正常,直到我尝试在拖放后打包标签小部件。下面的最小工作示例。有问题的行会用注释指出。我通常不会在调试方面遇到太多麻烦,但我只是不知......
  • 如何使代码格式再次适用于 Python(Mac 上的 Visual Studio Code)?
    在Mac上,Option+Shift+F现在会显示“没有安装用于‘python’文件的格式化程序”。消息框:我尝试安装这个插件,但没有看到这种情况的变化:我已经为Python安装了这两个插件:但是正如@starball提到的,它可能已经减少了支持现在。......