개요
리액트 라우터는 싱글 페이지 애플리케이션 (SPA)을 구축하는 데 많이 사용되는 JavaScript 라이브러리입니다. 하지만 SPA는 서버로부터 페이지를 받아오지 않기 때문에 보안 취약점에 노출될 수 있습니다. 이번 블로그 포스트에서는 리액트 라우터의 라우팅 보안과 CSRF(Cross-Site Request Forgery) 공격에 대응하기 위한 방법을 알아보겠습니다.
라우팅 보안
프라이빗 라우트 설정
리액트 라우터를 사용할 때, 보안상 중요한 정보를 포함하는 컴포넌트는 프라이빗 라우트로 설정하는 것이 좋습니다. 이를 위해 react-router-dom
패키지의 PrivateRoute
컴포넌트를 활용할 수 있습니다. 이 컴포넌트를 사용하면 인증되지 않은 사용자가 해당 페이지에 접근하는 것을 방지할 수 있습니다.
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={(props) =>
isAuthenticated ? (
<Component {...props} />
) : (
<Redirect to="/login" />
)
}
/>
);
export default PrivateRoute;
라우트 매칭 및 보안 검증
라우터가 접근 가능한 경로만을 매칭하도록 설정하는 것이 중요합니다. 예를 들어, 관리자 계정으로 접근 가능한 경로에는 /admin
패턴을 이용하여 접근 제어를 할 수 있습니다.
<Route path="/admin" render={() => isAdmin ? <AdminDashboard /> : <NotFound />} />
CSRF 대응 방법
CSRF 토큰 사용
CSRF(Cross-Site Request Forgery) 공격은 인증된 사용자의 권한을 이용하여 악의적인 요청을 보내는 공격입니다. 이를 방지하기 위해 각 요청마다 고유한 CSRF 토큰을 생성하여 사용하는 것이 좋습니다.
서버에서 CSRF 토큰을 생성하고 클라이언트에게 전달한 후, 클라이언트는 이 토큰을 각 요청의 헤더에 포함시켜 보내야 합니다.
// 서버에서 토큰 생성 및 전달
app.use((req, res, next) => {
const csrfToken = generateCSRFToken();
res.cookie('csrfToken', csrfToken);
res.locals.csrfToken = csrfToken;
next();
});
// 클라이언트에서 토큰 사용
const fetchData = async (url, method, data) => {
const headers = {
'Content-Type': 'application/json',
'X-CSRF-Token': getCSRFTokenFromCookie(),
};
const response = await fetch(url, {
method,
headers,
body: JSON.stringify(data),
});
return response.json();
};
SameSite 쿠키 속성 설정
SameSite 쿠키 속성을 설정하여 CSRF 공격을 방지할 수 있습니다. SameSite 속성을 설정하면 해당 도메인 외부에서의 요청은 쿠키를 포함하지 않게 됩니다. 이를 통해 CSRF 공격을 방어할 수 있습니다.
// 서버에서 SameSite 속성 설정
app.use(cookieSession({
name: 'session',
secret: 'secret-key',
sameSite: 'strict',
}));
결론
리액트 라우터를 사용하여 SPA를 개발할 때에는 라우팅 보안과 CSRF 대응을 고려해야 합니다. 프라이빗 라우트를 설정하고, 라우트 매칭과 보안 검증을 적절히 설정하며, CSRF 토큰을 추가하고 SameSite 속성을 설정함으로써 애플리케이션의 보안을 향상시킬 수 있습니다.