Creating Account #03

User를 만들고 passowrd를 저장하는 것까지 만들었다.

그러나 password가 그대로 노출되어 있어서 아주 위험하다.

절대 DBpassword를 저장하면 안된다. 아주 위험한거다.

어떤 회사든지 해킹 당하면 이런 식으로 DBpassword를 저장한걸 후회하게 된다.

그리고 보통 사람들은 같은 password를 여러 사이트에서 사용하기에

예를 들어 instagram,facebook,kakaotalk 같은 곳에서 password를 쓰듯이 말이다.

내일 당장 instagram이 해킹 당했다고 하면 그런데 이런식으로 password를 저장했다면

해커가 유출된 email,password로 다른 사이트에 로그인하려 할거다.

대부분의 사람들은 같은 password를 사용하기 때문이다.

그런 피해를 방지 할수 있게 되도로고 같은 password를 쓰지 않는거다.

그러면 해킹을 당했어도 다른 사이트에서 피해가 생기지 않을테니까 말이다.

만약 서비스에서 password를 관리하는 사람이라면 이런식으로 DBpassword를 저장하지 않으면 된다.

저번 파트에서 말했듯이 유저가 입력한 password가 뭔지 몰라도 password가 일치하는지

안하는지 알수 있다. 그래서 암호화 하는게 정말 중요한거다.

수학에 기반되어 있다는 것 빼고는 정말 완벽하다.

그래서 passwordhash 해볼거다.

블록체인에서 해싱은 어떤건지 password를 해싱하는 이유 등 많은 정보가 있으니

나중에 찾아 보도록 한다.

해싱은 일방향 함수인데 문자열이 필요하다. 만약에 이런 password가 있다고 한다면

14856198059174 -> dasfjboiqwenldsmpa

해싱을 하게 되면 이런 문자열로 바꿔 주는 거다.

DBpassword를 저장하지 않고 해싱된 password를 저장 하게 된다.

해싱이 일방향 함수라는 건 정말 중요한거다. 절대 되돌릴수 없다.

위 입력값으로는 위에 나온 출력 값이 나오는 거다. 그런데 출력값으로 입력 값을 알아 낼수가 없다.

입력을 하면 출력 값이 나오는데 출력값으로는 입력값을 알아 낼수 없다.

그리고 같은 입력 값으로는 항상 같은 출력값이 나온다.

해싱을 체험할 수 있는 사이트로 가본다.

https://emn178.github.io/online-tools/sha256.html

사이트 input입력란에 hello~~~~!!!라고 입력해 보았다.

그러면 밑에 출력이 해싱처리 되서 나온다.

그리고 그 출력값을 입력 칸에 복붙 해보면 다른 출력 값이 나오게 된다.

절대 입력 했던 값이 나오지 않는다. hello~~~~!!! 라고 입력해야 값은 값이 나온다.

그러니깐 같은 입력값으로는 항상 같은 해싱값이 나온다.

이런걸 컴퓨터 과학에서 deterministic function(결정적 함수) 라고 한다.

항상 똑같은 결과로 나와서 그런다.

그러면 password를 가지고 이렇게 만들어 본다.

password를 이렇게 만들면 다음에 유저가 로그인 할때 어떡해야 할지 궁금할거다.

유저들의 원래 password를 모르니까 말이다. 물론 원래 password를 모르지만

password의 해시값을 알고 있으니까 가능하다.

우선 계정을 만들때 password를 안전하게 저장하는 것부터 해보도록 한다.

mongo 콘솔에서 db.users.remove({})를 쳐서 모든 데이터를 지워 본다.

이제 모든 User를 지웠다. 그릭고 또 새로운 User를 만들건데 이번에는 password를 해싱할거다.

해싱할때 사용할건 bcrypt라는 건데 bcrypt는 정말 오래전에 만들어졌다.

1999년에 만들어 졌다. 많은 사람들이 사용하고 있다.

그리고 Blowfish cipher를 기반으로 만들었다. bcrypt는 정말 똑똑한 사람들이 만들었고,

여러 언어에서 사용할수 있다. 그 중에 하나가 javascript이다.

https://www.npmjs.com/package/bcrypt

여기 nodeJS에서 사용할 수 있는 bcrypt가 있다.

설치해 보도록 한다. npm i bcrypt 복사해서 vsc 터미널에 입력해 준다.

bcryptpassword를 해싱할거다. 해커가 해싱된 password를 가지고 할수 있는 공격이 있는데

