우리들에게 노드를 배우게 하다.Nest를 사용하여 백엔드를 구축합니다.js 및 Sequelize - 4과: 로그인 및 사용자 인증

본문 최초 발표https://www.blog.duomly.com/node-js-course-building-fintech-banking-app-lesson-4-user-login-authentication/

노드 소개.js 과정 - 로그인 및 사용자 인증


몇 주 전에 우리는 노드를 가동했다.js과정, 우리는 금융 과학 기술 은행 응용 프로그램을 구축하고 있습니다.이 과정에서 우리가 사용하는 것은 새둥지다.js 프레임워크와 Typescript. 
first lesson of this Node.js Course에서 우리는 데이터베이스를 구축하기 위해 프로젝트를 시작하고 이전을 진행했다.
secondthird lesson에서 저는 사용자 등록, 데이터베이스에서 새로운 사용자를 만들고 단점에서 오는 정확한 응답을 표시하는 데 중점을 두었습니다.
이제 로그인과 인증 노드를 만들 때가 되었다. 
유사한 백엔드를 구축하고 싶다면, 같은 프로그램을 만들고 있는 우리 Golang Course 를 시도해 보세요.
현재 Angular 9 Course 에 구축된 응용 프로그램의 앞부분을 마음대로 만들어 주십시오.
댓글을 읽는 대신 동영상 강좌에서 공부하는 것을 좋아하는 사람들에 대해 영상 버전을 준비했습니다.
수업 코드가 없으면, 언제든지 저희 Github repo for lesson three 에서 받으세요.
당신이 가장 좋아하는 코드 편집기에서 코드를 열고 시작합시다!

1. 사용자 엔티티 업데이트


우선, 우리는 user.entity.ts 파일에 두 줄의 코드를 추가할 것입니다. 거기에서 사용자와 계정 간의 연결을 정의해야 합니다.사용자 실체 파일을 열고 밑에 다음 코드를 추가합니다.
@HasMany(() => Accounts, 'UserId')
public accounts: Accounts[];
또한 계정 실체를 가져왔는지 주의하십시오.없으면 파일 맨 위에서 실행합니다. 
이제 로그인 함수를 만들 수 있습니다.

2. 로그인 기능 만들기

user.service.ts 파일을 열고, 우선register 함수를 작은 변경합니다.우리는 jwt 내부의 코드를 변경할 것이다.sign () 함수입니다.
const jwtToken = jwt.sign({id: user.id, username: user.Username, email: user.Email}, process.env.JWT_KEY, jwtConfig);
준비가 다 된 후에 우리는 로그인 논리를 구축하기 시작할 수 있다.register() 함수 아래에서credentials 파라미터를 사용하여 새로운 login() 함수를 정의합니다.우선, 데이터베이스에서 인증서의 사용자 이름과 같은 사용자를 찾을 수 있습니다.
public async login(credentials: any): Promise<object> {
    const user = await Users.findOne<Users>({
      where: { Username: credentials.Username },
      attributes: { exclude: ['createdAt', 'updatedAt'] }
    });
}
사용자를 정의해야 할 때 기억해야 할 것은 사용자 이름을 지정한 사용자가 존재하지 않는 경우가 있을 수 있다는 것이다. 이것이 바로 이런 오류를 처리하는 곳이다.이것이 바로 사용자 상수 아래에 조건문을 만들 것입니다. 사용자를 정의하지 않으면 오류가 되돌아옵니다.
if (!user) {
  return {
    success: false,
    message: 'User does not exist.'
  }
}
좋습니다. 사용자의 상황은 지금 잘 알고 있습니다. 비밀번호가 어떻게 된 일인지 보여 주십시오.사용자에게 로그인하려면 로그인 폼에서 전송된 암호가 데이터베이스에 저장된 암호와 같은지 확인해야 합니다.
데이터베이스에 저장하기 전에 암호를 변경했습니다. 현재 이 두 값을 비교할 수 있도록 로그인 폼의 암호를 동일하게 조작해야 합니다.
const inputPassword = crypto.createHmac('sha256', credentials.Password + user.Salt.trim()).digest('hex');
const isPasswordCorrect = user.Password.trim() === inputPassword.trim();
두 암호를 같은 형식으로 비교했기 때문에 사용자가 로그인할 수 있는지 잘 알 수 있다.만약 비밀번호가 다르다면, 우리는 반드시 다른 조건 문장으로 처리해야 한다.
if (!isPasswordCorrect) {
  return {
    success: false,
    message: 'Password is not correct.'
  }
}
login() 함수의 시작에서 우리는 데이터베이스에서 사용자를 얻었지만 사용자의 계정을 얻을 수 없었다. 왜냐하면 우리가 가지고 있는 유일한 가치는 사용자 이름이기 때문이다.이것이 바로 우리가 반드시 따로 장부를 기록해야 하는 이유다.Accounts Service 파일에 준비된 함수가 없습니다.이것이 바로 우리가 존재하지 않는 함수 이름을 사용해야 하는 이유입니다. 잠시 후에 accounts.service.ts 파일로 이동하여 getAccountsByUserId() 방법을 만들 것입니다.계정에 코드를 만들고 응답에서 되돌려 주는 jwt 영패를 만듭니다.
const accounts = await this.accountsService.getAccountsByUserId(user.id);
const jwtToken = jwt.sign({ id: user.id, email: user.Email, username: user.Username }, process.env.JWT_KEY, jwtConfig);
그래서 여기서 해야 할 마지막 일은 응답 대상을 준비하고 되돌려 주는 것이다.
const response = {
  user: {
    id: user.id,
    username: user.Username.trim(),
    email: user.Email.trim(),
    accounts,
  },
  token: jwtToken,
  success: true,
}

