Skip to content

로그인과 회원가입 구현 #114

@sewonkimm

Description

@sewonkimm

로그인, 회원가입을 구현하고 싶다!

회원가입을 먼저 해야겠지?

  • 간단하게 회원정보(아이디와 비밀번호)를 입력받아서 서버에 등록한다.
  • DB에 회원 정보를 등록하고
  • 로그인 시, 입력한 아이디와 비밀번호가 DB와 일치하면 로그인 성공!

사실은, 그렇게 간단하지가 않다.

사용자 비밀번호를 암호화 하여 저장한다

  • 왜? 보안이슈 때문이다!
    • DB가 유출될 가능성이 있는데 비밀번호가 암호화 되어있지 않으면 유저는 해당 서비스를 신뢰하고 사용할 수 없게 된다.
    • 유출되지 않더라도 DB관리자가 돈을 받고 팔아먹는다던가… 할 수도 있고, 비밀번호가 공개되어있으면 사용자의 개인정보에도 쉽게 접근할 수 있게 되는 것이 문제

암호화 해야하는 것은?

정보통신망법, 개인정보보호법 등에 의해서

  • 비밀번호
  • 바이오정보, 주민등록번호, 신용카드번호, 계좌번호, 여권번호, 운전면허번호, 외국인등록번호

등은 암호화해야한다.

개인정보 보호를 위한 암호화 때문에 회원가입 시, 이렇게 한다.

  1. 1차적으로 본인인증이 필요하다. 주민등록번호, 휴대폰 인증 등…
  2. 아이디 중복검사 - 이건 유저 구분을 위한 것
  3. 패스워드 validation - 복잡한 규칙이 있다.

암호화 방법에는 무엇이 있나?

  • ‘해싱’은 대표적인 단방향 암호화이다.
  • 단방향이라는 것은? 역으로 복호화가 불가능하다는 뜻.
  • 특정 알고리즘에 의해 원본 데이터를 맵핑시킨다. SHA-256과 같은 알고리즘이 대표적
a  SHA  암호화된 a

원본 a를 알아내기 위해서는 0부터 하나하나 대입해보면 된다. 이렇게 대입해볼 수 있는 테이블을 레인보우테이블 이라고 하고 이미 잘 만들어져있기 때문에 우리가 비밀번호를 복잡하게 만들어야하는 것이다.

이런 약점을 보환하기 위해서

  • 해시함수를 여러번 돌리기
  • 솔트(임이의 문자열) 추가
  • 비밀번호 n번 틀리면 계정 잠금

등의 방법을 사용해 볼 수 있다.

같은 비밀번호를 사용하더라도 솔트 문자열이 다르게 되면 다른 값으로 저장되고, 레인보우 테이블에서 비교하기가 힘들어진다.

그래서 이 암호화는 언제?

클라에서 서버로 보내기 전에 암호화를 해야한다. 중간에 해커가 가로채면 안되기 때문이다. 보통은 Https 프로토콜을 통해 암호화하고, 거기에 해싱까지 더해서 안전하게 전달한다.


회원가입이 끝났다. 그렇다면 로그인을 해보자!

아이디와 비밀번호를 입력해서 서버에 로그인 요청한다.

  • 이때 DB의 비밀번호는 암호화 되어있는데 이 때에도 암호화를 해주어서 서버에 보내주어야 하는가?
    결국 암호화 알고리즘은 클라이언트가 가지고 있는것 ?

로그인에 성공했다 === 인증 성공(Authentication)

로그인에 성공했다는 의미는 앞으로 이 사용자에게 특정 권한을 부여해주겠다는 의미이다.

근데 이걸 서버가 어떻게 알지? api 요청 보낼때마다 매번 아이디와 비밀번호를 입력할 수는 없지 않은가

  • 로그인에 성공하면 서버가 세션아이디를 쿠키에 담아서 응답을 해주고, 클라이언트는 그 쿠키를 다음 요청부터 같이 담아서 주면 해결!

쿠키

  • HTTP 프로토콜은 연결이 지속되지 않는 프로토콜이기 때문에 로그인 상태를 유지하려면 쿠키와 세션을 사용해야한다.
  • 받아온 토큰을 브라우저에 쿠키형태로 저장을 한다. 브라우저마다 다르게 저장되고, 호환이 불가능하다. 쿠키가 만료될 날짜를 지정해놓으면 시간이 지나면 소멸하고, 따로 만료될 날짜를 지정하지 않으면 세션쿠키라고 해서 브라우저가 닫히면 쿠키도 소멸된다.
  • 클라이언트는 이후 모든 요청에 쿠키를 헤더에 포함하여 요청한다.
  • 인증에 성공하면 서버에서 쿠키를 담아서 응답을 해주고, 클라이언트에서는 그 쿠키를 저장하고 있는 것

