일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 스타벅스다이어트
- R
- 파리바게트샐러드
- qh
- 엘리후기 #내돈내산 #솔직후기
- 스타벅스런치
- 스타벅스
- 스벅커피
- 스타벅스커피
- 부산빵집
- 스타벅스후기
- 저칼로리샌드의치
- 샌드위치후기
- 빠바샐러드
- 스타벅스점심
- 솔직리뷰
- 스타벅스신메뉴
- 파리바게트다이어트
- 스타벅스저칼로리
- 스타벅스리뷰
- 스타벅스칼로리
- 스타벅스샌드위치
- 샐러드후기
- 두유라떼
- 스타벅스가격
- 스벅
- 파리바게트
- 스벅라떼
- 저칼로리스타벅스
- 내돈내산
- Today
- Total
엘리
#TIL 항해 19일차 주특기 심화 과정 본문
2주차 강의
미들웨어, 쿠키 세션 이론 알기
1. 로그인 회원 가입 기능을 추가! (JWT)
JWT는 문자열 로그인 기능으로 쓸수 있는지 배울 예정!
2. JWT 기술을 이용해서 로그인을 구현 할수 있음
-변조가 불가능 하다/서버에서 원하는 데이터를 암호화를 해서 줌 -> 서버가 아니면, 변조가 불가능 하다!
-복호화는 어디서나 가능하다 (그 안에 있는 데이터는 모두가 열람이 가능하다) 유념하고, 개발을 할것!
(디코딩은 부호화된 데이터를 부호화 되기전 형태로 바꾸어 사람이 읽을수 있는 형태로 되돌려 놓은것)
-JWT안에는 중요하지 않는 정보(유저 아이디, 생년월일, 사용자를 구분할수 있는 정도)
3. JWT는 어떻게 사용하면 되나요?
사용량이 가장 많은 라이브러리를 사용!
/제이슨웹토큰/이라는 라이브러리를 사용할 것임!
새로운 폴더를 만듦 -> 터미널을 열고 - npm i jsonwebtoken -S 로라이브러리 설치 -> 새 파일 만들자(app.js) -> 제이슨 토큰 라이브러리 불러오기! -> const token= jwt.sign({tes:true}) 토큰 발행
사인을 하면 토큰이 만들어짐 -> 시크릿 키를 입력해줘야 함!(마음대로 지정할수 있음 but 복잡한걸 추천!) -> 암호화가 맞는지, 확인 하는 방법 ->jwt.io ->encoded 다 삭제 하고 복사한걸 붙여 놓어 보기! -> payload안의 내용을 확인 하기! -> 씨그니쳐는 유효화지 않다 (invalid) ->하지만, 시크릿 키를 넣으면 유효한 씨그니쳐가 됨! (이 의미도 무슨 말인지 모르겟음)
코드로 디코드해보기 -> const decoded = jwt.verify(~~~,시크릿키 ) -> jwt.decoded(변조한 키를 넣으면 ) -> 잘 나옴? 잘 이해가 안됨...-> 한번 확인되서 그런건가?
4.로그인 기능 구현 하기!
필요한것)
사용자 관련 몽구스 모델,
프로젝트 세팅과 더불어 사용자 모델을 정의 하는 것까지 구현
(그림을 그려가며 공부하면 좋을것 같다!)
-새로운 폴더를 만듦(shopping) -> 익스프레스 몽구스 제이슨 토큰을 한꺼번에 설치! -> app.js 파일을 만듦 -> 프론엔드 코드 다운 받아서 -> assets라는 폴더에 다운 받은 파일을 넣어줌 -> 새로운 기능) 로그인 체크, 로그인 화면, 회원가입 화면이 추가 ->로그인 체크 기능 ; 로그인화면 회원 가입 페이지 제외를 하고 다른 페이지에 접속하는 경우, api 를 요청 어떤 api? get 메소드에, api/user/me 경로로 항상 호출 한다 status code가 200이 아니라면, 로그인이 안되어 있는 것으로 판단하여, 로그인 화면으로 이동시킨다. -> 그런데 200이 왔다면, 로그인 되었다고 판단하고, get/user/me 에서 반환하는 토큰을 프론엔드에 저장을 한다! -> 로그인 상태 여부는 어떻게 판단? -> 브라우저에 토큰이 저장되어 있는지 아닌지를 살펴 보기! -> 토큰이 저장되어있으면 상품 목록 페이지로 이동! -> /user/me -> 내정보가맞는지 다시한번 확인 -> 잘못되면, 다시 로그인 페이지로 이동 (무한루프로 빠질수 있기 때문에 -> 목록페이지에서 로그인 페이지로 옮길때 브라우저에 저장되어있든 토큰을 비워준다! -> 로그인 버튼을 누르는 경우 post/auth 경로로api를 호출한다 -> 어떤 필드로 보냄? email, password필드로 데이터를 보냄 -> 로그인 성공? -> 상품 목록 페이지로 이동 -> 상품 목록 페이지 이동전에 -> api에서 받아온 토큰을 저장 한다! -> 로그인을 실패 하는 경우 -> 실패 모달을 띄우는걸 구현!
회원 가입 버튼을 누르는 경우 post/user 경로로 api를 호출한다 -> 이메일 닉네임, 패스워드, 컨펌 패스워드 4개의 필드로 데이터를 보냄 -> 비번확인(벨리데이션 개념) -> 회원가입 성공시 -> 로그인 페이지 (회원가입을 성공이라고 아는 방법은 api에서 성공이라고 응답을 줬을때) -> 실패시에 api응답 값 중 "errorMessage"가 있는지 확인! 있다면 필드에 있는 메세지를 보냄(이 부분 중요!)
- 로그인 api
-회원가입api
-내 정보 조회 api (로그인 체크 기능!)
User 모델 구현
- 몽구스를 이용해서 데이터를 저장하려면, 우선 모델을 구해야함
app.js 파일에 시작 코드를 작성하고 -> 모델 폴더를 만들고, user.js 파일을 생성한 뒤 구현해보자!
-> 몽구스 스키마 생성
*몽구스 virtual UserSchema.virtual("userId").get(function() {return this._id.toHexString(); });
-> userId ; 프론트 엔드에서 이 값을 참조 하고 있음 그래서 추가가 됨.
virtual
다큐먼트에는 없지만 객체에는 있는 가상의 필드를 만들어줌
스키마에 virtual을 붙이면, uers컬렉션을 조회할때 {이메일:… 패스워드:…} 처럼 디테일 필드가 생김
그리고 get 메소드 안에 넣어준 함수의 return값이 들어가 있음 (이 부분이 이해가 안되네)
기존의 필드를 활용하여, 새로운 가상 필드를 만드는 기능!
5. 회원가입 API 구현하기(데이터를 저장후 로그인 구현이 좋기때문에)
사용자 인증 미들웨어 구현하기
목록 조회 아무나 조회하게 하면 안됨 -> 회원제 -> JWT로 된 토큰을 우리에게 보내서, 이게 유효한지 체크 하구 -> 토큰 안에 있는 아이디를 데이터 베이스와 비교한다 -> 결과값 반환
순서
유저 모델을 미리 구현 해놨으니 -> 참조 (const User= require('../models/user')
포스터 메서드로 만듦 -> router.post ("/user" aysnc (req,res) =>{
const {name, email, password, confrimPassword} = req.body; });
if (password !== confirmPassword) {
res.status(400).send(errorMessage: "비밀번호와 비밀번호 확인 값이 다릅니다")};
return; (하지 않으면 아래 코드를 실행하지 않기 위해서!) }
const existUSer = await User.find({ $or: [{email}. {nickname}]), });
if (existUser.length) {
res.staus(400).send(errorMessage: "이미 가입된 이메일 혹은 닉네임이 있습니다)};
return;
}
const user = new User({email, nickname, password});
await user.save();
res.status(201).send();
});
6. 로그인 api 구현하기
패스워드를 그대로 저장하면 안됨 -> 암호화 시켜야 함! (서버 개발자도 모르도록) -> 단방향 해쉬 (암호화 할때마다, 다른 값이 나옴/검증 함수로 1234를 넣으면 통과! 단방향으로 원래 문자는 알수 없지만 검증은 가능한 방식
왜? post a메서드냐면? 그때 그때 마다 토큰을 생성하기 때문에
get으로 하면 url에 id가 다 나오기 때문에, 보안에 취약
구현을 하려면?
이메일과 패스워드 값을 받아 데이터 베이스 있는 정보중 이메일, 및 패스워드가 일치하면 로그인 성공!~
성공하면, jwt토큰에 담아서, 사인을 해서 사용자에게 내려줌!
토큰 구성 예시
시크릿 키만 바꿔서 써주기! 이유가? 나머지는 양식을 지켜주기!
router.post ("/auth", async (req,res) => {
const {email, password}= req.body; //왜 아이디값은 가지고 오지 않는지
const user = await User.findOne({email, ,password}).exec();
if (!user) {
res.status(401).send({errorMessage: " 일치하는 이메일 혹은 패스워드가 없습니다});
return;
} // 만들기 전에 토큰 모듈을 불러오기!!
const token = jwt.sign({userId: user.userId} ,"시크릿키 입력");
res.send( {token, }); //응답할때도 토큰이라는 키에다가 jwt토큰을 반환해야 프론엔드에서 정상적으로 동작하도록 구현을 함 (어려..)
}); //프론엔드와 백엔드 연결성 생각하기!
알수 없는 문제 발생? 원인?
내 정보 조회하기 에이파아이 실패 -> 만들기 이전에, 사용자 인증 미들웨어를 구현해야한다 -> 내 정보 조회하기는 쉬어진다!
7. 사용자 인증 미들웨어 구현
미들웨어 구현
http 인증에 대해서 공부하기
이 페이지 에서는 일반적인 http 인증 프레임 워크를 소개하고, 서버에 http 의 베이직 인증방식으로 접근을 제한 하는 것을 보여줌
일반적은 http인증 프레임 워크
서버에 의해 클라이언트 요청을 시도하고, 클라이언트에 의해 인증 정보를 제공하기 위해 사용될수 있는 http 인증 프레임 워크를 정의
시도와 응답 과정?
서버는 클라이언트에게 401응답 코드를 가지고 응답, 최소한의 한번의 시도에 포함된 응답 헤더로 권한을 부여하는 방법에 대한 정보를 제공한다.
**
JWT를 사용하여 API를 만들때, 고려해야 할점, 다른 사용자가 api를 쓰려면 JWT 토큰을 발급받고 인증 받아야 한다.
이는, 대부분의 라우터에 공통적으로 해당하는 부분이므로, 미들웨어로 만드는 것이 좋다
위의 같은 양식으로 보내는 이유는 http 인증중 Bearer 타입을사용하여 토큰을 전달하기 위함
미들 웨어:
폴더 생성 (middlewares) -> auth-middlewares.js
미들웨어 구현해야 함 -> module.exports = function (req, res, next) =>{
next(); //미들웨어는 반드시 next를 호출 해야 함 호출 되지 않는다면, 레벨에서 예외처리가 되어서 뒤에 있는 미들웨어 연결이 안됨.
-> app. js 파일로 돌아와서, 파일을 추가해본다! const authmiddleware = require("./middleware
요청하는 api만들기
router.get("/users/me", authMiddleware, async (req,res) =>{
const {authorization} = req.headers;
console.log(authorization);
cosnt [tokentype, tockentvalue] = athorization.split(' ');
if(tokenType !== 'Bearer') {
res.status(401).send({
errorMessage: "로그인 후 사용하세요",
});
return
}
try {
const decoded = jwt.verify(tokenValue, 시크릿키);
} cacth (error) {
next()
})
사용자 진짜 인증되는지 토큰 검사하기 / => 토큰 벨류가 정상 토큰인지 확인 했으면 -> jwt를 검증하기! (const jwt 를 불러오기!)
-> try catch 구문 사용하기!
2-8 내 정보 조회 api 구현하기
로그인 api만 구현한다고 끝난게 아님 -> 서버에서 인증할수 있는 값을 클라이언트 넘겨주고 -> 클라이언트는 로그인이 필요한 기능 을 할때마다 토큰을 서버에 같이 포함해서 보냄 (그걸 어떻게 함?) http header 중에서 authorization 헤더에 다가 이 토큰 값을 같이 넣어서 보냈음 토큰을 포함해서 api 요청!
2-7/8 다시 듣기!