return response;
좋습니다. 우리의 로그인 기능은 이미 준비가 되었습니다.사용자 계정을 얻기 위해 부족한 함수를 만들어야 한다는 것을 잊지 마세요.
또한 login() 함수의 전체 코드를 확인하여 외관이 동일한지 확인하십시오.
public async login(credentials: any): Promise<object> {
  const user = await Users.findOne<Users>({
    where: { Username: credentials.Username },
    attributes: { exclude: ['createdAt', 'updatedAt'] }
  });

  if (!user) {
    return {
      success: false,
      message: 'User does not exist.'
    }
  }

  const inputPassword = crypto.createHmac('sha256', credentials.Password + user.Salt.trim()).digest('hex');
  const isPasswordCorrect = user.Password.trim() === inputPassword.trim();

  if (!isPasswordCorrect) {
    return {
      success: false,
      message: 'Password is not correct.'
    }
  }

  const accounts = await this.accountsService.getAccountsByUserId(user.id);
  const jwtToken = jwt.sign({ id: user.id, email: user.Email, username: user.Username }, process.env.JWT_KEY, jwtConfig);
  const response = {
    user: {
      id: user.id,
      username: user.Username.trim(),
      email: user.Email.trim(),
      accounts,
    },
    token: jwtToken,
    success: true,
  }

  return response;
}

2. getAccountsByUserId 함수 만들기


이제 accounts.serivce.ts 파일로 이동하여 부족한 함수를 추가하기 위해 업데이트합니다.
public async getAccountsByUserId(UserId: number): Promise<object> {
  const accounts = await Accounts.findAll<Accounts>({
    where: { UserId },
    attributes: { exclude: ['createdAt', 'updatedAt'] }
  });

  return accounts ? accounts : [];
}
완료되면 UserService에서 더 이상 오류가 발생하지 않도록 할 수 있습니다.

3. 로그인 끝 만들기


UserController를 열고 로그인 경로를 사용하여 실제 노드를 만들 때가 되었습니다.우리는 POST 방법을 사용할 것이다.
@Post('login')
public async login(@Res() res, @Body() credentials: any): Promise<any> {
  const result: any = await this.usersService.login(credentials);
  if (!result.success) {
    throw new HttpException(result.message, HttpStatus.BAD_REQUEST);
  }
  return res.status(HttpStatus.OK).json(result);
}
소, 우리는 첫 번째 테스트를 시작할 수 있지만, 먼저 npm start 로 백엔드를 실행하는 것을 잊지 마세요.

4. 테스트 로그인


응용 프로그램이 시작되고 실행 중인 경우 API를 테스트할 수 있는 도구를 엽니다.나는 우체부로 이것을 한다.나의 노드.js 응용 프로그램이 http://localhost:3000 실행 중입니다. 기존 사용자를 테스트할 수 있습니다.
사용자가 없으면register endpoint를 사용하여 만들 수 있습니다.아래에서 너는 나의 결과를 볼 수 있다.

만약 모든 것이 정상이라면, 코드로 돌아가서 인증 함수를 만듭니다. 이 함수는 영패를 검사한 후에 사용자 데이터를 제공할 것입니다.

5. 인증 기능 만들기


