JavaScript를 이용한 로그인 기능 구현 시 주의사항

2024. 3. 2. 22:50 개발 이야기/JavaScript

안녕하세요. 해커의 개발일기 입니다. 오늘은 로그인 기능을 구현할 때 중요한 사항과 주의해야하는 부분에 대해 이야기 해보겠습니다.

웹 애플리케이션에 로그인 기능을 구현하는 것은 사용자의 정보를 보호하고, 사용자에게 맞춤형 서비스를 제공하기 위한 첫걸음입니다. JavaScript를 이용하여 로그인 기능을 구현할 때는 다음과 같은 중요한 사항들을 고려해야 합니다. 

목차

  • 안전한 통신: HTTPS 사용
  • 데이터 검증과 살균(Sanitize)
  • 비밀번호 관리
  • 토큰 기반 인증
  • 크로스 사이트 요청 위조(CSRF) 보호

  • 안전한 통신: HTTPS 사용
    로그인 정보와 같은 민감한 데이터는 암호화된 연결을 통해 전송되어야 합니다. HTTP 대신 HTTPS 프로토콜을 사용하면 데이터가 암호화되어 인터넷을 통해 전송되므로, 중간자 공격(man-in-the-middle attack)으로부터 보호받을 수 있습니다.  HTTPS를 사용하는 것은 서버 설정의 일부이므로, JavaScript 코드 예시는 해당하지 않습니다. 하지만 클라이언트 측에서 HTTPS 연결을 강제하는 방법으로, 서비스 워커를 사용하여 HTTP 요청을 HTTPS로 리다이렉트할 수 있습니다.

  •  데이터 검증과 살균(Sanitize)
    사용자 입력 데이터는 항상 검증되어야 합니다. 클라이언트 측 (JavaScript)와 서버 측 모두에서 입력 값을 검증하여, SQL 인젝션, 크로스 사이트 스크립팅(XSS) 등의 공격을 방지해야 합니다. JavaScript에서는 입력 데이터를 적절히 이스케이프하고, 불필요한 태그를 제거하는 등의 방법으로 데이터를 살균할 수 있습니다.

        클라이언트 측 예시:
       사용자 입력을 HTML에서 안전하게 처리하기 위해, JavaScript에서는 textContent를 사용하여 XSS 공격을 방지할 수 있습니다.

document.getElementById('userInput').textContent = someInput;

        서버 측 예시(Node.js):
        Express.js를 사용하는 경우, express-validator 미들웨어를 사용하여 입력 데이터를 검증할 수 있습니다.

const { check, validationResult } = require('express-validator');

app.post('/login', [
  check('username').isEmail(),
  check('password').isLength({ min: 5 })
], (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  // 로그인 로직 처리...
});
  • 비밀번호 관리
    비밀번호는 절대로 평문으로 저장하거나 전송해서는 안 됩니다. 비밀번호는 서버 측에서 해시 함수를 사용하여 해시된 형태로 저장해야 하며, 로그인 시에도 사용자가 입력한 비밀번호를 해시하여 저장된 해시와 비교해야 합니다. 또한, 비밀번호 복잡성 요구사항을 설정하여 사용자가 강력한 비밀번호를 사용하도록 유도해야 합니다.

    비밀번호 해싱 예시(Node.js에서 bcrypt 사용):
const bcrypt = require('bcrypt');

// 사용자 비밀번호 해싱
bcrypt.hash('userPassword', 10, function(err, hash) {
  // 데이터베이스에 해시 저장
});

// 로그인 시 비밀번호 검증
bcrypt.compare('userPassword', 'storedHash', function(err, result) {
  if (result) {
    // 비밀번호 일치
  } else {
    // 비밀번호 불일치
  }
});

 

  • 토큰 기반 인증
    세션 기반 인증 대신 토큰 기반 인증을 사용하는 것이 현대 웹 애플리케이션 개발에서는 보다 일반적입니다. JSON Web Token(JWT)와 같은 토큰은 사용자 인증 정보를 안전하게 전송하고 저장하는 방법을 제공합니다. 토큰은 서버에서 생성되며, 클라이언트 측에서는 토큰을 저장하고 있어야 합니다(예: 쿠키, 로컬 스토리지).

    JSON Web Token (JWT) 사용 예시 (Node.js):
const jwt = require('jsonwebtoken');

// 토큰 생성
const token = jwt.sign({ userID: user.id }, 'secretKey', { expiresIn: '2h' });

// 토큰 검증
jwt.verify(token, 'secretKey', function(err, decoded) {
  if (err) {
    // 토큰 검증 실패
  } else {
    // 토큰 검증 성공
  }
});

 

  • 크로스 사이트 요청 위조(CSRF) 보호
    CSRF 공격은 사용자가 자신의 의지와 무관하게 공격자가 의도한 행위를 웹 애플리케이션에서 수행하도록 만드는 공격입니다. CSRF 토큰을 사용하거나, SameSite 쿠키 속성을 설정하는 것으로 이러한 공격으로부터 보호할 수 있습니다.

    CSRF 토큰 생성 및 검증은 서버 측에서 처리합니다. 예를 들어, Express.js에서 csurf 미들웨어를 사용할 수 있습니다.
const csurf = require('csurf');
const csrfProtection = csurf({ cookie: true });

app.post('/process', csrfProtection, (req, res) => {
  // 요청 처리
});

 

위의 사항들은 JavaScript를 이용하여 로그인 기능을 구현할 때 고려해야 할 주요 보안 측면들입니다. 보안은 절대로 타협할 수 없는 부분이므로, 개발 과정에서 이러한 사항들을 철저히 고려하여 사용자의 데이터를 안전하게 보호해야 합니다. 이러한 코드 예시들은 보안적인 측면에서 중요한 로그인 기능을 구현할 때 참고할 수 있는 기본적인 방법들을 제공합니다. 실제 개발 환경에서는 이 외에도 많은 보안 고려사항이 있으므로, 보안 전문가의 조언을 구하거나 최신 보안 가이드를 참고하는 것이 중요합니다.