res.status~ .json()
의 .json()
부분에 {message : "로그인 성공", data : accessToken }
이런 식으로 넣어서 반환해주면 된다. const { characterName } = req.body;
로 받을것data : character
이런식으로 생성결과 같이 반환해주라는 얘기인것 같아 그렇게 구현. 비로그인 / 로그인한 타인과 로그인한 캐릭터주인의 로직이 달라야한다.
일단 삭제할 캐릭터가 있는지부터 확인해야 한다. characterId를 req.params로 받아올 것.
과제에서 password를 제대로 입력했는지 한번 더 확인 입력받는 조건이 있어 아무 생각없이 passwordConfirm도 DB에 push하도록 했는데, 생각해보니 이건 클라이언트단에서 둘이 일치하는지만 걸러주고 가면 되고 DB에 저장될 필요까지는 없었다. 모두의 도움으로 불필요한 컬럼을 만들지 않도록 수정했다.
Authentication은 id, password로 로그인 하는 작업으로 볼 수 있다. 인증된 신분을 가진 사람인지 확인하는 것. OAuth도 이 중 하나.
Authorization은 인증된 신분인 것은 확인 했는데, 특정 리소스에 접근할 수 있는지 권한을 확인하는 것이다. 판다우리에는 강바오 송바오는 들어갈 수 있어도 나는 들어갈 수 없다. 로그인된 사용자만 게시글을 작성하도록 검증하는 과정이 인가이다. 이것은 사용자 인증 미들웨어로 구현할 것이다. -> 이게 auth.middleware.js!
bcrypt.compare(입력받은 pwd, prisma find로 찾은 DB의 해당계정 pwd) 이렇게 써서 복호화 한 결과가 같으면 true, 아니면 false로 돌려줄 것이다.
이런 식으로 짠다.
토큰을 '쿠키에 담아 전달하지 말라'는 것 뿐이지, 토큰은 어찌됐든 줘야한다. 그래야 어떤 작업을 수행할 때 '내가 이 계정으로 로그인 한 이 사용자야!' 라는 것을 매번마다 서버가 알고 이 리퀘스트 주체의 행동을 인가할지 말지 결정할 수 있기 때문!
-> 로그인은 인증, 한정 리소스에 접근하는 것은 인가. 그래서 JWT도 인증을 위한 과정이다.
나중에 게시판 유저, 관리자 등의 등급과 접근권한을 나눈다면 그건 별도의 '인가'가 될것.
내가 여기에 TOKEN_SECRETKEY를 .env에 따로 빼놓고 dotenv로 불러온 이유는, JWT 암호화 할때 저 시크릿키가 필요하기 때문.
튜터님은 쿠키를 쓰셨지만 일단 형태만 보자면, req에 쿠키를 할당해주고 있다. 'authorization'이라는 키 값을 가지고 Bearer로 시작하도록 Bearer ${token}
이라는 형태로 조립해주었다.
Bearer는 JWT의 프로토콜 -> '얘는 JWT를 사용해서 인증요청 하는거야' 라는 것을 알려주는 용도. 얘가 붙어서 나가는 것은 내가 Insomnia의 Auth에서 Bearer Token을 선택했기 때문이고, jwt.sign만 하면 헤더.페이로드.시그니처인 알몸(?)만 뿅 만들어지는게 맞다.
내가 얘를 Bearer 형식으로 보내는 토큰임을 알리려는 방법은 여러가지다. Headers에 Add 해서 Bearer%20
만큼을 붙여줘서 만들어도 상관없는 것.
240910 TIL 참고해볼 것.
Access Token이 내가 처음에 로그인 할때 발급받았던 그 토큰이 맞다. 그런데 걔가 탈취되면 곤란하니(로그인에 필요한 일종의 키가 아예 털려버리니까),
Access Token 시간을 짧게 주고 Refresh Token을 길게 주는 식으로 털려도 덜 위험하도록 계속 인증 인가를 다시 하게 만들자는 시스템.
그래서 리프레시 토큰은 어떻게 만드는데? -> 이건 지금은 필요없지만, 액세스 토큰 만들듯 시크릿키 따로 두고 jwt.sign으로 만들면 된다.
얘는 왜 이렇게 오는걸까? 이유는 모르겠지만 req.headers['authorization']
으로 바꿨더니 잘 찾는다. 얘는 그냥 둬야겠다.
Authorization Header에 담은 JWT를 토대로 사용자를 인식하는 녀석이고 검증절차도 auth.middlewares.js에 다 들어있다. 계정의 고유 id로 유저를 찾고, 찾았으면 그 정보를 req.user에 담아서 다음 미들웨어로 넘겨준다.
그게 요 부분이다. req.user = user
이 구절이 검색된 유저정보를 req.user에 담는거고, next()로 다음 미들웨어에 넘기고 있다.
위 얘기가 저 req.user 얘기다. 나는 JWT 기반으로 인증된 사용자 정보를 이미 담아서 다음 동작으로 넘기고 있으니 OK.
캐릭터 상세조회에서 다른유저 로그인까진 되는데, 비로그인 유저의 경우 auth 미들웨어에서 토큰이 없다고 걸려버려 아무리 if문을 걸어도 캐릭터 조회 로직은 타지도 못한다.
어떻게 해야할지 도저히 감이 안 와 질문드리러 총총.
여기는 auth미들웨어가 오면 안되거나, 다른 미들웨어가 필요할 수 있다. 아니면 다른 미들웨어가 필요한건 맞는데, auth 미들웨어도 있으면 auth 미들웨어 까지 실행하지는 않을 수 있는 방법이 있다.
1. 요주는 auth미들웨어 앞에 분기 같은게 걸리면 되는 것! auth 헤더를 검증해서 헤더에 토큰이 없으면 없는대로 새 미들웨어쪽 로직을 타고, 있으면 auth 미들웨어를 타게끔.
익스프레스 미들웨어 문서를 보면 미들웨어를 건너뛰는 방법에 대해 나와있다. next('route')
를 쓰면 이 핸들러의 다음 경로로 가는게 아니라 다음 라우터로 점프해버린다.
(이걸 모른다면 익스프레스 문서를 안읽은 것😏)
익스프레스 문서
미들웨어 건너뛰는 방법 긱
아니면 req에서 값을 하나 더 설정할 수도 있을 것이다. req.isSignedUser 같은 불린값을 설정해 보는것도... -> ?? 이 말씀은 잘 이해하지 못했다😥
그래서 방법은 크게 두가지!
1. auth미들웨어를 고친다
2. 다른 미들웨어를 추가해야 한다
근데 1번은 부작용이 크니까 다른 미들웨어를 추가하는게 좋다.
그렇게 고친 나의 코드는 다음과 같다
얘를 characters.router.js에 import 해주고 캐릭터 상세조회 라우터에 미들웨어로 끼워넣었더니 원하는 대로 동작한다!
PUT : 자원의 전체 교체, 자원교체 시 모든 필드 필요
(만약 전체가 아닌 일부만 전달할 경우,
전달한 필드외 모두 null or 초기값 처리되니 주의!!)
PATCH : 자원의 부분 교체, 자원교체시 일부 필드 필요
이런 식으로 item_stat을 Json 타입으로 선언하면 item_stat : {"atk" : item_stat.atk, "hp" : item_stat.hp}
이런 식으로 써줄 수 있다. 한 개의 컬럼에서 여러 데이터를 다룰 수 있는 것.
chore는 하기 싫은 일, 혹은 루틴적으로 하는 일이라는 뉘앙스가 담겨있다. (집안일 같은 느낌)
feat : 새로운 기능 추가
fix : 버그 수정
docs : 문서 수정
style : 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우
refactor : 코드 리펙토링
test : 테스트 코드, 리펙토링 테스트 코드 추가
chore : 빌드 업무 수정, 패키지 매니저 수정
제발 집에 가염 여러분