이 단계에서, 우리는 사용자 서비스에 다른 함수를 만들 것입니다. 이 함수는 jwt 영패와 사용자 id를 가져옵니다. 다음은 영패가 유효한지 확인하고 이를 바탕으로 사용자 데이터를 되돌려줍니다.
우선 로그인 () 함수 아래에서 authenticate() 함수를 정의한 다음에 함수 내부에서 사용자의 계정을 가져오는 것부터 시작합니다.
public async authenticate(id: number, token: string): Promise<any> {
  const user = await Users.findOne<Users>({
    where: { id },
    include: [
      {
        model: Accounts,
        where: { UserId: id },
        required: true,
      }
    ],
  });
}
준비가 다 된 후에 우리는 jwt.verify() 함수를 사용하여 영패를 검증할 수 있습니다. 이 함수는 인코딩 영패, 사용자 id, 사용자 이름과 사용자 전자메일의 데이터를 되돌려줍니다.그리고 우리는 영패의 id와 함수에 전달되는 id를 비교할 것입니다.
const decodedToken = jwt.verify(token, process.env.JWT_KEY, jwtConfig);
const isTokenValid = decodedToken.id === Number(id);
ID가 비교적 준비되면 사용자 데이터가 전달될 수 있는지 알 수 있습니다.만약 전달할 수 없다면, 오류를 되돌려주는 조건문을 만들어야 합니다.
if (!isTokenValid) {
  return {
    success: false,
    message: 'User is not authorized.'
  }
};
완성된 후에 여기서 해야 할 마지막 일은 응답 대상을 만들고 되돌려주는 것입니다.그럼 시작합시다.
const response = {
  user: {
    id: user.id,
    email: user.Email.trim(),
    username: user.Username.trim(),
    accounts: user.accounts,
  },
  token,
  success: true,
}

return response;
마지막으로 authenticate() 함수의 전체 코드를 보고 누락된 내용이 없음을 확인합니다.
public async authenticate(id: number, token: string): Promise<any> {
    const user = await Users.findOne<Users>({
      where: { id },
      include: [
        {
          model: Accounts,
          where: { UserId: id },
          required: true,
        }
      ],
    });

    const decodedToken = jwt.verify(token, process.env.JWT_KEY, jwtConfig);
    const isTokenValid = decodedToken.id === Number(id);
    if (!isTokenValid) {
      return {
        success: false,
        message: 'User is not authorized.'
      }
    };

    const response = {
      user: {
        id: user.id,
        email: user.Email.trim(),
        username: user.Username.trim(),
        accounts: user.accounts,
      },
      token,
      success: true,
    }

    return response;
  }

6. 인증 노드 만들기


앞에서 말한 바와 같이, 우리는 단점을 만들 것이지만, 지금은 신분 검증에 사용된다.우리의 단점은 id 변수로 구성됩니다.
여기에서는 POST 방법도 사용하지만 여기에서는 @Headers()@Param() 을 사용합니다.파일 상단에서 가져오는 것을 기억하십시오.
헤더는 권한 수여 헤더를 얻는 데 매우 유용하다. 왜냐하면 이것은 영패가 어떻게 보내야 하는지이기 때문이다.
@Post(':id')
  public async authenticate(@Param() params, @Res() res, @Headers() headers): Promise<any> {
    const token = headers.authorization.replace('Bearer ', '');
    const result: any = await this.usersService.authenticate(params.id, token);
    if (!result.success) {
      throw new HttpException(result.message, HttpStatus.BAD_REQUEST);
    }
    return res.status(HttpStatus.OK).json(result);
  }
다행이네요. 테스트를 준비했나 봐요!

8. 테스트 인증


이제 응용 프로그램을 다시 실행하고 API 테스트에 사용할 도구를 엽니다.
이런 상황에서 가장 먼저 필요한 것은 영패입니다. 우리는 그것을 전달하여 우리의 단점을 테스트해야 하기 때문에 로그인 응답에서 영패를 복사했는지 확인하십시오.
권한 수여 헤더를 설정할 때, 영패 전에'적재자'를 추가하는 것을 기억하십시오.

결론


축하방금 Node를 사용하여 사용자 로그인 및 인증을 만들었습니다.js와 Nest.js 프레임워크.
코드가 누락되면 저희 Github 를 보십시오.
나는 네가 이 노드를 찾을 수 있기를 바란다.js 과정은 매우 유용하다.



읽어주셔서 감사합니다.
둘리의 안나.

좋은 웹페이지 즐겨찾기