在 Vapor 4 中注册新用户时如何保护我的路线?

How can I protect my routes when signing up a new user in Vapor 4?

我想知道我是否使用了此处的最佳做法,因为我以 Content-Type: application/json 方式发送用户凭据,没有保护密码。我想知道我是否可以使用中间件保护我的路由,并让用户以最安全的方式在我的 Vapor 4 应用程序上注册。

我可以使用 Authorization: Basic 在我的 Vapor 应用程序上注册用户吗? 我这里是正常流程吗?

这是我注册用户的方式。我的 table 与 UserModel,这是处理注册流程的扩展。

extension UserModel {
  //  MARK: UserSignUp
  /// Values needed for a user to sign up.
  ///
  struct SignUp {

    let email: String
    let password: String
  }
}

extension UserModel.SignUp: Codable {}

extension UserModel.SignUp: Validatable {
  /// Setting up sign up rules for email and password to validate
  /// new user.
  ///
  static func validations(_ validations: inout Validations) {
    validations.add("email", as: String.self, is: .email)
    validations.add("password", as: String.self, is: .count(1...))
  }
}

我想保护它以安全传递用户凭据的路由。

struct UsersAuthController: RouteCollection {
  func boot(routes: RoutesBuilder) throws {

    let unprotectedRoute = routes.grouped("users")
    unprotectedRoute.post("signup", use: signUp)
  }
}

这是我在 Vapor 应用程序中注册用户的方式。这是最安全的方式吗?

extension UsersAuthController {
  func signUp(_ req: Request) throws -> EventLoopFuture<UserModel.NewSession> {

    try UserModel.SignUp.validate(content: req)
    let signUpUser = try req.content.decode(UserModel.SignUp.self)
    let user = try create(from: signUpUser)
    var token: UserTokenModel!

    return checkIfUserExists(signUpUser.email, req: req)
      .flatMapThrowing { exists -> UserModel in
        guard !exists else {
          throw Abort(.conflict)
        }
        return user }
      .flatMap { [=12=].save(on: req.db) }
      .flatMapThrowing { _ -> UserTokenModel in
        guard let newToken = try? user.createUserToken(source: .signUp) else {
          throw Abort(.internalServerError)
        }
        token = newToken
        return token }
      .flatMap { [=12=].save(on: req.db) }
      .flatMapThrowing {
        UserModel.NewSession(token: token.value,
                             user: try user.asPublic())  // Just returning a token and use id.
      }
  }

  func create(from user: UserModel.SignUp) throws -> UserModel {
    UserModel(email: user.email,
              password: try Bcrypt.hash(user.password))
  }
}

你想防止什么?在 JSON body 中发送用户名和密码或作为 HTTP 基本凭据 header 发送用户名和密码并没有真正的区别。否则事情看起来没问题,尽管我会嵌套一些期货以避免 var token: UserTokenModel!