Vapor 大型教程
Basic 认证
本文给创建缩略语的接口加上 HTTP Basic 认证,只有带上正确“用户名 + 密码”的请求才能通过。
什么是 Basic 认证
HTTP Basic 认证把认证信息放在请求的 Authorization 头里。生成规则是:把“用户名:密码”拼起来后做 base64 编码,得到 token。例如用户名为 user、密码为 password 时:
base64(user:password) = dXNlcjpwYXNzd29yZAo=
那么认证头就是:
Authorization: Basic dXNlcjpwYXNzd29yZAo=
Vapor 提供了专门的 Authentication 包来处理包括 Basic 在内的各种认证,先把它加为依赖。
添加 Authentication 依赖
在 Package.swift 中加入 vapor/auth 包,并让 App 目标依赖 Authentication:
.package(url: "https://github.com/vapor/auth.git", from: "2.0.1"),
...
.target(name: "App", dependencies: ["FluentPostgreSQL", "Authentication", "Vapor", "Leaf"]),
改完依赖后重新生成 Xcode 工程:
vapor xcode -y
让 User 支持 Basic 认证
给 User 遵循 BasicAuthenticatable,告诉框架用户名和密码分别对应模型里的哪个属性:
import Authentication
...
extension User: BasicAuthenticatable {
static var usernameKey: WritableKeyPath<User, String> = \.username
static var passwordKey: WritableKeyPath<User, String> = \.password
}
用中间件保护路由
中间件(Middleware)可以拦截请求和返回。这里的基本认证中间件会拦截请求,用 Basic 方式校验发起请求的用户是否合法;guard 中间件则保证只有通过认证的用户请求才能继续往下走。在 AcronymsController 里把创建缩略语的路由用这两个中间件包起来:
import Authentication
...
struct AcronymsController: RouteCollection {
func boot(router: Router) throws {
let routeGroup = router.grouped("api", "acronyms")
let basicAuthenticationMiddleware = User.basicAuthMiddleware(using: BCryptDigest())
let guardAuthMiddleware = User.guardAuthMiddleware()
let protectd = routeGroup.grouped(basicAuthenticationMiddleware, guardAuthMiddleware)
protectd.post(Acronym.self, use: createHandler)
// routeGroup.post(Acronym.self, use: createHandler)
...
}
...
}
注意把受保护的路由挂到
protectd 上,而不是原来的 routeGroup。注释掉的那行是改造前的写法,留着方便对比。注册 AuthenticationProvider
上面的中间件要真正生效,还得在应用配置里注册认证服务提供者:
import Authentication
...
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
/// Register providers first
try services.register(FluentPostgreSQLProvider())
try services.register(AuthenticationProvider())
...
}
运行工程并用 Rested 工具测试:如果不带认证头,认证失败、无法创建缩略语;带上正确的用户名密码后,认证通过、创建成功。