토큰이 필요한 route에 접근.
→ router.beforeEach에서 캐치하여 dispatch('VerifyToken')을 호출.
→ interceptors.request에서 토큰을 담아 전송. (VerifyToken request)
→ 만료시간이 지나지 않았다면 통과, 정상적으로 페이지 이동.
( 에러가 발생했다면 )
→ 만료시간이 지났다면 401 Unauthorized 발생, interceptors.response에서 캐치,
→ 401에러라면 config에 isRetried를 추가해 무한 요청을 방지 후 dispatch('RefreshToken') 호출. (RefreshToken request)
→RefreshToken으로 갱신된 토큰을 갖고 다시 api 요청. (VerifyToken request)
→router.beforeEach에서 요청한 VerifyToken이 통과되었으므로 정상적으로 페이지 이동.
추가, 수정, 삭제 요청.
→ request에서 headers에 토큰을 추가하여 요청. (Create/Update/Destroy request)
→ 만약 만료되었거나, 토큰이 정상적이지 않은 경우, 위의 에러가 발생했을 때처럼dispatch.('RefreshToken') 호출...
문제가 있다면 어떤 요청에도 토큰을 검사해, 만료되었다면 새로 발급해주어야 한다는 점이다.
Check user equals to article author
먼저 Article 모델에 author필드를 추가, foreignKey로 Profile과 연결했다.
각 http 요청에 따라 매칭되는 액션을 호출했다. APIView들이 이렇게 다 되어있어서 일일이 호출해주어야 했다.
게시글을 수정 또는 삭제하려고 할 때 사용자의 id와 작성자의 id가 같아야만 페이지가 이동되도록 해야한다.
그러려면 먼저 사용자의 id를 알아야 하는데 프론트는 토큰만 갖고 있기 때문에 토큰을 뜯어보기 전까진 알 수가 없다.
JS로 뜯으면 되지만, 깔끔한 방법은 아니라고 생각되어 백엔드에서 가능한 방법을 생각해봤다.
Token Refresh flow
axiosInstance
를 만들고, interceptor를 이용해 요청을 보내기 전에 토큰이 유효한지 검사하기로 했다.router.beforeEach
에서 캐치하여dispatch('VerifyToken')
을 호출. →interceptors.request
에서 토큰을 담아 전송. (VerifyToken request) → 만료시간이 지나지 않았다면 통과, 정상적으로 페이지 이동. ( 에러가 발생했다면 ) → 만료시간이 지났다면 401 Unauthorized 발생,interceptors.response
에서 캐치, → 401에러라면 config에 isRetried를 추가해 무한 요청을 방지 후dispatch('RefreshToken')
호출. (RefreshToken request) →RefreshToken으로 갱신된 토큰을 갖고 다시 api 요청. (VerifyToken request) →router.beforeEach
에서 요청한 VerifyToken이 통과되었으므로 정상적으로 페이지 이동.headers
에 토큰을 추가하여 요청. (Create/Update/Destroy request) → 만약 만료되었거나, 토큰이 정상적이지 않은 경우, 위의 에러가 발생했을 때처럼dispatch.('RefreshToken')
호출...문제가 있다면 어떤 요청에도 토큰을 검사해, 만료되었다면 새로 발급해주어야 한다는 점이다.
Check user equals to article author
IsOwner Permission
을 추가, 토큰을 검증해 나온 user id와 게시글의 author id가 같아야 권한을 허용하도록 변경했다. https://github.com/10cheon00/RESTful-blog/blob/539ceda970cb1384f6696d29cfb5e90f06376d38/blog_project/backend/articles/views.py#L31-L33 이렇게 했다면 api요청 시 토큰만 가지고도 접근을 막을 수 있다. 하지만 백엔드는 최후의 방어막이고, 프론트에서 막는 방법도 추가해야했다.https://github.com/10cheon00/RESTful-blog/blob/539ceda970cb1384f6696d29cfb5e90f06376d38/blog_project/backend/profiles/views.py#L51-L61
JWTAuthentication
객체에 토큰을 검증하는 코드와 유저id를 알아내는 코드가 담겨 있어 그대로 이용했다. SimpleJWT에서 제공하는 객체다. 객체는 serialize될 수 없어서 dictionary로 일일이 쪼개 넘겼다. 아마 이것도 유틸이 있을 것 같다.로그인에 성공할 때도 똑같이
response.data['profile']
에 유저 정보를 담아 넘겼다. 이렇게 api설정을 마치면 토큰을 이용해 사용자 정보를 얻을 수 있고, vuex에 이 정보를 저장, 필요할 때마다 조회할 수 있다.beforeEnter
로 네비게이션 가드를 할 수 있다. https://github.com/10cheon00/RESTful-blog/blob/539ceda970cb1384f6696d29cfb5e90f06376d38/blog_project/frontend/src/router/articleRoute.js#L15-L32 url 직접접근을 할 수도 있어 비동기로 작성했다. 게시글을 갖고온 후, id를 비교한다. 같으면 통과, 틀리면 게시글 페이지로 이동한다.