오늘해야할일들
오늘 새롭게 알게된 내용
helmet 패키지를 사용하면 각종공격에 대비할 수 있다.
사용방법
const helmet = require('helmet')
app.use(helmet());
//helmet의 아래 기능을 모두 디폴트 값으로 사용하겠다는 의미이다.
app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());
기능에 대한 설명
CSP : Content-Sesurity-Policy 헤더를 설정해서 XSS나 교차사이트 인젝션등을 방지한다.
다른사이트의 script를 불러오는것도 막기때문에 헬멧 적용전 별도로 설정이 필요하다.
dnsprefetchControl : 도메인이 미리로딩되는 Prefetch에 대해 컨트롤 하기위해 X-DNS-Prefetch-Control 헤더를 설정한다.
expectCt : 잘못 발급된 SSL인증서를 완화한다.
frameguard : X-Fram-Options를 설정하며 클릭재킹의 공격을 방지한다.
HidePowerdBy : 응답 헤더에 있는 X-Powerd-By에 서버 소프트웨어가 표기되는데 이를 숨겨준다. 나는 Express 표기
hsts : http보다 https를 선호하도록 지시하는 Strict-Transport-Security 헤더를 설정한다. => 기본 false
ieNoOpen : IE8 이상에 대해 X-Download-Options 설정한다.
noSniff : X-Content-Type-Options를 설정하여 MIME유형 스니핑을 방지한다.
permittedCrossDomainPolicies : 일부 클라이언트간에 도메인 간 콘텐츠 로드에 대해 도메인 정책을 알려주는 헤더 X-Permitted-Cross-Domain-Policies를 설정한다
xssFilter : X-XSS-Protection헤더를 설정하여 xss공격이 있는 스크립트를 비활성화 시킨다.
referrerPolicy는 헤더에 있는 referrer과 관련이 있는 설정같다.
서버에 배포했을때 budle.js에 https로 자동으로 붙어서 렌더링이 되지않는 이슈가 발생했다.
※참고자료
https://riverblue.tistory.com/23
https://blog.uniony.me/nodejs/helmet/
winston.js 작성
로그를 관리하는 모듈을 따로 패키지 형태로 작성하려한다.
//config 폴더의winston.js 파일을 만들고 아래의 코드를 붙여넣는다.
const appRoot = require('app-root-path'); // app root 경로를 가져오는 lib
const winston = require('winston'); // winston lib
const process = require('process');
const { combine, timestamp, label, printf } = winston.format;
const myFormat = printf(({ level, message, label, timestamp }) => {
return `${timestamp} [${label}] ${level}: ${message}`; // log 출력 포맷 정의
});
const options = {
// log파일
file: {
level: 'info',
filename: `${appRoot}/logs/winston-test.log`, // 로그파일을 남길 경로
handleExceptions: true,
json: false,
maxsize: 5242880, // 5MB
maxFiles: 5,
colorize: false,
format: combine(
label({ label: 'winston-test' }),
timestamp(),
myFormat // log 출력 포맷
)
},
// 개발 시 console에 출력
console: {
level: 'debug',
handleExceptions: true,
json: false, // 로그형태를 json으로도 뽑을 수 있다.
colorize: true,
format: combine(
label({ label: 'nba_express' }),
timestamp(),
myFormat
)
}
}
let logger = new winston.createLogger({
transports: [
new winston.transports.File(options.file) // 중요! 위에서
//선언한 option으로 로그 파일 관리 모듈 transport
],
exitOnError: false,
});
if(process.env.NODE_ENV !== 'production'){
logger.add(new winston.transports.Console(options.console)) // 개발 시 console로도 출력
}
module.exports = logger;
//app.js 부분에 logger를 추가한다.
const express = require('express');
const bodyParser = require('body-parser')
const app = express();
const api = require('./routes/index');
const winston = require('./config/winston')
app.use(bodyParser.json());
app.use('/api', api);
const port = process.env.PORT || 3001;
app.listen(port, () => winston.info(`Listening on port ${port}...`));
Morgan
http요청에 대한 logging을 하는 모듈로 일종의 미들웨어로 동작한다.
로그값을 좀더 상세하게 확인하기 위해서 사용한다.
npm i morgan 설치
config 폴더에 winston.js 파일아래의 코드를 추가해준다.
//해당 코드 추가
logger.stream = {
write: function(message, encoding) {
logger.info(message); // 단순히 message를 default 포맷으로 출력
},
};
module.exports = logger
//app.js에 미들웨어 추가
app.use(bodyParser.json());
app.use(morgan('combined', {stream: winston.stream})); // morgan http 로그 미들웨어 추가
// 로그 확인방법은 두가지가있다
//tiny 는 최소한의 로그 확인이다.
//combined 는 좀 더 자세한 정보를 남길수있다.
app.use(morgan('combined'))
app실행 후 http 요청을 보내면 로그를 확인할 수 있다.