09/09, Auth

Ian·2020년 9월 9일
0

Today I Learned

목록 보기
22/40
post-thumbnail

Office Hour

추가로 추천하는 과제

users 와 urls 라는 테이블을 두 개 만들고, 그 관계성을 잡아보자

실제로 써야 하는 거니깐

공식 문서를 보고 밑바닥부터 먼저 만들어보자

스프린트 reference code 를 본다고 수동으로 할 수 있는 sprint 가 아니다.

이번 sprint 의 ORM 은 전부 model

ORM 의 역할은 테이블 구조로 되어있는 DB 의 데이터를 Object 의 형식으로 가져오는 것. 엄밀히 말해서 SQL ↔ JS 간의 치환이라고 하면... 반 쯤만 맞는 대답. 정확히 말하자면, 앞에 적은 설명이 맞다.

controller 는 무엇인가?

business logic , 자연스러운 언어로 코드가 작동하는 절차적인 과정을 기술한 것을 의미한다. controller 는 이 business logic 을 기술하는 역할을 담당한다. model 을 어떤 식으로 사용하는지만 기술해도 controller 는 제 역할을 한다고 볼 수 있다. 가장 잘 짠 view 는 controller 를 몰라야 한다는 점.

그렇다면, design pattern 이란?

코드를 기술하는 방법론들을 일컫는다. module 패턴, singleton 패턴, flux 패턴 등등이 있다. 엔지니어 분께서 디자인 패턴에 대해서는 head ifrst design pattern 이라는 책을 추천해주셨다. 클린코드 라는책도 여기 있는 형이 추천해주었고.

주니어에게 은근히 요구하는 것이 디자인 패턴에 대한 이해라고 한다. 한 번 읽어보자.

MDN Redirect / bit.ly 를 통한 리디렉션의 원리 이해

다른 URL 로 이동할 때 301 status code 를 넘겨준다. MDN 을 봐도 좋고, express 의 공식 홈페이지인 res.redirect 를 참조하면 된다.

다시 한 번 해 보기

migration 은 commit 과 같다

version control 이라는 공식문서의 이야기가 맞는 이야기였다. 얼마나 반영이 되었는지는 npx sequelize-cli status 라는 걸 통해 확인할 수 있다. 뒤로 되돌리기 위해서는 npx sequelize-cli migration:undo 를 통해서 작업할 수도 있다.

구현 팁들

increment 를 통한 방문횟수 카운팅

Sequelize

이 부분을 참조하였다고 한다.

findOrCreate

"만약에 있다면 찾고, 없으면 만들어라" 라는 연속된 쿼리문을 하나의 메서드로 지원하는 것.

addConstarint

테이블간의 관계 (FK, PK) 추가하기


Short.ly Express Intro

bit.ly 의 URL 을 줄여주고, 해당 링크로 페이지를 열었을 때 redirection 이 되며, count 가 늘어나는 것은 만들어져 있다. (어떻게 보면 우리가 어제 만들었던 거니깐)

이제 우리는 log-in, log-out 을 구현할 것이다(authentication). user 관리 api, client code 에서도 정상적으로 작동할 수 있게 하면서 말이다. 즉, authentication 과정을 구현한다는 것이다.

Flow of Auth. (도식화)


Hashing(hash string)

어떠한 문자열에 "임의의 연산" 을 적용하여, 다른 문자열로 변환하는 것. 나의 민감한 정보들을 그대로 노출시키지 않고 한 눈에 알아볼 수 없는 문자열을 통해 주고받을 때 사용하는 처리과정.

이 hashing 과정은 주로 서버 로직 내에서 이뤄지고, 상대적으로 정보가 노출되기 쉬운 클라이언트 상의 보안을 신경쓰기 위해 사용한다. 흔히 말하는 암호화 과정이다. 정보가 탈취되어도 그 정보를 암호화 처리를 하면, 상대방이 해독하기 어려우니깐!

일정시간동안 동일한 사용자에 대한 상태정보를 유지시키는 것. 방문자(browser)가 웹 서버에 접속하게 되면 방문자의 요구에 따른 정보를 저장하는 행위를 의미한다.

그리고 그 저장하는 행위는 저장/관리되는 위치에 따라 구분된다. 먼저, 사용자의 정보를 서버 상에서 관리하고 저장하는 것을 Session 이라고 한다. 다음으로, 사용자의 정보를 사용자 메모리(브라우저)에서 관리하는 것을 Cookie 라고 구분짓는다. 일단 지금 단계에서는 이렇게만 알아놓자!

이번 스프린트를 진행하는 과정은?

  1. intro session
  2. Shortly Express 프로젝트 코드 둘러보기
  3. Shortly Directory 확인
  4. User Flow API 생성 (Shortly)
  5. Authentication Session
  6. 암호화 및 세션 적용
  7. Advanced Challenge 진행 (JWT 등등...)

Cookie

