TIL#57 인증 & 인가

Dasom·2020년 9월 7일
0

Django

목록 보기
5/32

인증(Authentication) & 인가(Authorization)

  • 인증과 인가는 API에서 가장 자주 구현되는 기능 중 하나이다
  • Private 한 API는 물론이고 Public한 API도 기본적인 인증과 인가를 요구한다

인증(Authentication)

  • 유저의 identification을 확인하는 절차이다
  • 쉽게 설명하자면 유저의 아이디와 비밀번호를 확인하는 절차이다
  • 인증을 하기 위해서는 먼저 유저의 아이디와 비밀번호를 생성할 수 있는 기능도 필요하다

로그인 절차

  1. 유저 아이디와 비밀번호 생성
  2. 유저의 비밀번호를 암호화해서 Database에 저장
  3. 유저 로그인 -> 아이디, 비밀번호 입력
  4. 유저가 입력한 비밀번호를 암호화 한 후에 DB에 암호화되어서 저장된 유저의 비밀번호와 비교
  5. 일치하면 로그인 성공
  6. 로그인이 성공하면 access token을 클라이언트에게 전송
  7. 유저는 로그인을 성공 후 다음부터는 access token을 첨부해서 request를 서버에 전송함으로서 매 요청마다 로그인해도 되지 않도록 한다

비밀번호 암호화

  • 유저의 비밀번호는 절대 비밀번호 그대로 DB에 저장하지 않는다
    • ❗️ 비밀번호를 그대로 저장하게 된다면
    • DB가 해킹을 당하면 유저의 비밀번호도 그대로 노출된다
    • 외부 해킹이 아니더라도 내부 개발자나 인력이 유저들의 비밀번호를 볼 수 있다
  • 유저의 비밀번호는 암호화하여 저장해야 한다
    • DB가 해킹을 당해도 비밀번호가 그대로 노출되지 않으며 내부 인력도 비밀번호를 알 수 없다

단방향 해시함수 & 레인보우 테이블 어택

단방향 해시함수

⭐️ 비밀번호 암호에는 단방향 해시함수(one-way hash function)가 일반적으로 쓰인다

  • 원본 메세지를 변환하여 암호화된 메세지인 다이제스트(digest) 를 생성한다. 원본 메세지를 알면 암호화된 메세지를 구하기는 쉽지만 암호화된 메세지로는 원본 메세지를 구할 수 없어서 단방향성(one-way) 라고 한다
import hashlib   # 해시 라이브러리 모듈 임포트

m = hashlib.sha256()  # sha256 아래에 설명.
m.update(b"비밀번호")  # 인코딩한 비밀번호
m.hexdigest()   # 암호화된 메세지 생성

Hash Function(해시함수)

  • 임의의 길이를 갖는 메세지를 입력받아 고정된 길이의 해시값을 출력하는 함수
  • 목적 : 메세지의 오류나 변조를 탐지할 수 있는 무결성을 제공하기 위해 사용

특징

  • 어떤 입력 값에도 항상 고정된 길이의 해시값을 출력
  • 눈사태 효과(Avalanche effect) : 입력 값의 아주 일부만 변경되어도 전혀 다른 결과값을 출력
  • 출력된 결과값을 토대로 입력값을 유추할 수 없다
  • 입력된 값이 동일하면 항상 동일한 값을 출력한다
    해시함수 참고링크

SHA256

알고리즘의 한 종류로서 256비트로 구성되며 64자리 문자열을 반환한다. 어떤 길이의 값을 입력하더라고 256비트의 고정된 결과값을 출력한다. 일반적으로 입력값이 조금만 달라져도 출력값이 완전히 달라져서 출력값을 토대로 입력값 유추는 거의 불가능하다. 아주 낮은 확률로 입력값이 다름에도 불구하고 출력값이 같은 경우가 발생하는데 이것을 충돌이라고 하며 이러한 충돌의 발생 확률이 낮을수록 좋은 함수라고 평가된다. SHA256은 출력속도가 빠르다는 장점을 갖고 있다.
SHA256 참고링크

Rainbow Table Attack

