创建AuthServer进行身份验证和授权
AuthServer
是一个处理创建、验证和刷新授权令牌的服务。你在你的应用程序通道中创建一个AuthServer
并注入到处理授权的类型中。这种类型包括:
Authorizer
: 中间件控制器,可防止端点控制器受到未经授权的访问AuthController
: 授予访问令牌的端点控制器AuthCodeController
: 端点控制器,授予授权码以换取访问令牌
AuthServer
必须持久保存其使用和创建的数据,例如客户端标识符和访问令牌。 存储通常由数据库执行,但是它可以位于内存,缓存或其他某种介质中。 由于存在许多不同的存储介质,因此AuthServer
本身不会执行任何存储,它依赖于特定于应用程序的AuthServerDelegate
实例。 这使得存储可以独立于验证逻辑。
创建AuthServer和AuthServerDelegate实例
AuthServerDelegate
是AuthServer
用于处理客户端标识符,令牌和其他授权工件的存储的接口。 必须使用AuthServerDelegate
的具体实现来创建AuthServer
。 Aqueduct包含了使用ORM的AuthServerDelegate
的具体实现。 强烈建议使用此实现方式,而不是自己的存储,因为它已经过全面测试并且可以正确清理过期的数据。
这个具体的实现名为ManagedAuthDelegate <T>
。 它存在于Aqueduct的一个子包中,必须显式导入。 以下是创建AuthServer
和ManagedAuthDelegate <T>
的示例:
import 'package:aqueduct/aqueduct.dart';
import 'package:aqueduct/managed_auth.dart';
class MyApplicationChannel extends ApplicationChannel {
AuthServer authServer;
@override
Future prepare() async {
final context = ManagedContext(...);
final delegate = ManagedAuthDelegate<User>(context);
authServer = AuthServer(delegate);
}
...
}
(注意,ManagedAuthDelegate
有一个类型参数,这将在下一节中介绍。)
尽管AuthServer
具有处理授权任务的方法,但很少直接使用它。 而是将AuthCodeController
和AuthController
连接到路由,以通过应用程序的HTTP API授予授权令牌。Authorizer
的实例在通道中保护路由。所有这些类型都会在AuthServer
上调用适当的方法。下面是一个设置和使用授权的ApplicationChannel
子类的例子:
import 'package:aqueduct/aqueduct.dart';
import 'package:aqueduct/managed_auth.dart';
class MyApplicationChannel extends ApplicationChannel {
AuthServer authServer;
ManagedContext context;
@override
Future prepare() async {
context = ManagedContext(...);
final delegate = ManagedAuthDelegate<User>(context);
authServer = AuthServer(delegate);
}
@override
Controller get entryPoint {
final router = Router();
// 设置认证令牌路由,这将授予和刷新令牌。
router.route("/auth/token").link(() => AuthController(authServer));
// 设置身份验证代码路由,授予可以交换令牌的临时访问码
router.route("/auth/code").link(() => AuthCodeController(authServer));
// 设置保护路由
router
.route("/protected")
.link(() => Authorizer.bearer(authServer))
.link(() => ProtectedController());
return router;
}
}
有关授权控制器(如 AuthController
)的更多细节,请参见授权控制器。有关保护路由的更多细节,请参阅授权器。
使用 ManagedAuthDelegate
ManagedAuthDelegate<T>
是AuthServerDelegate
的具体实现,为AuthServer
提供授权令牌和客户端的存储。存储是通过Aqueduct的ORM来完成的。ManagedAuthServerDelegate<T>
,默认情况下不是标准的aqueduct
库的一部分。要使用这个类,应用程序必须导入package:aqueduct/managed_auth.dart
。
ManagedAuthDelegate<T>
的类型参数代表了应用程序对 "用户 "或 "账户 "的概念,OAuth 2.0的术语将这个类型称为资源所有者。一个资源拥有者必须是一个 ManagedObject<T>
子类,它是你的应用程序所特有的。它的表定义必须扩展 ResourceOwnerTableDefinition
,并且实例类型必须实现ManagedAuthResourceOwner<T>
,其中T
是表定义。一个基本定义可能看起来像这样:
class User extends ManagedObject<_User>
implements _User, ManagedAuthResourceOwner<_User> {
}
class _User extends ResourceOwnerTableDefinition {
@Column(unique: true)
String email;
}
通过扩展表定义中的 "ResourceOwnerTableDefinition",数据库表具有以下四列:
- 整数主键,名为
id
- 唯一的字符串
username
- 密码的哈希值
- 用于生成密码哈希值的salt
ResourceOwnerTableDefinition
也有一个ManagedSet
的token
,代表每一个被授予的令牌。
接口ManagedAuthResourceOwner <T>
是确保类型参数同时是ManagedObject <T>
和ResourceOwnerTableDefinition
的要求,除了限制ManagedAuthDelegate <T>
的类型参数外,没有其他目的。
这种结构允许应用程序声明其自己的“用户”类型,同时仍然满足Aqueduct的OAuth 2.0实现的需求。
managed_auth
库还声明了两个ManagedObject <T>
子类。 ManagedAuthToken
代表授权令牌和授权码的实例,ManagedAuthClient
代表OAuth 2.0客户端的实例。 这意味着使用ManagedAuthDelegate <T>
的渡槽应用程序至少具有三个数据库表:用户,令牌和客户端。
当不再使用授权令牌和授权代码时,ManagedAuthDelegate <T>
将删除它们。 这取决于资源所有者拥有的令牌数量以及令牌的到期日期。 一旦资源所有者获取了40个以上的令牌/代码,最早的令牌/授权码(由到期日期确定)将被删除。 实际上,资源所有者被限制为40个令牌。 实例化ManagedAuthDelegate <T>
时可以更改此数字:
final delegate = ManagedAuthDelegate(context, tokenLimit: 20);
配置数据库
ManagedAuthDelegate<T>
需要用户、令牌和客户端的数据库表。在你的项目中使用数据库命令行工具来生成迁移脚本,并在数据库中执行。这个工具将查看你的用户类型、ManagedAuthToken
和 ManagedAuthClient
的声明,并创建相应的表。