위에서도 적었듯이, 서버가 사용자의 위치에 정보를 저장하고 불러올수 있는 수단을 의미한다. 쿠키는 두 가지 특징을 가지고 있다.

  1. 특정 호스트에서 생성된 쿠키는, 이후 모든 요청마다 서버로 다시 전송된다.
  2. 쿠키는 이름 값, 만료 날짜, 경로 정보로 구성된다.

cookie 를 확인하기 위해서는 구글 개발자 도구를 킨 뒤, 새로고침을 해서 headers 에 담겨있는 cookie 를 확인하면 된다.

  1. client → server requset, 아직은 cookie 와 관련된 아무 일도 일어나지 않는다.
  2. server → client response 에서, 서버가 set-cookie 를 한뒤, 위에 있는 구성요소들을 key:value 의 형태로 response 에 보내줌.
  3. client → server request 는 쿠키를 지우기 전까지 방금 전의 response 에서 받은 cookie 를 계속 같이 실어서 보냄.

Session

서버와 클라이언트의 연결이 활성화 된 상태를 의미한다. 서버는 접속하는 client 에 대해 "유일한" ID 를 부여하여 서버 측에서 관리한다. 그리고 그 유일한 Client ID 가 서버에서 존재하는 상황을 Session 이라고 칭한다. 각 Client ID 의 Session 객체마다 Data 를 관리할 수 있고, 사용자의 정보 중 보안상 중요한 데이터는 cookie 가 아닌 session 에서 관리한다.

이제 내가 id / pw 를 입력해서 서버로 로그인 요청을 하게 되면 서버는 그 id / pw 를 받고, 그것이 vaild 한 사용자인지 확인한다. 만약, valid 한 사용자라면

  1. session 을 생성
  2. 사용자의 브라우저에 token 과 함께 cookie 를 발급

해준다. 그렇게 하게 된다면, valid 한 사용자의 브라우저는 로그인 상태를 유지할 수 있게 된다.

Token

정의

인증을 위해 사용되는 암호화 된 문자열

특징

  1. 기본적으로 HTTP 통신의 stateless 특징과 알맞다. 연결의 상태에 연연하지 않고, token 을 통해 판단할 수 있다.
  2. 유저의 인증정보를 서버나 세션에 담아놓지 않는다. 위처럼 어떤 token 을 가지면, 어디서 접속하든 언제 접속하든 "아, 이 유저는 A 라는 유저다" 라는 식의 판단이 가능하다.
  3. 유저의 활성화 여부를 신경쓰지 않고 넘겨진 요청에 담겨진 token 의 정합성(정상적인지, 변형이 되었는지)만을 확인한다.
  4. 서버에서 클라이언트의 상태정보를 저장하지 않고, 클라이언트에서 넘겨지는 요청만으로 작업을 처리하게 되는데, 이런 경우 클라이언트 상태관리에 관한 비용이 없기 때문에 서버의 확장성이 높아진다.
    만약 token 이 없다면 유저의 모든 정보를 다 서버 / DB 에 저장해야 하겠지만, token 이 있으면 상태 정보를 저장할 필요가 없기 때문에 business logic 에만 집중하면 된다.

Session Management

  1. client → server // POST method 로 login request 를 보냄
  2. server // session token 생성
  3. server → client // set-cookie 를 통해 token: session_token 을 1에 대한 response 로 보냄
  4. client → server // GET method 로 정보를 가져오는 request 를 보냄 + cookie 에 3에서 받은 token 도 같이 실어보냄
  5. server // 4의 요청을 통해 받은 token 의 정합성을 검사함
  6. 만약 5에서 정합성이 검증되었다면, 아까의 cookie 를 담아 4에 대한 response 에 실어보냄

요점은, cookie 를 통해 발급한 token 으로 서로간의 정합성을 매 reqeust / response 마다 검사한다는 점!

조금 더 생각해 볼 점

어떻게 하면 이 인증 절차에서 보안을 더 신경쓸 수 있을까? 단순한 hashing 만을 통해서 하기엔 존재하는 취약점이 분명 존재할 것이다. 그래서 조건들을 건다면, 어떤 조건들을 추가로 거는 것이 적절할까? 만약 내가 user 에게 발급한 token 자체가 유출되었다고 해도, 더 나아가 해당 session 자체가 유출되었다고 해도 어떻게 최대한 안전하게 user 의 정보를 보호할 수 있을까?


Sprint : Mini Auth Server

HTTP 쿠키

Node.js v14.10.0 Documentation

cookie 를 통해서 로그인이 가능하게 만들어야 한다. 어떻게 해야할지 찾아보기 위해, MDN 의 HTTP 쿠키 문서를 보았다. 그리고 그 안에서 같이 보여준 node.js 상에서의 cookie 생성법도 참조하였다.

