Loopback4-绑定时出现身份验证JWT服务错误

时间:2020-06-26 12:40:19

标签: typescript loopback4

loopback4出现问题,尤其是当我尝试创建自定义身份验证UserService时。

我尝试定义自己的JWTStrategyJWTService,但是有相同的错误。

我遵循文档(https://loopback.io/doc/en/lb4/JWT-authentication-extension.html#stability-%EF%B8%8Fexperimental%EF%B8%8F),但是在运行API时返回错误

Argument of type 'typeof MyUserService' is not assignable to parameter of type 'Constructor<UserService<User, Credentials>>'.
  Construct signature return types 'MyUserService' and 'UserService<User, Credentials>' are incompatible

这是我的要素

PostgreSQL数据库=>用户表

CREATE TABLE public.users (
    username CHARACTER VARYING(10) NOT NULL UNIQUE,
    password CHARACTER VARYING(255) NOT NULL,
    PRIMARY KEY (username)
);

user.model.ts

import {Entity, model, property} from '@loopback/repository';

@model({settings: {strict: false}})
export class MyUser extends Entity {
  @property({
    type: 'string',
    id: true,
    generated: false,
    required: true,
  })
  username: string;

  @property({
    type: 'string',
    required: true,
  })
  password: string;
  
  [prop: string]: any;
  constructor(data?: Partial<MyUser>) {
    super(data);
  }
}

export interface UserRelations {
  // describe navigational properties here
}

export type UserWithRelations = MyUser & UserRelations;

user.repository.ts

import {DefaultCrudRepository} from '@loopback/repository';
import {MyUser, UserRelations} from '../models';
import {DbDataSource} from '../datasources';
import {inject} from '@loopback/core';

export class MyUserRepository extends DefaultCrudRepository<
  MyUser,
  typeof MyUser.prototype.username,
  UserRelations
> {
  constructor(
    @inject('datasources.db') dataSource: DbDataSource,
  ) {
    super(MyUser, dataSource);
  }
}

user.service.ts

import {UserService} from '@loopback/authentication';
import {repository} from '@loopback/repository';
import {HttpErrors} from '@loopback/rest';
import {securityId, UserProfile} from '@loopback/security';
import {compare} from 'bcryptjs';
import {MyUser} from '../models';
import {MyUserRepository} from '../repositories';

export type Credentials = {
    username: string;
    password: string;
}

export class MyUserService implements UserService<MyUser, Credentials> {
    constructor(
        @repository(MyUserRepository) public userRepository: MyUserRepository
    ) {}

    async verifyCredentials(credentials: Credentials): Promise<MyUser> {
        const foundUser = await this.userRepository.findOne({
            where: {
                username: credentials.username
            }
        })

        if (!foundUser) throw new HttpErrors['NotFound']('Invalid creds');

        const isMatch = await compare(credentials.password, foundUser.password);
        if (!isMatch) throw new HttpErrors.Unauthorized('Password not match');

        return foundUser;
    }

    convertToUserProfile(user: MyUser): UserProfile {
        return {
            [securityId]: user.username,
            username: user.username
        }
    }
}

和我的application.ts文件

import {BootMixin} from '@loopback/boot';
import {ApplicationConfig} from '@loopback/core';
import {
  RestExplorerBindings,
  RestExplorerComponent,
} from '@loopback/rest-explorer';
import {RepositoryMixin} from '@loopback/repository';
import {RestApplication} from '@loopback/rest';
import {ServiceMixin} from '@loopback/service-proxy';
import path from 'path';
import {MySequence} from './sequence';
import {
  AuthenticationComponent,
} from '@loopback/authentication';
import {
  JWTAuthenticationComponent,
  UserServiceBindings
} from '@loopback/authentication-jwt';
import {
  DbDataSource
} from './datasources';
import {MyUserService} from './services';
import {MyUserRepository} from './repositories';

export {ApplicationConfig};

export class PsqlTodoApplication extends BootMixin(
  ServiceMixin(RepositoryMixin(RestApplication)),
) {
  constructor(options: ApplicationConfig = {}) {
    super(options);

    // Set up the custom sequence
    this.sequence(MySequence);

    // Set up default home page
    this.static('/', path.join(__dirname, '../public'));

    // Customize @loopback/rest-explorer configuration here
    this.configure(RestExplorerBindings.COMPONENT).to({
      path: '/explorer',
    });
    this.component(RestExplorerComponent);

    this.component(AuthenticationComponent);
    this.component(JWTAuthenticationComponent);
    this.dataSource(DbDataSource, UserServiceBindings.DATASOURCE_NAME);
    this.bind(UserServiceBindings.USER_SERVICE).toClass(MyUserService); // <= error is here!
    this.bind(UserServiceBindings.USER_REPOSITORY).toClass(MyUserRepository);

    this.projectRoot = __dirname;
    // Customize @loopback/boot Booter Conventions here
    this.bootOptions = {
      controllers: {
        // Customize ControllerBooter Conventions here
        dirs: ['controllers'],
        extensions: ['.controller.js'],
        nested: true,
      },
    };
  }
}

如何使用用户名/密码创建自己的凭据,而不重用@loopback/authentication-jwt中的凭据?

0 个答案:

没有答案