Postman
Tweets
Auth
폴더정리
// controller/auth.js
import * as authRepository from '../data/auth.js';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
/*
문제
jwt.js를 참고하여 controller/auth.js 에 토큰을 발행하고 login()에 로그인 완료되면 클라이언트에 토큰을 출력하는 프로세스를 만들어보자
*/
const secretKey = "abcd1234%^&*";
const jwtExpiresInDays = '2d';
const bcryptSaltRounds = 10;
// async function makeToken(id){
// const token = jsonwebtoken.sign({
// id: id,
// isAdmin: false
// }, secret, {expiresIn: '1h'})
// return token;
// }
function createJwtToken(id){
return jwt.sign({id}, secretKey, {expiresIn: jwtExpiresInDays});
}
/*
문제.
회원가입시 아이디 중복체크 하기
단. 중복이라면 409을 리턴
*/
// 회원가입
export async function signup(req, res, next){
const {username, password, name, email, url} = req.body;
const found = await authRepository.findByUsername(username);
if(found){
return res.status(409).json({message:`${username}이 이미 있습니다`});
}
const hashed = await bcrypt.hash(password, bcryptSaltRounds);
const userId = await authRepository.createUser({username, hashed, name, email, url});
const token = createJwtToken(userId);
res.status(201).json({token, username});
}
/*
문제
controller/auth.js 에서 login()를 bcrypt를 적용하여 로그인 프로세스를 만들어보자
*/
//로그인
export async function login(req, res, next){
const {username, password} = req.body;
// const user = await authRepository.login(username);
const user = await authRepository.findByUsername(username);
if(!user){
return res.status(401).json({message : '아이디를 찾을 수 없음'})
}
const isValidpassword = await bcrypt.compareSync(password, user.password);
if(!isValidpassword){
return res.status(401).json({message : `비밀번호가 틀렸음`});
}
const token = createJwtToken(user.id);
return res.status(200).json({token, username});
}
export async function verify(req, res, next){
const token = req.header['Token'];
if(token){
res.status(200).json(token);
}
}
// data/auth.js
let users = [
{
id: '1',
// userid: "apple",
username: "apple",
password: "$2b$10$TvIhNWYtvCNzOA0ZkmNg6.YU3EG49msPLzxphLYahMT63DVWRWZTe",
name: "김사과",
email: "apple@apple.com",
},
{
id: '2',
// userid: "banana",
username: "banana",
password: "$2b$10$TvIhNWYtvCNzOA0ZkmNg6.YU3EG49msPLzxphLYahMT63DVWRWZTe",
name: "반하나",
email: "banana@banana.com",
}
]
// 아이디(username) 중복 검사
export async function findByUsername(username){
return users.find((user) => user.username === username);
}
// id 중복 검사
export async function findById(id){
return users.find((user) => user.id === id);
}
export async function createUser(user){
const created = {id:'10', ...user }
users.push(created);
return created.id;
}
export async function login(username){
return users.find((users) => users.username === username);
}
Bearer 띄고 위 토큰 복붙
Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEiLCJpYXQiOjE3MTQ2MjE1NDcsImV4cCI6MTcxNDc5NDM0N30.UHG0DmY_2hSfSG9K8Y4DAVQZJBGSWYtYB5yZi9D8zio
// middleware/auth.js
import jwt from 'jsonwebtoken';
import * as authRepository from '../data/auth.js';
const AUTH_ERROR = {message: "인증에러"};
export const isAuth = async(req, res, next) => {
const authHeader = req.get('Authorization');
console.log(authHeader);
if(!(authHeader && authHeader.startsWith('Bearer'))) {
console.log('에러1');
return res.status(401).json(AUTH_ERROR);
}
const token = authHeader.split(' ')[1];
jwt.verify(
token, 'abcd1234%^&*',async(error, decoded) => {
if(error) {
console.log('에러2');
return res.status(401).json(AUTH_ERROR);
}
const user = await authRepository.findById(decoded.id);
if(!user){
console.log('에러3');
return res.status(401).json(AUTH_ERROR);
}
req.userId = user.id;
next();
}
);
}
// tweets.js
import express from "express";
import * as tweetController from '../controller/tweet.js';
import { body } from 'express-validator';
import { validate } from "../middleware/validator.js";
import { isAuth } from "../middleware/auth.js";
const router = express.Router();
/*
문제
Post, Put에 text에 대해 빈문자열을 없애고, 최소 3자 이상 입력해야 데이터를 저장하도록 API에 적용
*/
const validateTweet = [
body('text').trim().isLength({min: 3}).withMessage('최소 3자 이상 입력'), validate
]
// 해당 아이디에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets?username=:username
// http://localhost:8080/tweets?username=banana
router.get('/', isAuth, tweetController.getTweets);
// 글번호에 대한 트윗 가져오기
// GET
// http://localhost:8080/tweets/:id
// http://localhost:8080/tweets/1
router.get('/:id', isAuth, tweetController.getTweet);
// 트윗하기
// POST
// http://localhost:8080/tweets
// name, username, text
// json 형태로 입력 후 추가된 데이터까지 모두 json으로 출력
// {
// "id":55,
// "text":"트윗을 추가했어요555",
// "name":"김사과",
// "username":"apple"
// }
router.post('/', validateTweet, isAuth, tweetController.createTweet);
// 트윗 수정하기
// PUT
// http://localhost:8080/tweets/:id
// http://localhost:8080/tweets/1
// id, username, text
// json 형태로 입력 후 변경된 데이터까지 모두 json으로 출력
// {
// "text":"트윗을 변경했어요!"
// }
router.put('/:id', validateTweet, isAuth, tweetController.createTweet);
// 트윗 삭제하기
// DELETE
// http://localhost:8080/tweets/:id:
router.delete('/:id', isAuth, tweetController.deleteTweet);
export default router;
// router/auth.js
import express from 'express';
import { body } from 'express-validator';
import * as authController from '../controller/auth.js';
import { validate } from '../middleware/validator.js';
import { isAuth } from '../middleware/auth.js';
const router = express.Router();
const validateLogin = [
body('username').trim().notEmpty().withMessage('username을 입력하세요'),
body('password').trim().isLength({min:4}).withMessage('password는 최소 4자 이상 입력하세요'), validate
];
const validateSignup = [
... validateLogin,
body('name').trim().notEmpty().withMessage('name을 입력하세요'),
body('email').isEmail().withMessage('이메일 형식을 확인하세요'),
body('url').isURL().withMessage('URL 형식을 확인하세요'), validate
]
router.post('/signup', validateSignup, authController.signup);
router.post('/login', authController.login);
router.get('/me', isAuth, authController.me);
export default router;
'Web > Node.js' 카테고리의 다른 글
2024-05-07 관리자페이지팁, (0) | 2024.05.07 |
---|---|
2024-05-03 환경 변수 관리, HTTP 통신, 웹소켓 (0) | 2024.05.03 |
API 명세서 (0) | 2024.04.30 |
2024-04-30 (0) | 2024.04.30 |
2024-04-29 리팩토링 (0) | 2024.04.29 |