- Bcrypt 모듈을 사용하여 사용자 비밀번호 암호화
- Express를 이용한 API 서버 만들기의 Assignment 1의 사용자 회원가입 하기 코드에 추가
- 회원가입 API
- 알맞은 API 호출 URL을 설정하여서 클라이언트와(httpie/postman) 통신을 성공해 주세요.
- 알맞은 http 메소드를 선정하여서 유저의 정보를 백엔드 서버에 전달해 주세요.
- bcrypt 모듈을 사용하여 회원가입 하는 사용자의 비밀번호 암호화를 진행해 주세요.
- 데이터가 생성됬을 때에 알맞는 http 상태코드를 반환해 주세요.
- http response로 반환하는 JSON 데이터의 형태는 다음과 같습니다.
{ "message" : "userCreated" }
bcrypt 패키지를 설치한다
npm install bcrypt
새로운 브랜치를 생성 및 교체
git branch 새_브랜치_이름
git checkout 새_브랜치_이름
bcrypt 모듈을 임포트해서 변수bcrypt에 할당한다(위쪽에 위치시킬 것!)
const bcrypt = require("bcrypt");
솔팅 횟수saltRounds
를 지정하고,
변수bcrypt의 메소드hash()
로 password
(string)와 saltRounds
(number)를 인자로 받아 hash값을 반환하는 함수makeHash()
를 선언한다
const saltRounds = 12;
const makeHash = async (password, saltRounds) => {
return await bcrypt.hash(password, saltRounds);
}
지난주에 만들었던 회원가입 엔드포인트에서;
password
와 위에서 선언한 saltRounds
를 인자로 받는 makeHash()
를 호출하고, hashedPassword
에 할당한다hashedPassword
를 받도록.app.post("/users/signup", async(req, res, next) => {
const { name, email, profileImage, password } = req.body;
const hashedPassword = await makeHash(password, saltRounds);
await appDataSource.query(
`INSERT INTO users(
name,
email,
profile_image,
password
) VALUES (?, ?, ?, ?);
`, [name, email, profileImage, hashedPassword]
);
res.status(201).json({ message : "userCreated"});
})
httpie
http -v POST 127.0.0.1:3000/users/signup name="Live Bear" email="lb34@gmail.com" profileImage="http://github.com/image_test_2.jpg" password="password"
mysql
TIL
왜인지 모르겠지만 async로 선언한 main()함수 안에 makeHash 함수를 호출하고 main()함수를 app.post(...) 안쪽에 선언했을 때는 커넥션 abort 에러?로 인해 동작이 되지 않았다. 쿼리에 hashedPassword값이 반환되지 않아서 sql syntax에러가 발생했는데.. 비동기를 겹쳐 써서?로 인해 값을 불러오지 못하는 거 같다(추측)
- Bcrypt Verification을 진행하여 로그인 정보 확인
- 로그인 정보 확인 후 JWT 토큰을 발급
- 로그인 API
- 알맞은 API 호출 URL을 설정하여서 클라이언트와(httpie/postman) 통신을 성공해주세요.
- 알맞은 http 메소드를 선정하여서 유저의 정보를 백엔드 서버에 전달해주세요.
- 비밀번호 검증이 안 되었을 때 적절한 에러를 반환해주세요.
- 토큰이 발급 되었을 때와 에러가 발생했을 때 각 각 알맞는 http 상태코드를 반환해주세요.
- http response로 반환하는 JSON 데이터의 형태는 다음과 같습니다.
// 로그인 성공, 토큰 발급 { "accessToken" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" }
// 로그인 실패 { "message" : "Invalid User" }
jsonwebtoken을 설치한다
npm install jsonwebtoken --save
.env파일에 TYPEORM_SECRETKEY = 내시크릿키
를 입력한다
환경변수 dotenv
임포트한 모듈을 변수 jwt에 할당한다
const jwt = require("jsonwebtoken");
.env파일에 환경변수를 선언했으므로 불러오기 위해서는 typeORM의 새 클래스 DataSource에도 넣어준다.
const appDataSource = new DataSource({
// (생략)
secretKey: process.env.TYPEORM_SECRETKEY
})
입력한 비밀번호와 저장된 비밀번호해시값을 비교하는 함수를 선언한다
👉 await를 쓰는 이유는 비교한 값의 계산 후 반환까지 시간이 걸려서 기다리겠다는 의미
👉 async를 쓰는 이유는 await를 쓰기 위해 비동기 함수를 별도 선언한 것
const checkHash = async (password, hashedPassword) => {
return await bcrypt.compare(password, hashedPassword)
}
GET
http Method, /login
URL, email, password
bodyemail
body가 일치하는 사용자의 'id, email, password'를 조회하고 이를 변수userInfo
에 할당한다200
, accessToken값을,401
, Invalid User라는 메시지를 보낸다app.get("/login", async(req, res, next) => {
const { email, password } = req.body;
const userInfo = await appDataSource.query(
`SELECT
users.id,
users.email,
users.password
FROM users WHERE users.email=?;`, [email]);
const hashedPassword = userInfo[0].password;
const result = await checkHash(password, hashedPassword);
const payLoad = { "user_id" : userInfo[0].id,
"exp" : 1671408000 };
const secretKey = process.env.TYPEORM_SECRETKEY;
const jwtToken = jwt.sign(payLoad, secretKey);
if ( result === true){
res.status(200).json({ "accessToken" : jwtToken });
}else{
res.status(401).json({ "message" : "Invalid User" });
}
})
로그인 성공
http -v GET 127.0.0.1:3000/login email="lb34@gmail.com" password="password"
로그인 실패
http -v GET 127.0.0.1:3000/login email="lb34@gmail.com" password="password1"
- Express를 이용한 API 서버 만들기의 Assignment 6의 게시글 등록하기 코드에 추가
- 게시글 등록 API
- 알맞은 API 호출 URL을 설정하여서 클라이언트와(httpie/postman) 통신을 성공해주세요.
- 알맞은 http 메소드를 선정하여서 게시글 내용 및 토큰을 백엔드 서버에 전달해주세요.
- 토큰 검증이 안 되었을 때 적절한 에러를 반환해 주세요.
- 데이터가 생성됬을 때와 에러가 발생했을 때 각 각 알맞는 http 상태코드를 반환해주세요.
- http response로 반환하는 JSON 데이터의 형태는 다음과 같습니다.
// 게시글 등록 성공 { "message" : "postCreated" }
// 토큰 검증 실패 { "message" : "Invalid Access Token" }
과제2에서 알게 된 accessToken:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjo5LCJleHAiOjE2NzE0MDgwMDAsImlhdCI6MTY2Nzk4NjE0MH0.y5dWrs8y2B6auoh2T1XpyxXclIUwJzts3MwfiA7lkdQ
이렇게 하는게 아닐까.. 생각했던 불완전한 소스코드:
👉 모듈화를 해서 끌어와야 한다
app.post("/posts/signup", async(req, res, next) => {
const { title, content, imageUrl, userId, jwtToken } = req.body;
const secretKey = process.env.TYPEORM_SECRETKEY;
const decoded = jwt.verify(jwtToken, secretKey);
console.log(decoded);
await appDataSource.query(
`INSERT INTO posts(
title,
content,
image_url,
user_id
) VALUES ( ?, ?, ?, ? );
`, [title, content, imageUrl, userId]
);
if(decoded.user_id === userIdDB){
res.status(201).json({ message : "postCreated"});
}else{
res.status(401).json({ message : "Invalid Access Token"})
}
})
소스코드
TIL
route와 controller를 사용해서 따로 써야 하는데 아직 방법을 모르겠다