09_ 인증과 인가

Lukaid·2023년 9월 20일
0

boostcamp

목록 보기
17/20

authentication and authorization

인증과 인가는 웹에서 상당히 중요한 개념이다. 인증은 사용자가 누구인지 확인하는 것이고, 인가는 사용자가 어떤 권한을 가지고 있는지 확인하는 것인데, 서비스에서 매우 중요한 역할을 하다 보니, 현업에서는 만져볼 일이 거의 없었다.

이번에 쿠키와 세션을 이용해서 인증과 인가를 구현하면서 이 개념들을 정리해 보려고 한다.



Authentication (인증)

인증은 로그인을 생각하면 된다. 인증이 필요한 서비스에 접근할 때 사용자의 신원을 파악하기 위해서 보통 로그인을 요구한다. 로그인 방식은, 비밀번호, 지문, 카드, 핸드폰 인증 등 다양한 방법으로 이뤄지지만, 본질은 사용자가 누구인지 확인하는 것이다.


Authorization (인가)

인가는 사용자나 시스템이 특정 리소스에 대한 접근 권한을 얻는(확인하는) 프로세스이다. 보통 인증 이후에 인가가 이뤄지며, 사용자의 세부적인 정보나 역할에 따라서 권한이 부여된다. 예를 들어, 사용자 A는 파일을 읽고 쓸 수 있지만, 삭제할 수 없는 권한을 가질 수 있다.






인증과 인가를 구현하기 위해서 웹에서 가장 자주 사용되는 개념이 쿠키와 세션 일 것이다.


쿠키(Cookie)

쿠키는 브라우저에서 저장하는 "작은 데이터 조각"으로 주로 서버와 브라우저 간에 상태 정보를 유지하고, 사용자 인증 정보를 저장하며 세션 추적을 위해 사용된다. 쿠키는 서버에서 브라우저로 전송되고, 브라우저에서는 지정된 유효 기간 동안 해당 쿠키를 보관한다. 쿠키는 브라우저가 종료되어도 삭제되지 않으면, 유효 기간이 만료되기 전까지는 계속해서 브라우저에 저장된다.

네이버에 로그인을 했다가 브라우저를 종료하고 일정 시간 안에 다시 켜서 네이버에 접속하면, 로그인을 다시 하지 않아도 된다. 이는 브라우저에서 쿠키를 사용해서 사용자의 로그인 정보를 저장하고 있기 때문이다.


세션(Session)

세션은 서버 측에서 관리되는 데이터이며, 클라이언트와 서버 간의 연결을 유지하고 상태 정보를 저장하는 데 사용된다. 일반적으로 사용자 인증 정보와 사용자의 권한 등의 데이터를 담당한다.

사용자가 로그인하면 서버에서 고유한 세션 ID를 생성하고 이를 쿠키에 저장한다. 클라이언트는 세션 ID를 쿠키를 통해 서버로 전달하고, 서버에서는 해당 세션 ID를 사용하여 사용자 세션을 식별하고, 세션은 주로 브라우저를 닫을 때 또는 세션 유효 시간이 만료될 때까지 지속된다. 이는 서버에서 어떻게 세션을 관리하느냐에 따라 달라진다.


세션을 이용하여 사용자의 인증과 인가를 관리하는 방법을 간단히 정리하면 다음과 같다. 사용자가 로그인하면 세션이 생성되고 해당 세션은 서버에 저장되며, 세션아이디를 비롯한 몇몇 정보는 브라우저의 쿠키에 저장되어 브라우저에서 서버로 요청을 보낼 때 마다 해당 세션을 같이 보내서 사용자를 인가하게 된다.


여기서 들었던 의문이 쿠키와 함께 또 다른 브라우저의 저장소 "세션스토리지"는 왜 등장하지 않았는가 이다.



Cookies and Session Storage

쿠키 (Cookies)

  • 작동 원리: 쿠키는 서버에서 클라이언트로 데이터 조각을 보내고, 클라이언트 브라우저에서 저장된다. 그런 다음 클라이언트가 동일한 웹 사이트를 방문하여 요청을 보낼 때마다 쿠키가 함께 전송된다.
  • 용도: 쿠키는 주로 사용자 인증 정보세션 추적과 같은 상태 정보를 저장하기 위해 사용된다. 사용자 식별, 로그인 유지, 장바구니에 상품 추가 등에 사용 될 수 있다.
  • 제한 사항: 쿠키는 일정 크기 제한이 있으며, 보안에 취약할 수 있으며, 사용자의 개인 정보를 저장할 때 주의해야 한다. 브라우저 설정에서 쿠키를 거부할 수도 있다.

