미들웨어 설정 + 추가 라우팅React+REST API 게시판 구현/BE - TypeORM2021. 9. 26. 00:24
Table of Contents
인증 미들웨어 설정
- 인증이 필요한 API로 접근 시 jwt 토큰 정보가 있고 유효한지를 먼저 체크하는 미들웨어를 생성하자.
- HTTP 헤더에 authorzaition 키가 있는지 체크하고 있다면 토큰 정보가 Bearer 다음에 들어가 있으므로 Bearer가 있는지 체크하고 없다면 401 에러를 리턴한다.
- 토큰을 꺼내서 verify 함수를 사용해서 토큰이 유효한지 체크하고 req에 userid와 roles 정보를 세팅하여 뒤에 나올 권한 미들웨어에 넘겨주자!
- 우선 src 폴더 아래 middleware 폴더를 만든 후 AuthMiddlewars.ts 파일을 생성하자!
src/middleware/AuthMiddleware.ts
- 아래 next() 메서드는 현재 라우터에서 판단하지 않고 다음 라우터에서 response를 처리하겠다는 의미이다!
import {verify} from 'jsonwebtoken';
export class AuthMiddleware {
static verifyToken = async (req, res, next) => {
if (!req.headers["authorization"] || !req.headers["authorization"].startsWith("Bearer ")) {
return res.status(401).send({
message: "Unauthorized!"
});
}
const token = req.headers["authorization"].substring(7);
verify(token, process.env.secret, (err, decoded) => {
console.log(err);
if (err) {
return res.status(401).send({
message: "Unauthorized!"
});
}
console.log(decoded);
req.userId = decoded.jti;
req.roles = decoded.roles;
next();
});
}
}
board와 comment에 인증 미들웨어 적용
- 인증이 필요한 api에 인증 미들웨어를 적용하자.
- 로그인과 회원가입은 /auth 라우팅에는 인증이 필요하지 않고 /images에도 인증이 필요하지 않다.
- /admin 경로에는 인증이 필요하므로 인증 src/router/index.ts 인증 미들웨어를 설정하자.
src/router/index.ts
import {Router} from "express";
// src/router/board.ts 라우팅 모듈
import board from "./board";
// src/router/comment.ts 라우팅 모듈
import comment from "./comment";
// src/router/image.ts 라우팅 모듈
import image from "./image";
// src/router/admin.ts 라우팅 모듈
import admin from "./admin";
// src/router/auth.ts 라우팅 모듈
import auth from "./auth";
// 인증 미들웨어
import {AuthMiddleware} from "../middleware/AuthMiddleware";
const routes = Router();
routes.use('/board', board);
routes.use('/comment', comment);
routes.use('/image', image);
routes.use('/admin', AuthMiddleware.verifyToken, admin);
routes.use('/auth', auth);
export default routes;
- board의 경우 추가, 수정, 삭제시에 인증이 필요하므로 아래와 같이 /board 뒤의 서브 라우팅을 처리하는 부분에 인증 미들웨어를 설정하자.
- 또한 쿼리 파라미터로 user의 id를 가지고 user가 작성한 board를 가져오는 라우팅과 URI 파라미터로 user가 작성한 board 전체 갯수를 가져오는 라우팅을 컨트롤러를 만들기 전에 미리 만들고 인증 미들웨어를 설정하자
src/router/board.ts
import {Router} from "express";
import {BoardController} from "../controller/BoardController";
// 인증 미들웨어
import {AuthMiddleware} from "../middleware/AuthMiddleware";
// multer
const multer = require('multer');
const upload = multer({storage: multer.memoryStorage()})
const routes = Router();
routes.post('', AuthMiddleware.verifyToken, upload.single('file'), BoardController.addBoard);
routes.get('/list', BoardController.findAllBoard);
routes.get('/count', BoardController.countBoard);
routes.get('/:id', BoardController.findOneBoard);
// user가 등록한 board 전체 갯수
routes.get('/user/count/:user_id', AuthMiddleware.verifyToken, BoardController.countUserBoard);
// user가 등록한 board 가져오기
routes.get('/user/list/', AuthMiddleware.verifyToken, BoardController.findAllUserBoard);
routes.put('', AuthMiddleware.verifyToken, upload.single('file'), BoardController.modifyBoard);
routes.delete('/:id', AuthMiddleware.verifyToken, BoardController.removeBoard);
export default routes;
- comment 경우 추가, 수정, 삭제시에도 /comment 뒤의 서브 라우팅을 처리하는 부분에 인증 미들웨어를 설정하자.
- 또한 페이지네이션을 구현하기 위해 board의 id를 쿼리파라미터로 받아서 해당하는 board의 id에 맞는 전체 comment 갯수를 리턴하는 라우팅을 추가하자. 뒤에서 구현할 것이므로 미리 추가하자
- 그리고 전체 board의 id에 해당하는 전체 comment를 리턴하는 /api/comment/list의 컨트롤러도 페이지네이션 방식으로 추후에 변경할 것이다
src/router/comment.ts
import {Router} from "express";
import {CommentController} from "../controller/CommentController";
// 인증 미들웨어
import {AuthMiddleware} from "../middleware/AuthMiddleware";
const routes = Router();
routes.post('', AuthMiddleware.verifyToken, CommentController.addComment);
routes.get('/list',CommentController.findAllComment);
// 추가 -> 쿼리 파라미터로 board의 id를 받아서 해당하는 id의 board의 전체 comment 갯수
routes.get('/count', CommentController.countBoardComment);
routes.get('', CommentController.findOneComment);
routes.put('', AuthMiddleware.verifyToken, CommentController.modifyComment);
routes.delete('', AuthMiddleware.verifyToken, CommentController.removeComment);
export default routes;
권한 미들웨어 설정
- 권한이 필요한 api에 인증 미들웨어를 적용하기 위해서 권한 미들웨어를 생성한다.
- 인증 미들웨어가 먼저 적용되고 인증 미들웨어에서 req에 userId와 roles가 설정되어서 들어오기 때문에 /api/admin으로 들어올 때 req.roles에 ROLE_ADMIN이 있는지 체크하고 없으면 권한 없음 에러를 리턴한다.
src/middleware/AuthMiddleware.ts
import {verify} from 'jsonwebtoken';
export class AuthMiddleware {
...
static hasRole = async (req, res, next) => {
console.log(req.userId, req.roles);
if (req.baseUrl.startsWith('/api/admin')) {
if (req.roles.indexOf('ROLE_ADMIN') < 0) {
return res.status(401).send({
message: "Admin Role is needed!"
});
}
} else if (req.url.startsWith('/api/moderator')) {
if (req.roles.indexOf('ROLE_MODERATOR') < 0) {
return res.status(401).send({
message: "Moderator Role is needed!"
});
}
}
next();
}
}
- admin API에 권한 미들웨어를 적용하자!
src/router/index.ts
import {Router} from "express";
// src/router/board.ts 라우팅 모듈
import board from "./board";
// src/router/comment.ts 라우팅 모듈
import comment from "./comment";
// src/router/image.ts 라우팅 모듈
import image from "./image";
// src/router/admin.ts 라우팅 모듈
import admin from "./admin";
// src/router/auth.ts 라우팅 모듈
import auth from "./auth";
// 인증 미들웨어
import {AuthMiddleware} from "../middleware/AuthMiddleware";
const routes = Router();
routes.use('/board', board);
routes.use('/comment', comment);
routes.use('/image', image);
routes.use('/admin', AuthMiddleware.verifyToken, AuthMiddleware.hasRole, admin);
routes.use('/auth', auth);
export default routes;
- 이제부터 위와 같이 인증 미들웨어가 포함된 라우팅을 헤더에 토큰 없이 보내면 오류가 발생한다!!
'React+REST API 게시판 구현 > BE - TypeORM' 카테고리의 다른 글
board, comment 인증 로직 적용하기 + 추가구현 (0) | 2021.09.26 |
---|---|
회원가입, 로그인 구현 (0) | 2021.09.24 |
인증과 권한 설계 (0) | 2021.09.24 |
commet CRUD API (0) | 2021.09.24 |
board에 image 추가하기 (0) | 2021.09.24 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!