用户名/密码认证 
模块a-authsimple提供了开箱即用的用户名/密码认证
如何使用 
1. 注册新用户 
typescript
const jwt = await this.bean.auth.authenticate('a-authsimple:simple', {
  clientOptions: {
    username: 'tom',
    password: '123456',
    email: 'xxx@xxx.com',
    avatar: ':emoji:flower',
    confirmed: true,
  },
  state: {
    intention: 'register',
  },
});confirmed: 如果为true,意味着用户已经确认,不需要后续的激活操作
- 简写方式:
 
typescript
const jwt = await this.bean.authSimple.authenticate({
  username: 'tom',
  password: '123456',
  email: 'xxx@xxx.com',
  avatar: ':emoji:flower',
  confirmed: true,
}, 'register');2. 登录 
typescript
const jwt = await this.bean.auth.authenticate('a-authsimple:simple', {
  clientOptions: {
    username: 'tom',
    password: '123456',
  },
  state: {
    intention: 'login',
  },
});- 简写方式:
 
typescript
const jwt = await this.bean.authSimple.authenticate({
  username: 'tom',
  password: '123456',
}, 'login');3. 退出登录 
typescript
await this.bean.passport.signout();4. 参数配置 
模块a-authsimple采用password-hash-salt对 Password 进行 hash 处理
可以在 App Config 中修改参数配置
src/backend/config/config/config.ts
typescript
// modules
config.modules = {
  'a-authsimple': {
    passwordHash: {
      saltlen: 64,
      iterations: 10000,
      keylen: 64,
      digest: 'sha1',
    },
  },
};源码解析 
这里对模块a-authsimple的核心源码进行解析,从而说明如何开发一个新的 Auth Provider
比如,在模块a-authsimple中创建一个 Auth Provider: simple
1. Cli命令 
bash
$ vona :create:bean authProvider simple --module=a-authsimple2. 菜单命令 
TIP
右键菜单 - [模块路径]: Vona Bean/Auth Provider
Auth Provider定义 
diff
export interface IAuthProviderSimpleClientRecord extends IAuthProviderClientRecord {}
export interface IAuthProviderSimpleClientOptions extends IAuthProviderClientOptions {
  username?: string;
  password?: string;
  email?: string;
  avatar?: string;
  locale?: keyof ILocaleInfos;
}
export interface IAuthProviderOptionsSimple extends IDecoratorAuthProviderOptions<
  keyof IAuthProviderSimpleClientRecord,
  IAuthProviderSimpleClientOptions
> {}
@AuthProvider<IAuthProviderOptionsSimple>()
class AuthProviderSimple {
  async verify(
    _args,
    clientOptions,
    _options,
    state,
  ) {
    if (state?.intention === 'register') {
      if (!clientOptions.username || !clientOptions.password) return this.app.throw(403);
      // authSimple: create
      const authSimple = await this.scope.service.authSimple.create(clientOptions.password);
      // profile
      const profile: IAuthUserProfile = {
        id: authSimple.id.toString(),
        username: clientOptions.username,
      };
      if (clientOptions.email) {
        profile.emails = [{ value: clientOptions.email }];
      }
      if (clientOptions.avatar) {
        profile.photos = [{ value: clientOptions.avatar }];
      }
      if (clientOptions.locale) {
        profile.locale = clientOptions.locale;
      }
      return profile;
    } else {
      if (!clientOptions.username || !clientOptions.password) return this.app.throw(401);
      // user
      const user = await this.bean.user.findOneByName(clientOptions.username);
      if (!user) return this.app.throw(401);
      // verify
      const profileId = await this.scope.service.authSimple.verifyPassword(user.id, clientOptions.password);
      if (!profileId) return this.app.throw(401);
      // profile
      const profile: IAuthUserProfile = {
        id: profileId.toString(),
      };
      return profile;
    }
  }
}IAuthProviderSimpleClientRecord: 定义多个 Clients,默认有default的定义IAuthProviderSimpleClientOptions: 定义 Client optionsIAuthProviderOptionsSimple: 定义 Auth Provider 的参数verify: 对register和login进行处理,返回 Profile 数据
Profile 
- Provider 的
verify只需返回 Profile 数据。系统将根据 Profile 数据生成 User 对象 register和login返回的 Profile 都必须包含相同的id字段值- 确保为不同的用户生成唯一的
id值 
Profile 具有统一的接口定义:
typescript
export interface IAuthUserProfile {
  id: string;
  username?: string;
  displayName?: string;
  name?: IAuthUserProfileName;
  gender?: string; // male/female
  profileUrl?: string;
  emails?: IAuthUserProfilePropSlice[];
  photos?: IAuthUserProfilePropSlice[];
  locale?: keyof ILocaleInfos;
  confirmed?: boolean;
}confirmed: 如果为true,意味着用户已经确认,不需要后续的激活操作