server1이 꽉차면 server2로 가게됨 (여기서 client는 재로그인을 해야함 )
문제 해결 위해 : 브라우저가 내용을 가지고 있게됨 => 보안취약
-> data 암호화해서 token 보내줌
위의 흐름 중 5번 중요 !
6. server는 middleware를 통해 token 쳌
* 토큰의 생성
google jwt (json web token) -> application, webside 등등 모두 사용
token = 문자로 표현되어 있음 (SJDnshdLS..)
토큰을 만들 때 이미 암호화를 거침. ( 규격이 있슴)
우리가 받아서 복구화 , 복구화의 결과 = json
오늘 수업 : 토큰 생성 ( 암호화와 함께 )
암호화된token = header, payload, verify signature 세개로 구성되어 있음
Encoded token 을 브라우저가 들고 댕기다가 server한테 줄 때마다 server가 복구화, 일치확인, 응답.
사용 이유 : server가 다수가 되었을 때 회원이 로그인 할 때마다 정보 공유가 어려움. 차라리 고객이 들고 다니게 만들었고 보안의 이유상 암호화를 시킨 것 => 메모리적으로 server에게 좋음.
Header : 토큰의 정보 , 타입,
alg = 알고리즘?
바이너리 데이터(Binary data)
우리가 쓰는 모든 text 파일
-> 글자를 16진수로 바꿈
image도 text로 이루어져있는데 -> 요 text도 binary data이다.
15 -> 16진법으로 F
15 -> 이진법으로 1111 (4비트, 4자리수)
15를 2로 나눠 신기하군
2진수 (0,1) - 컴퓨터 최애 -> 0,1만 표현하면 데이터 넘 많아지니깐 요걸 해결하기위해 16진수 사용
8진수 (0~7)
10진수 (0~9)
16진수 (0~9 + A~F)
컴퓨터가 16진수 -> 2진수 바꾸기 쉽다.
2진수는 16진수를 좋아함
16진수는 64진수를 좋아함
.toSTring('base64') => 글자가 더 줄여짐
let header 를 암호화하기
객체라서 - JSON.stringify() 를 통해
Buffer.from () - 안에 String 값이 들어감 -> header는 객체 -> Object를 String으로 바꿔주기 (by JSON.stringify()) = 저렇게 객체처럼 생긴 글자를 만든다는 것 (객체처럼 생김 근데 string)
let txt = "마포대교는 무너졌냐ㅑ";
let header = {
"alg":"HS256",
"typ":"JWT"
}
console.log(typeof header);
console.log(typeof JSON.stringify(header));
console.log(header);
console.log(JSON.stringify(header));
console.log(header.alg); //Object - 된다.
console.log(JSON.stringify(header).alg); // Stirng - 안된다.
let txt2 = Buffer.from(JSON.stringify(header)).toString('base64').replace('=','');
console.log(txt2);
컴퓨터가 읽기 쉬운 바이너리 파일로 만들고 -> 64진수로 만든 것 : header만들기 끗
-> 아직 암호화는 아님
Payload 도 똑같이
let payload = {
"sub":"123456678",
"name":"John Doe",
"iat":123325,
}
let encodepayload = Buffer.from(JSON.stringify(payload)).toString('base64').replace('=','');
console.log(encodepayload);
Buffer.from
The Buffer.from() method creates a new buffer filled with the specified string, array, or buffer.
let payload = {
"sub":"123456678",
"name":"John Doe",
"iat":123325,
}
console.log(Buffer.from(JSON.stringify(payload)));
console.log(Buffer.from(JSON.stringify(payload)).toString('base64'));
let encodepayload = Buffer.from(JSON.stringify(payload)).toString('base64').replace('=','');
console.log(encodepayload);
let a = Buffer.from('a');
let b = Buffer.from([1,2,3])
console.log(a)
console.log(b)
*buffer, 버퍼란?
하나의 장치에서 다른 장치로 데이터를 전송할 경우에 양자간의 데이터의 전송속도나 처리속도의 차를 보상하여 양호하게 결합할 목적으로 사용하는 기억영역을 버퍼 또는 버퍼 에어리어라고 한다. 보통 중앙처리장치와 단말이나 다른 입출력장치사이의 데이터 송수신에는 입출력 영역으로서 버퍼를 필요로 한다. 또, 중앙처리장치와 주기억장치의 사이에 고속으로 동작하는 소용량의 버퍼 메모리(로컬 메모리라고도 한다)를 설치하여 처리의 고속화를 꾀하는 방식도 있다.
[네이버 지식백과] 버퍼 [Buffer] (정보통신용어사전, 2008. 1. 15., 윤승은)
Verify Signature
위의 두가지 정보(Header, Payload) 를 받아서 암호화를 한 내용을 담는 공간 = 비밀 키
암호화 하는 package 다운 받기
$npm install crypto
const crypto = require('crypto')
//첫번째 인자값 : 어떤 암호화 할건지 (sha256)
//두번째 인자값 : 암호화 규칙 : string = 우리가 임의대로 만들어 놓은 key값 = 16진수로 만들어 놓기
// 두번째값 - 요 값을 가지고 sha256 암호 형태로 결과값을 주겠다.
let signature = crypto.createHmac('sha256',Buffer.from('anything'))
console.log(signature)
-
const crypto = require('crypto')
let txt = "마포대교는 무너졌냐ㅑ";
let header = {
"alg":"HS256",
"typ":"JWT"
}
let encodeheader = Buffer.from(JSON.stringify(header)).toString('base64').replace('=','');
let payload = {
"sub":"123456678",
"name":"John Doe",
"iat":123325,
}
let encodepayload = Buffer.from(JSON.stringify(payload)).toString('base64').replace('=','');
//첫번째 인자값 : 어떤 암호화 할건지 (sha256)
//두번째 인자값 : 암호화 규칙 : string = 우리가 임의대로 만들어 놓은 key값 = 16진수로 만들어 놓기
// 두번째값 - 요 값을 가지고 sha256 암호 형태로 결과값을 주겠다.
let signature = crypto.createHmac('sha256',Buffer.from('anything'))
.update(`${encodeheader}.${encodepayload}`)//header.payload의 값을 string을 . 으로 연결해서 표현
.digest('base64').replace('=','') // string 값을 64비트 형태로 바꾸기
console.log(signature)
console.log(`${encodeheader}.${encodepayload}.${signature}`);
console.log에 찍힌 token
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY2NzgiLCJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjEyMzMyNX0.NSNmmXiinXHWDz4U8sxvLsayCwMaV1IgRG7Zi3xllRY
* token 이 잘 만들어졌는지 확인하기
아까 JWT 사이트에서 확인
바이너리로 했다고 오른쪽아래 파란색 checkbox 체크 해보기
만든 token을 client에게 보내고 client가 받는거 해보기
function 에 담고 return 으로 키 반환, module.exports = createtoken; 으로 exports 하기
const crypto = require('crypto')
function createtoken() {
let header = {
"alg": "HS256",
"typ": "JWT"
}
let encodeheader = Buffer.from(JSON.stringify(header)).toString('base64').replace('=', '');
let payload = {
"sub": "1234567890",
"name": "John Doe",
"user": "ddd",
"iat": 123325,
}
let encodepayload = Buffer.from(JSON.stringify(payload)).toString('base64').replace('=', '');
let signature = crypto.createHmac('sha256', Buffer.from('anything'))
.update(`${encodeheader}.${encodepayload}`)
.digest('base64').replace('=', '')
return `${encodeheader}.${encodepayload}.${signature}`
}
let token = createtoken();
console.log(token);
module.exports = createtoken;
쿠키 사용해보면서 내용 어떻게 전달되는지 보기
$npm i express
server.js 기본 코드 작성
const express=require('express');
const app=express();
app.get('/', (req,res)=>{
res.send('hello world')
})
app.listen(3000,()=>{
console.log('server start port: 3000');
})
server에서 쿠키 생성 방법
app.get('/', (req,res)=>{
res.cookie('token','any'); //Key:value == headers:{set-cookie:'token=ingoo')
res.send('hello world') // == body:{ 내용:hello world}
})
send에는 body 에 담는다 라는 것도 있음
res.send / res.render = 응답 메세지를 완성시켜서 보내줌
cookie 는 boy? or header?
-> network 봐봐 - res headers 에 있음 (브라우저가 이 값을 받아서 저장함)
console.log창에 document.cookie 하면 브라우저가 지금 받고 저장한 값이 나옴
코드 추가
const express=require('express');
const app=express();
app.get('/', (req,res)=>{
res.cookie('token','any');
res.send('hello world <a href="/menu1"> menu1</a>')
})
app.get('/menu1',(req,res)=>{
res.send('menu1페이지입니다.');
})
app.listen(3000,()=>{
console.log('server start port: 3000');
})
text로 보내도 브라우저가 html a tag로 변환해줌
nunjucks를 사용하지않아도 page 이동이 됨
a link 누르고 요청 header 보기
server가 저 쿠키 값을 보고 식별하고 처리가능
브라우저 : storage에 있는 것을 headers에 넣고 보냄 : cookie가 유지되는 방법
페이지 바뀔 때마다 계속 쿠키값을 줌 (헤더에 있으니)
cookie-parser 다운
$npm install cookie-parser
코드 작성
const express=require('express');
const cookieParser=require('cookie-parser');
const app=express();
app.use(cookieParser());
app.get('/', (req,res)=>{
res.cookie('token','any');
res.send('hello world <a href="/menu1"> menu1</a>')
})
app.get('/menu1',(req,res)=>{
console.log(req.cookies);
res.send('menu1페이지입니다.');
})
app.listen(3000,()=>{
console.log('server start port: 3000');
})
브라우저가 토큰가지고 있으면 어떤 서버에 가더라도 토큰이 headers안에 있으니 편함
실제로 토큰 생성해서 넣기
아까 만든 KEY module.exports 한거 가져오기
const token = require('./key');
key = 파일명
전체 코드
const express=require('express');
const cookieParser=require('cookie-parser');
const token = require('./key');
const app=express();
app.use(cookieParser());
app.get('/', (req,res)=>{
let {msg} = req.query;
res.send(`${msg} hello world <a href="/menu1"> menu1</a><a href="/login?id=root&pw=root">로그인</a>`)
})
app.get('/login',(req,res)=>{
let {id,pw} = req.query;
if(id=='root' && pw=='root'){
//토큰 생성
let keytoken = token();
res.cookie('token',keytoken); //만든 토큰을 쿠키값에 넣어줌
res.redirect('/?msg=로그인성공');
}else{
//토큰 실패
res.redirect('/?msg=로그인실패');
}
})
app.get('/menu1',(req,res)=>{
console.log(req.cookies);
res.send('menu1페이지입니다.');
})
app.listen(3000,()=>{
console.log('server start port: 3000');
})
server on -> check
로그인, 메뉴 왔다갔다 할 때 쿠키값있나 확인 ! -> 모두 있음
쿠키 : 보안 취약은 ? ?
이렇게 쿠키값 가로채기 가능 ↓↓
그래서 생긴게 - 특별한 명령어들이 생김 - 쿠키를 세팅할 때 세번째 인자값 - 쿠키 설정 바꾸기 by객체
if(id=='root' && pw=='root'){
//토큰 생성
let ctoken = token();
res.cookie('token',ctoken, {httpOnly:true,secure:true,}); //만든 토큰을 쿠키값에 넣어줌
res.redirect('/?msg=로그인성공');
}else{
//토큰 실패
res.redirect('/?msg=로그인실패');
}
브라우저 저장소에 있지만 값을 가져올 수 없게 만듬
내일 : 비동기로 토큰 로그인 / 복구화 공부
비동기 하려면 req,res 문서 왔다갔다 하는거 정확하게 공부
매 실행 요청, 응답 헤더 , 바디 보면서 쿠키 보기 - 쿠키 미리 삭제 ㄱ
'블록체인 기반 핀테크 및 응용 SW개발자 양성과정 일기' 카테고리의 다른 글
[53일차] 20210528 JWT token 암호화 , 검증 예제 Node.js (6) | 2021.05.28 |
---|---|
[52일차 복습] Javascript node.js [JWT] token 토큰 암호화해서 브라우저 cookie에 저장하기 (0) | 2021.05.27 |
[51일차 복습] 카카오 API / 주소, 우편번호 요청 및 가져오기 (0) | 2021.05.26 |
[51일차]20210526 API 카카오 주소 가져오기 (0) | 2021.05.26 |
[50일차 복습] HTTP protocol 구조 개요와 예제 (1) | 2021.05.26 |