前话:
起步总是很艰难的,如果没有接触过Vapor 2的同学,上来就接触Vapor 3。那这边恭喜一下,起码在模型的处理上,大大的简便了,当然,我就是其中一员,我没有用过Vapor 2,我也是刚刚开始接触...
你在网络上搜索各种技术文档,你会发现打多少都是Vapor 2,虽然技术是相通的,但这对于一名长时间在移动端开发的开发者来说,还是有不小的挑战的呢。不过,这也正是你了解它的开始吧,强大的框架拿到就能了如指掌那是不可能的,除非这是你自己写的,就像我对自己的项目一样。好了,话不多说,开始上代码...
相信这个介绍能让你的Web从这里开始···
开始,你所需要做的
1. 数据库安装: brew install mysql
2. Vapor安装: brew install vapor/tap/vapor
好了,就这么简单,幸福的时刻来了,可以看代码了。
如果你还不了解Vapor生成的模版中各个结构的职能,请先移驾结构说明
有一定了解了是吧~
好的,那我们就开始个登录模块,注册模块的开发吧~
我的目录
注意,如果你的项目没有Resources目录的话:
请在项目目录下执行:
mkdir -p Resources/Views/
重新生成Xcode文件:
vapor update -y
登录简易流程
管理我们所需要的库Package.swift
import PackageDescription
let package = Package(
name: "APIService",
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
.package(url: "https://github.com/vapor/fluent-mysql.git", from: "3.0.0"),
.package(url: "https://github.com/vapor/leaf.git", from: "3.0.0-rc"),
.package(url: "https://github.com/vapor/auth.git", from: "2.0.0-rc")
],
targets: [
.target(name: "App", dependencies: ["FluentMySQL", "Vapor", "Leaf", "Authentication"]),
.target(name: "Run", dependencies: ["App"]),
.testTarget(name: "AppTests", dependencies: ["App"])
]
)
框架最细节的地方就是配置configure.swift
/// Session
middlewares.use(SessionsMiddleware.self)
config.prefer(MemoryKeyedCache.self, for: KeyedCache.self)
/// 数据库
let databaseConfig = MySQLDatabaseConfig.init(hostname: "localhost",
port: 3306,
username: "root",
password: "********",
database: "WZ_APP",
transport: .unverifiedTLS)
/// 修改数据库配置
let mysql = MySQLDatabase.init(config: databaseConfig)
databases.add(database: mysql, as: .mysql)
框架最细节的地方就是配置routes.swift
/// User
let userController = UserController()
router.get("login", use: userController.dologin)
router.post("register", use: userController.create)
/// 使用HTTP cookie保存和恢复连接客户端的会话
let authSesstionRouter = router.grouped(User.authSessionsMiddleware())
authSesstionRouter.post("authlogin", use: userController.authlogin)
/// 重定向List
let protectedRouter = authSesstionRouter.grouped(RedirectMiddleware<User>(path: "/"))
protectedRouter.get("list", use: userController.index)
let basicAuthRouter = authSesstionRouter.grouped(BasicAuthenticationMiddleware.init(authenticatable: User.self, verifier: BCrypt))
basicAuthRouter.get("/", use: userController.checkLogin)
创建用户类User.swift
final class User: MySQLModel {
var id: Int?
/// 登录账号
var account: String
/// 登录密码
var password: String
/// 用户姓名
var fullname: String?
/// 创建时间
var createdAt: Date?
init(id: Int?, account: String, password: String, fullname: String?, createdAt: Date?) {
self.id = id
self.account = account
self.password = password
self.fullname = fullname
self.createdAt = createdAt
}
}
extension User: PasswordAuthenticatable {
static var usernameKey: WritableKeyPath<User, String> {
return \User.account
}
static var passwordKey: WritableKeyPath<User, String> {
return \User.password
}
}
extension User: MySQLMigration { }
extension User: Content { }
extension User: Parameter { }
extension User: SessionAuthenticatable { }
注意:需要在configure.swift-> 增加 migrations.add(model: User.self, database: .mysql)
创建控制器UserController.swift
import Vapor
import FluentMySQL
import Crypto
final class UserController {
/// 渲染登录页面
func dologin(_ req: Request) throws -> Future<View> {
return try req.view().render("login")
}
/// 检验是否已登录
func checkLogin(_ req: Request) throws -> Future<Response> {
if try req.isAuthenticated(User.self) {
return Future.map(on: req) {
return req.redirect(to: "/list")
}
}
return Future.map(on: req) {
return req.redirect(to: "/login")
}
}
func authlogin(_ req: Request) throws -> Future<Response> {
/// 释放之前登录用户会话
try req.unauthenticateSession(User.self)
return try req.content.decode(User.self).flatMap { user in
return User.authenticate(username: user.account, password: user.password, using: BCryptDigest(), on: req).map {
user in
guard let user = user else {
return req.redirect(to: "/login")
}
try req.authenticateSession(user)
return req.redirect(to: "/list")
}
}
}
/// 用户列表
func index(_ req: Request) throws -> Future<[User]> {
let currentUser = try req.requireAuthenticated(User.self)
return User.query(on: req).filter(\.id != currentUser.id).all()
}
/// 创建
func create(_ req: Request) throws -> Future<Response> {
return try req.content.decode(User.self).flatMap { user in
/// 检查是否存在注册
return User.query(on: req).filter(\.account == user.account).first().flatMap { result in
if let _ = result {
return Future.map(on: req) {
return req.redirect(to: "/register")
}
}
user.password = try BCryptDigest().hash(user.password)
return user.save(on: req).map { _ in
return req.redirect(to: "/login")
}
}
}
}
}
创建页面login.leaf
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>丸子API-登录</title>
<!-- Bootstrap -->
<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<form class="form-horizontal" method="POST" action="/authlogin">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">登录工号/邮箱</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputEmail3" placeholder="输入工号/邮箱" name="account">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">登录密码</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3" placeholder="输入登录密码" name="password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" value="login">立即登录</button>
</div>
</div>
</form>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
主要代码就到这了,相信现在初步的开始已经没有问题了呢。一起加油吧。
特别声明:作者是新入坑小白,有错误之处还请说明,谢谢。