패스워드 별로 해시값들을 미리 계산해 놓은 테이블을 Rainbow table 이라고 한다. 크래킹하고자 하는 해시값을 테이블에서 검색해서 역으로 패스워드를 찾는다. 이를 이용해서 고속으로 검색해서 해킹을 할 수 있게 되어 있다. 레인보우 테이블을 이용한 공격으로 부터 방어하기 위해서는 패스워드를 가능한 한 길게, 그리고 다양한 종류의 문자를 포함하도록 사용하는 것이 좋다.

❗️ 크래킹 : 특정 목표에 피해를 주는 것을 목적으로 하고 있는 해킹. 일반적으로 사람들이 인식하고 있는 해킹은 크래킹이다.

Salting & 키스트레칭 & bcrypt

레인보우 테이블 어택을 보완하기 위해 일반적으로 2가지 방법들이 사용된다

Salting

실제 비밀번호 이외에 추가적으로 랜덤 데이터를 더해서 해시값을 계산하는 방법(랜덤한 문자열을 실제 비밀번호의 앞이나 뒤, 중간에 덧붙여서 원본의 길이가 길어지게 만드는 방법)

Key Stretching

단방향 해쉬값을 계산한 후에 그 해쉬값을 입력값으로 하여 또 해쉬하고 또 이를 반복하는 것을 말한다. 보통 사용자가 작성한 패스워드가 짧거나 예측하기 쉬운 경우가 많은데 키스트레칭은 이를 어렵게 만들어준다.

bcrypt

Salting 과 Key Stretching을 구현한 해시함수 중 가장 널리 사용된다. 애초에 패스워드 저장을 목적으로 설계되어서 매우 강력한 패스워드 다이제스트를 생성하는 해시함수이다. 관련된 라이브러리도 언어별로 쉽게 찾을 수 있다.

import bcrypt

bcrypt.hashpw(b"비밀번호", bcrypt.gensalt())
bcrypt.hashpw(b"비밀번호", bcrypt.gensalt()).hex()

JWT(JSON Web Token)

필요한 모든 정보를 자체적으로 지니고 있다. JWT 시스템에서 발급된 토큰은 토큰에 대한 기본정보, 전달할 정보(ex.로그인시스템이라면 유저의 정보), 토큰이 검증되었다는 것을 증명해주는 signature를 포함하고 있다. 자가수용적이기 때문에 두 개체 사이에서 손쉽게 전달될 수 있다. 웹서버의 경우 HTTP의 Header에 넣어서 전달할 수도 있고 URL의 파라미터로 전달할 수도 있다.

회원인증 : JWT를 가장 흔하게 사용한다. 유저가 로그인을 하면 서버는 유저의 정보에 기반한 토큰을 발급하여 유저에게 전달해준다. 그 이후에 유저가 서버에 요청을 할 때마다 JWT를 포함하여 전달한다. 서버가 클라이언트에게 요청을 받을 때마다 해당 토큰이 유효하고 인증되었는지 검증을 하고, 유저가 요청한 작업에 대하여 권한이 있는지 확인해서 작업을 처리한다. 서버측에서는 유저의 세션을 유지할 필요 없이(로그인, 로그아웃을 신경쓸 필요 없이) 유저가 요청을 했을 때 토큰만 확인하면 된다.
JWT 참고링크

인가(Authorization)

유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인지를 확인하는 절차이다.(ex. 해당 유저는 고객 정보를 볼 수는 있지만 수정할 수는 없음) JWT를 통해서 구현될 수 있다. access token 을 통해 해당 유저 정보를 얻을 수 있기 때문에 해당 유저가 가지고 있는 권한(permission)도 확인할 수 있다.

Authorization 절차

  1. Authentication 절차를 통해 access token을 생성한다. access token 에는 유저 정보를 확인할 수 있는 정보가 들어있어야 한다(ex. user id)
  2. 유저가 request를 보낼 때 access token을 첨부해서 보낸다
  3. 서버에서는 유저가 보낸 access token을 복호화한다
  4. 복호화된 데이터를 통해 user id 를 얻는다
  5. user id 를 사용해서 database에서 해당 유저의 권한(permission)을 확인한다
  6. 유저가 충분한 권한을 가지고 있으면 해당 요청을 처리한다
  7. 유저가 권한을 가지고 있지 않으면 Unauthorized Response(401) 혹은 다른 에러 코드를 보낸다

❗️ 복호화(Decryption) : 암호문을 평문으로 변환하는 과정. 암호화의 반대말.

profile
개발자꿈나무🌲

0개의 댓글