세션

  • 세션은 서버에서 일련의 상태를 유지하기 위해 사용하는 기술이다.
  • 사용자 구분을 위해 세션아이디를 만들어서 테이블을 가지고 있고, 쿠키에서 받아온 세션아이디와 비교해서 인가해준다. 세션아이디가 만료되거나 서버가 종료되기 전까지 유지되기 때문에 사용자가 많아질 수록 서버에 부담이 될 수이다.
  • 일정시간동안 요청이 없으면 세션을 끊기도 한다. (은행에서 시간 제한이 있는 것처럼)
  • 보안측면에서 쿠키보다 우수하다. 결국 중요한 정보는 서버에서 관리하고, 외부에 노출되지 않도록 해야한다.

근데 세션은 서버에 부하를 줄 수 있고, 서버 확장성에도 어려움이 때문에 요즘은 이런 문제를 보완한 토큰 기반의 인증을 사용한다.


토큰 기반 인증

사용자 정보를 서버에서 다루는 것이 아니라 JWT와 같은 보조 서비스를 통해 인증에 필요한 모든 정보를 관리하게 되면 쿠키-세션 방식의 단점을 보완할 수 있다.

JWT(JSON Web Token)

  • 로그인에 성공하면 서버는 클라이언트로부터 받아온 정보를 가지고 Access token을 생성하여 클라이언트에 전달한다.
  • api 요청시 쿠키를 담아서 보내줬던 것처럼 access token을 authorization header에 담아서 보내준다.
  • 공개키로 데이터를 암호화하여 전달하고, 비밀키를 가지고서만 복호화할 수 있기 때문에 비밀키는 노출되지 않도록 잘 지켜야한다. 비밀키는 서버가 가지고 있고, 클라이언트에게 받은 토큰을 복호화해서 유효한 토큰인지 확인하는 데에 사용한다.

Access token과 Refresh token

  • 보통 Access token은 유효기간이 짧다. 중간에 토큰을 탈취 당했을 때를 대비해서 짧게 만드는데 이게 상당히 번거로울 수 있다. 토큰이 만료될 때마다 다시 로그인 해줘야한다는 의미니까
  • sliding session 이라고해서 요청이 올때마다 유효기간을 연장시켜 주는 방식으로 보완하기도 하지만 무한정 만료시간을 연장할 수 있는 위험도 있고해서
  • Refresh token을 가장 많이 사용한다! 이 토큰은 유효기간이 길고, 이 토큰값을 가지고 있으면 따로 로그인 할 필요 없이 Acceess token을 발급받을 수 있다.

토큰은 또 어디에 저장하는가?

클라이언트에서 토큰값을 저장하는 방법은 크게 3가지이다. 쿠키, 세션스토리지, 로컬스토리지.

  • http only 옵션으로 브라우저에서 접근할 수 없게 설정한 쿠키에 저장하게 되면
    XSS 공격으로 부터 비교적 안전하지만 CSRF 공격에 취약
    • 액세스 토큰이 털려서 서버에 거짓 요청을 보내는 것이 CSRF 공격이고, 이를 방지하기 위해 액세스 토큰은 털리지 않도록 해야한다.
  • 로컬스토리지에 저장하면 CSRF 공격에는 안전하지만 XSS 공격에 취약
    • 로컬스토리지는 자바스크립트로 접근이 너무나도 쉽다.
  • refresh token은 http only secure 쿠키에, access token은 프로그램상의 로컬 변수에 담아놓는 것이 그나마 안전하다고 한다. [참고](https://simsimjae.tistory.com/482)
    • DB에 refresh token을 저장하고, 털려도 상관없는 index값만 클라이언트 단에서 저장해 놓으면 쿠키에 저장해 놓는 것 보다도 더 안전한 저장방법이 될 수 있다.
    • 결론은 refresh token은 가능한 접근하기 어려운 곳에 저장할 것…!

구글로 로그인하기 그런건 어떻게 구현할까?

외부 서비스의 아이디로 인증이 가능하게하는 기술이 있다. OAuth 라고, 인증과 인가를 외부 서비스에 위임하는 프로토콜이다.

OAuth로 인증하는 과정

  1. 페이스북, GCP과 같이 외부 서비스의 개발자 페이지에서 클라이언트를 등록한다.
    1. redirect url 등을 적어주고, client id와 client secret을 발급받는다.
  2. 구글 로그인 버튼 클릭 시, 구글에 로그인 요청
  3. 사용자는 구글 서비스 위에서 로그인하게 되고, 인증에 성공하면 구글에서 우리 서버에게 authorization code를 발급해준다.
  4. 응답받은 authorization code을 가지고 다시 요청해서 access token과 refresh token을 받아온다.

생각보다 간단하다..! Passport를 사용하면 더 쉽게 구현 가능

  • passport는 node의 로그인 미들웨어

요즘은 firebase도 많이 사용하던데?

  • 구글에서 인증, DB, 푸시알람 등의 기능을 손쉽게 구현할 수 있도록 만든 서비스
  • 세션처리, 보안처리, 비밀번호 찾기 및 변경 등의 기본적인 기능들이 구현되어있다.
  • 콘솔이 있어서 다루기 쉽다.
  • 간단히 프로토타이핑할 때에는 많이 사용되는 편이지만 제약이 많기 때문에 실제 서비스를 구현할 때에는 백엔드를 직접 개발하는 것이 좋다.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Wiki공부해서 알게 된 내용

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions