哈希

未匹配的标注

AdonisJS 哈希模块允许你使用 bcryptArgon2 对值进行哈希处理,以及添加自定义哈希驱动程序的选项。

你可以在 config/hash.ts 文件中配置你选择的驱动程序。

import { hashConfig } from '@adonisjs/core/build/config'

export default hashConfig({
  default: Env.get('HASH_DRIVER', 'argon'),

  list: {
    /**
     * 确保从 npm 安装驱动程序
     * ------------------------------------
     * npm i phc-argon2
     * ------------------------------------
     */
    argon: {
      driver: 'argon2',
      variant: 'id',
      iterations: 3,
      memory: 4096,
      parallelism: 1,
      saltSize: 16,
    },

    /**
     * 确保从 npm 安装驱动程序
     * ------------------------------------
     * npm i phc-bcrypt
     * ------------------------------------
     */
    bcrypt: {
      driver: 'bcrypt',
      rounds: 10,
    },
  },
})

默认哈希器

default 属性将散列器配置为默认用于散列值。它必须是列表对象中可用的哈希器之一。


可用的哈希器

list 对象包含一个或多个可用于散列值的散列器。每个哈希器都必须使用可用的驱动程序之一。例如:

  • argon 哈希器使用argon2驱动程序。
  • bcrypt 散列器使用bcrypt驱动程序。
# 如果使用 bcrypt
npm i phc-bcrypt

# 如果使用argon2
npm i phc-argon2

哈希值

make

Hash.make方法接受一个字符串值得到一个散列。

import Hash from '@ioc:Adonis/Core/Hash'
const hashedPassword = await Hash.make(user.password)

Most of the time, you will be hashing the user's password, so it is better to use a model hook to perform the hashing.

import Hash from '@ioc:Adonis/Core/Hash'
import { column, beforeSave, BaseModel } from '@ioc:Adonis/Lucid/Orm'

export default class User extends BaseModel {
  @column({ isPrimary: true })
  public id: number

  @column({ serializeAs: null })
  public password: string

  @beforeSave()
  public static async hashPassword(user: User) {
    if (user.$dirty.password) {
      user.password = await Hash.make(user.password)
    }
  }
}

验证

您不能将哈希值转回明文字符串,你仅能验证给定的明文字符串是否匹配对应的哈希值。

if (await Hash.verify(hashedValue, plainTextValue)) {
  // 验证通过
}

NeedsReHash

查询之前生成的哈希值是否需要重新生成。如果哈希的加密系数改变,此方法将返回 true 。

在用户登录时通常是检查 needsReHash 的最好时机。

if (Hash.needsReHash(user.password)) {
  // 你必须修改模型钩子函数,
  // 不要重新哈希已经被哈希过的密码
  user.password = await Hash.make(plainPassword)
}

PHC 字符串格式

bcrypt 和 Argon2 驱动程序根据 PHC string format 返回哈希值。它允许我们验证哈希值是否与目前配置的哈希函数匹配,并确定是否需要重新哈希。

添加自定义驱动程序

哈希模块是可扩展的,允许你注册自定义的驱动程序。每个驱动程序必须实现下面的 hashdriverContract 接口。

interface HashDriverContract {
  ids?: string[]
  params?: any

  /**
   *  使用默认映射对纯文本进行哈希
   */
  make(value: string): Promise<string>

  /**
   * 检查哈希值是否需要重新哈希
   */
  needsReHash?(hashedValue: string): boolean

  /**
   * 根据散列值验证普通值是否是有效
   */
  verify(hashedValue: string, plainValue: string): Promise<boolean>
}

make

make 方法负责哈希纯字符串值。


verify

verify 方法负责根据预先存在的哈希验证纯字符串。


needsReHash

needsReHash 是可选的。但是,如果你的散列算法支持它,则必须实现它。


params/ids

paramsids 属性是你在使用 PHC 字符串格式时需要的东西。只需检查现有驱动程序的实现并阅读有关 PHC 字符串格式的信息即可了解更多信息。


由外向内延伸

任何时候你都在扩展框架的核心。最好假设你无权访问应用程序代码及其依赖项。换句话说,像编写第三方包一样编写扩展,并使用依赖注入来依赖其他依赖。

出于演示目的,让我们创建一个虚拟哈希驱动程序:

mkdir providers/HashDriver
touch providers/HashDriver/index.ts

目录结构如下所示。

providers
└── HashDriver
 └── index.ts

打开HashDriver/index.ts文件并将以下内容粘贴到其中。

// 文件名: providers/HashDriver/index.ts
import { HashDriverContract } from '@ioc:Adonis/Core/Hash'

export class PlainTextDriver implements HashDriverContract {
  public async make(value: string) {
    return value
  }

  public async verify(hashedValue: string, plainValue: string) {
    return hashedValue === plainValue
  }
}

最后,打开 providers/AppProvider.ts 文件并在 boot 方法中添加自定义驱动程序。

import { ApplicationContract } from '@ioc:Adonis/Core/Application'

export default class AppProvider {
  public static needsApplication = true

  constructor(protected app: ApplicationContract) {}

  public async boot() {
    const { PlainTextDriver } = await import('./HashDriver')
    const Hash = this.app.container.use('Adonis/Core/Hash')

    Hash.extend('plainText', () => {
      return new PlainTextDriver()
    })
  }
}

瞧!你的 PlainTextDriver 驱动程序已准备好使用。

通知 TypeScript 新驱动程序

在可以在 config/hash.ts 文件中引用此驱动程序之前,你必须告知 TypeScript 静态编译器它的存在。

如果你正在创建一个包,那么你可以在你的包主文件中编写以下代码,否则你可以将它写在 contracts/hash.ts 文件中。

import { PlainTextDriver } from '../providers/HashDriver'

declare module '@ioc:Adonis/Core/Hash' {
  interface HashDrivers {
    plainText: {
      config: {
        driver: 'plainText',
        // ...其余的配置
      }
      implementation: PlainTextDriver
    }
  }
}

更新配置

为了使用驱动程序,你必须在配置文件中定义一个映射,设置 driver=plainText

// 文件名: config/hash.ts

list: {
  myHashDriver: {
    driver: 'plainText',
  },
  // 其他哈希器
}

现在,你可以使用新定义的映射,如下所示。

await Hash.use('myHashDriver').make('foo')

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/adonisjs/5.x/se...

译文地址:https://learnku.com/docs/adonisjs/5.x/se...

上一篇 下一篇
贡献者:3
讨论数量: 0
发起讨论 只看当前版本


暂无话题~