바로 rainbow table이란거다. rainbow table도 정보를 한번 찾아 보도록 한다.

rainbow table의 공격을 bcrypt가 막아준다.

이제 password를 해싱 해볼건데

bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
    // Store hash in your password DB.
});

여기 나온대로 사용 하면 된다. myPlaintextPassword말고도 다른argument가 하나 더 있는데

saltRounds가 있다. 말 그대로 소금을 뿌리는 건데 password를 더 예측하기 어렵게 만든다.

그래서 이 함수를 그대로 사용 할거다.

bcrypt.hash() 쓰고 유저가 입력한 passwordargument로 넣을거다.

"12345" 같은 password를 말이다. 그리고 saltRounds를 5라 하면

몇번 해싱을 할건지 알려주는 거다. 이렇게 하면 출력값이 나온다.

saltRounds가 뭐냐면 한번만 해싱 하는것 보다 여러번 하는게 암호화 하기에 더 좋다.

유저가 로그인 할때 password를 입력할텐데 그 password를 5번 해싱한 다음에

password가 일치하는지 비교하는거다. 좀 복잡하게 느껴 질수도 있는데 걱정 할 필요 없다.

천천히 알아가 보도록 한다. 그러면 왜 이렇게 만들었는지 알게 된다.

이제 password를 해싱 할건데 User를 저장하기 전에 해싱을 해줄거다.

이전 파트에서 pre("save")라는걸 했다. 그걸 사용해본다.

User.js에서

import bcrypt from "bcrypt";

userSchema.pre("save", async function () {
  this.password = await bcrypt.hash(this.password, 5);
});
userSchema.pre("save", async function () {

save를 하기전에 async function을 사용 할건데 이 안에서 this.password를 가지고 해싱을 한거다.

그리고 documents를 확인하면 function에 콜백 함수를 쓸수도 있다.

mongoose가 하는 방식이랑 정말 비슷하다. 그리고 promise도 쓸수 있다.

그래서 then을 쓰거나 async,await를 쓸수 있다.

그 다음 이제 await를 먼저 쓰고 bcrypt에서 일단 bcryptimport해주고

bcrypt.hash()를 써주고 이 안에 암호화 될 data를 넣어주면 된다.

암호화 할 data는 유저가 입력한 password이다.

왜냐하면 유저가 입력한 password를 그대로 저장하면 안된다.

암호화할 datapassword에 있다. 그러니까 thin.password라고 쓰면 된다.

기억하자. context,function 안에서 thiscreate되는 User를 가리킨다.

그걸 this라고 부른다. 여기서 하는건 저장하려는 Userpassword

암호화 시킨 다음에 저장하는거다. 그리고 saltRounds를 넣어 줬다.

await를 쓰고 있어서 콜백 함수는 필요 없다. 이렇게 해서 암호화 된 password를 저장하고 있다.

앞으로는 유저가 form에 입력한 passwordUser가 저장되지 않고 form에 입력한

password를 해싱한 다음에 저장 할거다.

그리고 this.passwordconsole.log해본다.

userSchema.pre("save", async function () {
  console.log("Users password:", this.password);
  this.password = await bcrypt.hash(this.password, 5);
  console.log("Hashed password", this.password);
});

위에서는 User password를 받고 밑에서는 hassingpassword를 받는거다.

이제 계정을 다시 만들어 본다. 잘 작동 할거다.

예전에 Video를 만들때도 이렇게 했었다. Videohashtagsformat하기 위해서 말이다.

이미 한번 했었던 패턴이다. 다시 한번 복습한다. this.password는 유저가 입력 한
password를 말한다.

이번에 password를 "12345"로 해서 만들어 본다. 콘솔 두개다 값이 잘 나오고 있다.

Users password: 12345
Hashed password $2b$05$39HICIb9XG2kHMJNntufcOANiiC6rMkbTzPCmmV2YXC1PKIMb7CIG

mongodb로 가서 users를 확인해 본다. 여기에도 해싱 처리되어서 출력된다.

이제 더 이상 password를 그대로 저장하지 않고 해싱된 password를 저장한다.

이제 누군가 DB를 보게 되더라도 password가 뭔지 모르게 된다.

유저의 정보를 보호해 주는거다. 이제 어떻게 password를 암호화 하는지 알게 되었다.

절대 password를 그대로 저장하지 않는다. 항상 해싱 해준다.

userSchema.pre("save")를 써서 저장하기전에 잠깐 가로채서 작업 할수 있게 만들었다.

좋은 웹페이지 즐겨찾기