HTTP 요청을 수신할 때, 서버는 응답과 함께 Set-Cookie 헤더를 전송할 수 있습니다. 쿠키는 보통 브라우저에 의해 저장되며, 그 후 쿠키는 같은 서버에 의해 만들어진 요청(Request)들의 Cookie HTTP 헤더안에 포함되어 전송됩니다. 만료일 혹은 지속시간(duration)도 명시될 수 있고, 만료된 쿠키는 더이상 보내지지 않습니다. 추가적으로, 특정 도메인 혹은 경로 제한을 설정할 수 있으며 이는 쿠키가 보내지는 것을 제한할 수 있습니다.

서버가 이제 request 에 대한 response 를 발송할 때, Set-Cookie 라는 헤더값에 내가 원하는 key - value 를 통해 cookie 를 심어 전달할 수 있다고 한다.

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

[page content]

지금 하는 프로젝트에서는 express 를 사용하지 않기 때문에 순수한 node.js 의 문법에 맞추어 진행해야 한다. 그래서 node.js 의 response.getHeaderNames() 라는 메서드를 이용하기로 했다. node.js 공식문서에서 제공한 예시 코드는 다음과 같다.

response.setHeader('Foo', 'bar');
response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']);

const headerNames = response.getHeaderNames();
// headerNames === ['foo', 'set-cookie']

이렇게 배열형식으로 header 를 return 해준다고 하며, 유의사항이 있다면 모든 header 의 이름은 소문자로 쓰여진다고 한다(All header names are lowercase)

크롬을 기준으로 주소창 좌측 ⓘ 버튼을 누르면 내 쿠키에 접근할 수 있다. 여기서 쿠키를 삭제할 수 있다.

Session 연결

사실상 구현해 준 것에 빈칸을 채워넣는 수준이었다. 그래도 어떤 과정을 통해서 Session 과 token 이 작동하고, 어떻게 그것들의 정합성을 판단하는지를 감을 잡을 수 있었다.


Socrative

유저가 어떤 팝업 창에 대해 '7일간 다시 보지 않기'를 선택할 경우, 해당 설정은 무엇을 통해 저장하는 것이 가장 바람직할까요?

→ 잘 몰라서 구글링을 통해 찾아보았습니다. 쿠키에 해당 "7일간 다시 보지 않기" 를 클릭한 날짜를 기록하여 다시 방문했을 때와 그 기록을 비교하는 식으로 구현하는게 바람직 할 듯 합니다.

모범답안 : 어떻게 구현해도 문제없지만, 쿠키로 저장하는 것이 보통입니다.

express-session을 통해 세션 객체에 'username'이라는 데이터를 저장하려 합니다. 다음 중 올바른 방법은 무엇일까요?

express-session 의 공식문서를 통해 찾아보았는데, req.session.cookie 라는 문법을 통해 저장할 수 있다고 한다.

express-session

정답 : req.session.username 을 통해 그냥 저장하면 된다고 한다. cookie 에 저장하는 게 아니라 session 객체에 저장하는 것이기 때문에... ㅠㅠ

암호화에서 솔트(salt) 란 무엇일까요?

Salt (cryptography)

In cryptography, a salt is random data that is used as an additional input to a one-way function that hashes data, a password or passphrase.

→ 위키백과를 참조했다. 암호학에서 salt 란 어떤 input 을 넣고, 그것을 hash 하는 단방향 함수의 결과물로 나오는 불규칙한 데이터를 의미한다고 한다.

모범답안 : 암호화해야 하는 값에 어떤 별도의 값을 추가하여 결과를 변형하는 것

→ stateless 를 골랐다. 이건 내 스스로 이해를 해 봐야 할 듯 하다. "각 request-response 가 상태가 없이 독립적이기에 매 상태마다 cookie / session 을 넣어서 보내주면서 통신을 하기 때문에 stateless 속성과 가장 밀접한 연관이 있다" 라는 식으로 이해를 했는데, 이게 맞을지 모르겠다. 내일 질문해야겠다.

node.js crypto 모듈의 createHmac 메서드를 사용하여 'topSecret!'이라는 문자열을 암호화하고자 합니다. 다음 코드에서 잘못된 부분은 어디이고, 틀린 이유는 무엇일까요?

const crypto = require('crypto');

const yourSecretKey = 'thisIsMySecretKey'
const hash = crypto.createHmac('topSecret!', yourSecretKey)
        .update('topSecret!')
        .digest('base64');

Node.js v14.10.0 Documentation

createHmac 의 첫 번째 인자로 알고리즘을 받아야 하는데 'topSecret' 이라는 문자열이 들어가있어서 첫 번째 인자에 알고리즘이 들어가야 한다는 선택지를 골랐는데 틀렸다...


Nested Concepts

SQL에서varchartext 의 차이점

VARCHAR vs TEXT in MySQL

긴 문자열이 아니라면, varchar 에 접근하는 게 더 빠르다! 라는 장점이 있다.

profile
правда и красота, truth and beauty

0개의 댓글