세션 스토리지 (Session Storage)

  • 작동 원리: 세션 스토리지는 브라우저 세션 동안 데이터를 저장하는 데 사용된다. 세션은 사용자가 웹 애플리케이션을 닫거나 브라우저를 종료할 때까지 유지된다.
  • 용도: 세션 스토리지는 일시적인 데이터를 저장하거나, 세션 동안 일어난 사용자 작업의 상태를 유지하기 위해 사용된다. 브라우저를 닫을 때 해당 데이터가 자동으로 제거되므로 임시 정보에 적합하다.
  • 제한 사항: 세션 스토리지의 데이터는 브라우저 세션이 종료되면 손실된다. 따라서 장기적으로 데이터를 보관해야 하는 경우에는 다른 옵션을 고려해야 한다.

둘 중 어떤 옵션을 선택할지는 요구 사항과 보안 고려 사항에 따라 다르지만, 일반적으로 사용자 인증 정보와 같이 보안이 중요한 데이터는 서버 측에 저장하고, 클라이언트 측에서는 그 데이터를 참조하는 토큰이나 세션 ID 등을 사용하여 인증을 수행하는 것이 좋다. 임시 상태 정보를 저장하거나 브라우저 세션 동안 정보를 유지해야 할 때는 세션 스토리지를 활용할 수 있지만, 로그인 정보 등 인증과 인가에 대한 정보를 저장 할 때는 일반적으로 쿠키를 이용하는 것이 좋다.






express에서 구현

그럼 쿠키와 세션을 이용한 인증/인가 구현을 express에서 어떻게 할 수 있는지 알아보자. 우선 다음의 라이브러리를 사용해야한다.


import cookieParser from "cookie-parser";
import session from "express-session";
import bodyParser from "body-parser";

역할

  • cookie-parser: 브라우저에서 보내오는 쿠키를 파싱하는 미들웨어
  • express-session: 세션을 관리하는 미들웨어
  • body-parser: 요청의 본문을 해석하는 미들웨어

그리고 express의 미들웨어에 등록해준다.


const app = express();

app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(
  session({
    secret: "your-secret-key", // 세션 암호화에 사용할 키
    resave: false, // 변경되지 않은 세션도 다시 저장 (권장: false)
    saveUninitialized: true, // 초기화되지 않은 세션도 저장 (권장: true)
    cookie: {
      secure: false, // HTTPS를 사용할 때 true로 설정 (배포 환경에서)
      maxAge: 3600000, // 세션 만료 시간 (밀리초) - 예: 1시간
    },
  }),
);

이러면 미들웨어에 등록해야 하는 것은 끝이다. 이제 브라우저와 http 통신을 할 때, session 미들웨어를 거치면서 세션을 발급해준다. 이 세션은 서버에 저장되고 (서버의 메모리에 저장되는 듯), 브라우저에는 세션 ID가 쿠키로 저장된다. 사용자가 로그인시 다음과 같이 세션을 발급해주면 된다.

app.post("/login", async (req, res) => {
  const { username, password } = req.body;

  // 사용자 인증을 위해 MySQL에서 사용자 정보를 가져옵니다.
  const user = await User.findOne({ where: { username, password } });

  if (user) {
    // 사용자를 인증하고 세션에 사용자 ID 저장
    req.session.userId = user.id;
    res.json({ success: true, message: "Login successful!" });
  } else {
    res.status(401).json({ success: false, message: "Authentication failed." });
  }
});

이제 현재 사용자의 세션을 확인하는 미들웨어를 만들어보자.

function isAuthenticated(req, res, next) {
  if (req.session.userId) {
    // session에 userId가 있으면 인가된 것으로 간주
    next();
  } else {
    res.status(401).json({ success: false, message: "Not authenticated." });
  }
}

// 인증이 필요한 API 예제
app.get("/protected", isAuthenticated, (req, res) => {
  // 미들웨어로 인증 확인
  res.json({ success: true, message: "Protected resource!" });
});

이렇게 완성을 했는데, 이렇게만 구현을 한다면, 한계가 많다. 우선 서버의 메모리 위에서 세션을 관리하므로, 사용자 추적이 어렵고, 서버가 다운되면 세션 정보가 모두 날아가는 등의 문제가 있다. 이를 해결하기 위해서는 세션을 서버의 메모리가 아닌, 데이터베이스에 저장해야 한다. 이를 위해서는 express-session의 옵션을 조금 바꿔줘야 하는데, 여기까지 구현하지는 않아서 다음에 더 자세히 공부해보자.


profile
풀스택 지향 웹개발자 이성우입니다.

0개의 댓글