iT邦幫忙

2022 iThome 鐵人賽

DAY 19
0
Modern Web

Vue+Django+MongoDB+Nginx 全端開發系列 第 19

Json web token authentication --part4: interceptor & api authentication

  • 分享至 

  • xImage
  •  

前言

只要把後端對外,或者網站對外,就一定會被攻擊,有自己用自己的電腦當 server 架站過就一定知道,只要一對外,每天都會收到一些隨機的攻擊,最常見就是別人在亂試 api 看能不能猜對,通常是猜不到啦,鬼知道你的 api 長什麼樣子,更別提要帶什麼參數,能猜對真的是會通靈。

儘管如此,你可能還是不知道在哪洩露了你的 api,有可能不小心推到 github 公開,或者被勒索檔案之類的。所以我們還是要幫 api 上一道鎖比較安全。

作法就是前台這邊發 request 一定要加入 access token 作為驗證依據,後台這邊一定要要求 request 中的 access token 合法才能使用 api。那以下就開始實做吧!

Interceptor

Interceptor 是讓你在前台發出 request 或接收到 response 之前可以先要求做什麼事再進行接下來的 request 或 response。

create instance module

首先我們先在前台 src/ 內創建 utils/useAxios.js ,這邊是把 useAxios.js 做成一個 module,裡面會做一個 instance,要求使用攔截器 (interceptor)。

dayjs 這個套件是等一下用來判斷 access token 是否失效,我們用 axios.create 創建一個 instanse,要求 headers 內 Authorization 為 Bearer 加上我們之前存在 localStorage 的 access token。

再來是攔截器,用 axiosInstance.interceptors.request.use, 要求使用攔截器, const payload=jwt_decode(String(localStorage.getItem('authTokenAccess'))) 解析 access token payload,用 const isExpired = dayjs.unix(payload.exp).diff(dayjs()) < 1; 判斷 access token 是否失效,如果失效就重新去拿 token 並存到 localStorage。

import axios from 'axios'
import jwt_decode from "jwt-decode";
import dayjs from 'dayjs'

const baseURL = 'localhost:8000'

const useAxios=()=>{
  const axiosInstance = axios.create({
    baseURL,
    headers:{Authorization: `Bearer ${localStorage.getItem('authTokenAccess')}`}
  });

  axiosInstance.interceptors.request.use(async req =>{

    const payload=jwt_decode(String(localStorage.getItem('authTokenAccess')))
    const isExpired = dayjs.unix(payload.exp).diff(dayjs()) < 1;

    if(!isExpired){
      return req
    } 
    else{
      const response = await axios.post(`${baseURL}/api/token/refresh/`, {
        refresh: localStorage.getItem('authTokenRefresh')
      });

      localStorage.setItem("authTokenRefresh",response.data['refresh']);
      localStorage.setItem("authTokenAccess",response.data['access']);

      req.headers.Authorization = `Bearer ${response.data['access']}`
      return req    
    }
  })

  return axiosInstance
}

export default useAxios;

use your customize instance

在我們想用攔截器的頁面引入剛剛做的 instance module

import useAxios from '../utils/useAxios'
let api = useAxios()

以下是範例,記得用 asyncawait 做同步處理

let func1 =async()=>{
  let res=await api.get('localhost:8000/expense/get_fixed_item',{
    params:{
      par1:'par1'
    }
  })

  console.log(res.data['something'])
}
func1()

API authentication

再來是後端 API 的部分。很簡單,先在 views.py 上方加入

from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated

然後在想要做驗證的 funtion 前面加上

@api_view([‘GET’]) 
@permission_classes([IsAuthenticated])

像這樣

@api_view([‘GET’]) 
@permission_classes([IsAuthenticated])
def func1(request):
    return JsonResponse({})

ok,到這邊 api 驗證就完成了,就算別人知道你的 api,也用不了了!


上一篇
Json web token authentication --part3: Vue
下一篇
MongoDB getting started
系列文
Vue+Django+MongoDB+Nginx 全端開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言