对于 REST API,我可以使用flask-login 提供的身份验证机制,还是必须明确使用基于令牌的身份验证,例如 JWT?

ker*_*nic 0 python authentication api flask access-token

规格:我正在使用 PyQt5 在 Python 中编写桌面应用程序。我的应用程序通过提供 RESTful 路由的 Flask API 与远程数据库通信。Flask API 和数据库位于同一台服务器上。在客户端,我使用RequestsPython 中的模块。我必须在我的应用程序中实现用户身份验证和授权系统。目前,我正在使用烧瓶登录。

@app.route("/login", methods=['POST'])
def login():
    user = User.query.filter_by(email = request.form["email"]).first()
    if user and check_password():
       flask_login.login_user(user, remember=request.form['remember'])
       return Response(status=201)
    else:
        return Response(status=401)
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我正在检查用户是否存在并且散列密码是否匹配。如果是这样,flask_login 将自动登录用户并发送回cookie响应,我可以将其用于会话管理和其他内容。

我的问题:我在任何地方都读到过使用基于令牌的身份验证系统来保护 API。但是,我目前的方法有什么问题吗?这不是实现身份验证的传统方式吗?此外,它在任何意义上都比基于令牌的系统更不安全吗?

ste*_*eve 5

您的问题的答案并非直截了当,但简而言之,这通常可能是保护 API 的一种糟糕方式。但是,如果这是您所熟悉的,那么您可能可以通过这种方式逃脱,因为它们不是为什么这实际上不起作用的“技术”原因。

API 通常希望每次请求都将访问凭证/令牌发送到 API。这类似于 Web 服务器(Flask)直接返回 html/js 代码时对请求进行身份验证的方式。

然而,区别在于客户端用于提交身份验证证明的机制。在后端提供前端代码的典型应用程序中,cookie 用于存储会话信息,这些 cookie 由客户端(浏览器)在每次请求时自动发送到后端。

在您的情况下,Flask Login 正在查看这些 cookie 并验证它们的真实性,并根据服务器上会话中存储的信息确定哪个用户发出了请求。

您提到您的客户端是一个使用 Python Requests 库的桌面应用程序,因此如果您想继续使用您拥有的 auth 方法,您可能希望对桌面客户端进行编程以使用requests.Session 对象发送请求。这基本上包装了您的请求并为您存储 cookie。为此,您使用 request.Session 对象发出初始登录请求,然后所有后续请求将自动发送 cookie,您的 Flask 应用程序将看到您的桌面应用程序已登录。查看文档了解更多信息.

但是,对于 API,Flask Web 服务器不会直接向客户端提供前端代码。事实上,API 不应该关心客户端是否有前端。所有的 API 都知道客户端可能是另一个脚本或curl在终端中运行命令的用户等。重要的是,客户端可能有也可能没有任何“cookies”的概念。因此 API 需要一种方法来验证传入的请求是否经过授权。

就像 cookie 需要随每个请求一起发送一样,API 需要随每个请求发送一些内容,内容为“嘿服务器,我是一个请求,我已获得授权”。

显而易见的解决方案是在每个请求中发送用户名和密码。这个解决方案非常基础,被恰当地称为基本身份验证。显然这里存在安全问题,但是如果 http 流量是加密的 (https) 基本身份验证在客户端是在安全盒上运行的进程的实例中可能没问题,该进程从安全文件读取密码。

Python Requests 模块在以下方面对此提供了支持:Link to Docs 它就像发出这样的请求一样简单:

requests.get('https://api.github.com/user', auth=('user', 'pass'))
Run Code Online (Sandbox Code Playgroud)

然后在 Flask 后端

@app.route(...)
def some_route():
  username = request.authorization.username
  password = request.authorization.password
  # check to make sure username/password is okay
  # could abstract this code as a decorator and apply it to multiple routes
  # that you want protected by basic auth
Run Code Online (Sandbox Code Playgroud)

还有Flask-BasicAuth模块,它似乎使 Flask 接受基本身份验证变得非常容易,尽管我从未使用过它。

但是,在不能假设客户端超级安全的情况下,比如前端 Web 应用程序,作为开发人员的您可能不想直接在浏览器中存储用户名和密码,并且可能有人只是查看本地存储等并查看用户凭据。

基于令牌的身份验证是另一个更安全的选项,基本上客户端将用户名/密码凭据发送到后端一次,并将它们交换为令牌。然后,此令牌随客户端发出的每个请求一起发送。在后端,Web 服务器可以验证令牌的真实性并从中提取身份。令牌可以通过 HTTP 标头发送,也可以通过 url 查询字符串发送。IE www.myapi.com/some-end-point?token=12345678

然后,如果令牌被泄露,用户可以使用他们相同的用户名/密码来获取另一个令牌,旧令牌可能会过期。

如果您想使用基于令牌的身份验证方法,请查看 JSON Web Tokens (JWT),特别是在以下 Flask 插件中: Flask-JWT-Extended Flask-Praetorian