인증 미들웨어 설정 및 적용
인증이 필요한 api로 접근시 토큰 정보가 있고 유효한지를 먼저 체크하는 미들웨어를 생성한다.
http 헤더에 authorization 키가 있는지 체크하고 있다면 토큰 정보가 Bearer 다음에 토큰 정보가 들어가 있으므로 Bearer 가 잇는지 체크하고 없다면 401 에러를 리턴한다.
토큰을 꺼내서 verify 함수를 사용해서 토큰이 유효한지 체크한다. 체크후에는 req에 userId와 roles 정보를 세팅하여 뒤에 나올 권한 미들웨어에 넘겨준다.
src/middleware/AuthMiddleware.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
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(); }); } } |
인증이 필요한 api에 인증 미들웨어를 적용한다.
로그인과 회원가입인 /auth에는 인증이 필요없고 /images에도 인증이 없게 설정한다. 앞에서 만든 admin 사이트에에 인증 미들웨어를 아래와 같이 설정한다.
src/router/index.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import {Router} from "express"; import image from "./image"; import auth from "./auth"; import admin from "./admin"; import {AuthMiddleware} from "../middleware/AuthMiddleware"; import board from "./board"; import comment from "./comment"; const routes = Router(); routes.use('/board', board); routes.use('/image', image); routes.use('/comment', comment); routes.use('/auth', auth); routes.use('/admin', AuthMiddleware.verifyToken, admin); export default routes; |
게시판의 경우는 쓰기, 수정, 삭제 시에 인증이 필요하므로 아래와 같이 인증 미들웨어를 설정한다.
src/router/board.ts
1 2 3 4 5 6 7 8 9 10 11 12 |
import {Router} from "express"; import {BoardController} from "../controller/BoardController"; import {AuthMiddleware} from "../middleware/AuthMiddleware"; const routes = Router(); routes.post('', AuthMiddleware.verifyToken, BoardController.addBoard); routes.get('/list', BoardController.findAllBoard); routes.get('/count', BoardController.countBoard); // routes.get(/^/(d+)$/, BoardController.findOneBoard); routes.get('/:id', BoardController.findOneBoard); routes.put('', AuthMiddleware.verifyToken, BoardController.modifyBoard); routes.delete('', AuthMiddleware.verifyToken, BoardController.removeBoard); export default routes; |
댓글의 경우도 쓰기, 수정, 삭제 시에 인증 미들웨어를 적용한다.
1 2 3 4 5 6 7 8 9 10 |
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); 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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
1 2 3 |
... routes.use('/admin', AuthMiddleware.verifyToken, AuthMiddleware.hasRole, admin); export default routes; |