API 开发
向 Masonite 项目添加 API 支持非常简单。 Masonite 已经支持返回 JSON 响应,但有一些用于身份验证和授权的 API 功能很有帮助。
默认项目不附带这些功能,因此您必须简单地注册它们。
入门
提供者
首先,通过将服务提供者添加到您的 PROVIDERS 列表中,在您的项目中注册 ApiProvider:
from masonite.api.providers import ApiProvider
PROVIDERS = [
#..
ApiProvider
]
这将注册一些用于 API 开发的必需类。
您现在应该创建一个api.py
文件,用于将您的 API 路由添加到:
# routes/api.py
ROUTES = [
Route.get('/users', 'UsersController@index')
]
然后,您必须为该文件的位置添加到容器的绑定。您可以在Kernel.py
文件中的register_routes
方法内进行操作:
def register_routes(self):
#..
self.application.bind("routes.api.location", "routes/api")
此文件中的任何路由都将被分组到一个 api 中间件堆栈中。
模型和迁移
接下来,您必须选择一个您想要负责身份验证的模型。这通常是您的用户模型。您必须将AuthenticatesTokens
类继承到此模型上:
from masoniteorm.models import Model
from masonite.api.authentication import AuthenticatesTokens
class User(Model, AuthenticatesTokens):
#..
这将允许模型将令牌保存到表中。
接下来,您将在模型表中添加一列以保存令牌。在这里,我们将其命名为api_token
,但这可以通过向模型添加__TOKEN_COLUMN__
属性来配置。您的迁移文件应如下所示:
with self.schema.table("users") as table:
table.string("api_token").nullable()
然后通过运行迁移您的迁移:
$ python craft migrate
配置
接下来,您可以创建一个新的 API 配置文件。您只需运行 install 命令即可:
python craft api:install
这将在您的配置目录中创建一个新的api.py
配置文件,如下所示:
"""API Config"""
from app.models.User import User
from masonite.environment import env
DRIVERS = {
"jwt": {
"algorithm": "HS512",
"secret": env("JWT_SECRET"),
"model": User,
"expires": None,
"authenticates": False,
"version": None,
}
}
这将尝试导入您的用户模型,但如果您有不同的模型或者如果它位于不同的位置,您可以在该模型中更改它。
此命令还将生成一个密钥,您应该将该密钥存储在名为JWT_SECRET
的环境变量中。这将用作编码和解码 JWT 令牌的盐。
authenticates
键用于检查每个请求上的数据库,以查看是否在用户上设置了令牌。默认情况下,不会调用数据库来检查令牌是否已分配给用户。 JWT 的好处之一是不需要进行数据库调用来验证用户,但如果你想要这种行为,你可以将此选项设置为True
路由
您应该在web.py
文件中添加一些路由,这些路由可用于对用户进行身份验证以向他们提供 JWT 令牌:
from masonite.api import Api
ROUTES += [
#.. web routes
]
ROUTES += Api.routes(auth_route="/api/auth", reauth_route="/api/reauth")
上述参数已经是默认值,因此如果您不想更改它们,则不必指定它们。
中间件
由于api.py
文件中的路由包装在api
中间件中,因此您应该在内核文件的路由中间件中添加一个中间件堆栈:
# Kernel.py
from masonite.api.middleware import JWTAuthenticationMiddleware
#..
class Kernel:
# ..
route_middleware = {
# ..
"api": [
JWTAuthenticationMiddleware
],
}
此中间件将允许此堆栈上设置的任何路由受到 JWT 授权的保护。
默认情况下,
routes/api.py
文件中的所有路由都已经有api
中间件堆栈,因此无需在所有 API 路由上指定堆栈。
完成这些步骤后,您现在可以创建 API
创建你的 API
设置完成后,我们就可以开始构建 API。
路由资源
构建 API 的方法之一是使用控制器和路由资源。
控制器资源是具有多个方法的控制器,用于指定应用程序中实体(如用户)中的每个操作。
要创建控制器资源,您可以运行带有-a
标志的控制器命令:
$ python craft controller api/UsersController -a
这将使用以下方法创建一个控制器:
- index
- show
- store
- update
- destroy
然后,您可以创建路由资源:
# routes/api.py
from masonite.routes import Route
ROUTES = [
# ..
Route.api('users', "api.UserController")
]
这将创建以下与您的 API 控制器方法匹配的路由:
Method | URL | Action | Route Name |
---|---|---|---|
GET | /users | index | users.show |
GET | /users/@id | show | users.show |
POST | /users | store | users.store |
PUT/PATCH | /users/@id | update | users.update |
DELETE | /users/@id | destroy | users.destroy |
验证
我们之前添加的路由包含 2 种身份验证方法。/api/auth
路由可用于获取新的身份验证令牌:
首先,使用username
和password
发送POST
请求以取回 JWT 令牌:
{
"data": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJleHBpcmVzIjpudWxsLCJ2ZXJzaW9uIjpudWxsfQ.OFBijJFsVm4IombW6Md1RUsN5v_btPwl-qtY-QSTBQ0b7N2pca8BnnT4OjfXOVRrKCWaKUM3QsGj8zqxCD4xJg"
}
然后,您应该使用token
输入或Authorization
标头发送此令牌:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJleHBpcmVzIjpudWxsLCJ2ZXJzaW9uIjpudWxsfQ.OFBijJFsVm4IombW6Md1RUsN5v_btPwl-qtY-QSTBQ0b7N2pca8BnnT4OjfXOVRrKCWaKUM3QsGj8zqxCD4xJg
重新认证
如果您没有在配置文件中为expires
键设置值,那么您的 JWT 令牌将不会过期并且将永远有效。
如果您确实在配置文件中设置了过期时间,那么 JWT 令牌将在该分钟数后过期。如果令牌过期,您将需要重新进行身份验证以获取新令牌。这可以通过发送旧令牌以取回新令牌来轻松完成:
您可以通过使用包含当前 JWT 令牌的token
输入向/api/reauth
发送 POST 请求来执行此操作。这将检查表中的令牌,如果找到,将生成一个新令牌。
版本
JWT 令牌的问题之一是几乎无法使 JWT 令牌失效。一旦 JWT 令牌有效,它通常永远有效。
使 JWT 令牌无效并强制用户重新进行身份验证的一种方法是指定版本。一个经过身份验证的 JWT 令牌将包含一个版本号(如果存在)。验证 JWT 令牌后,令牌中的版本号将与配置文件中的版本号进行核对。如果它们不匹配,则该令牌被视为无效,用户必须重新进行身份验证才能取回新令牌。
加载用户
由于我们将活动的 api_token 存储在表中,我们能够使用LoadUserMiddleware
和新的guard
路由中间件堆栈来检索用户:
首先添加保护中间件堆栈,并将LoadUserMiddleware
添加到api
堆栈。
##..
"api": [
JWTAuthenticationMiddleware,
LoadUserMiddleware
],
"guard": [
GuardMiddleware
],
最后,在您的路由或路由组中,您可以指定保护中间件并指定保护名称:
# api.py
ROUTES = [
#..
Route.get('/users', 'UserController@show').middleware(["guard:jwt"])
]
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。