iT邦幫忙

0

在Http Only 的網站 傳送 JWT Token 至後端API

  • 分享至 

  • xImage

今天我要從前端的SPA,透過axios呼叫某個後端的API
而後端的API的驗證機制使用JWT Token

一般來說,這個Token值則會在登入時放入Client的Cookie當中
每次呼叫ajax時,將JWT的Token值塞入在Request的Header的Authorization

可是因為安全性的問題,該網頁的Cookie有設定Httponly
所以無法透過Javascript從Cookie取得Token,無法將Token塞入Request的Header
想請教這個問題在C# Web API 與 Laravel 等後端API 通常該怎麼實作?

淺水員 iT邦大師 6 級 ‧ 2019-12-11 23:56:10 檢舉
(看錯,先刪除)
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
Ray
iT邦大神 1 級 ‧ 2019-12-12 08:21:37
最佳解答

這個 Laravel 的做法, 是不是你要的情境:

HttpOnly cookie is a more secure place to put the token since no js code can access it. Fortunately, Laravel JW Auth library let you do that out of the box.

JWT HttpOnly authorization with Laravel and React

通靈亡 iT邦高手 1 級 ‧ 2019-12-12 17:56:12 檢舉

是這個情境沒有錯
不過我剛才仔細看了一下內文

我有看到一段Login的驗證Controller程式碼,會把登入後的Token設定在Cookie:

public function login(LoginRequest $request): JsonResponse
{
    return (new AuthResource(auth()->user()))
        ->response()
        ->withCookie(
            'token', 
            auth()->getToken()->get(), 
            config('jwt.ttl'), 
            '/'
        );
}

那麼每當呼叫需要驗證JWT的API路由時
是不是不需要在Request的Header存放Token
Laravel會有什麼機制自動從Request取得Client端的Cookie驗證JWT?
因為其他的方法都是跟防CSRF的Token有關,沒看到存取JWT的程式碼

Ray iT邦大神 1 級 ‧ 2019-12-12 19:02:02 檢舉

Cookie 是存在 Browser 裡面, 每一筆瀏覽 Browser 都會主動從 Cookie 內 將 JWT Token 取出, 帶進 Header 裡面送給 Server, 你不需要自己用 JS 去送.... 請參考:
Day 19 - 二周目 - 帳密認証與JWT (JSON Web Token)傳遞
最下面「回傳JWT」那節的說明....

2
dragonH
iT邦超人 5 級 ‧ 2019-12-11 22:39:33

所以無法透過Javascript從Cookie取得Token,無法將Token塞入Request的Header

那就不要放 header 阿

看你用 cookie 或是 payload 帶到後端都可以

也不一定要放 cookie

localStorage 也可以

看你的需求

看更多先前的回應...收起先前的回應...
通靈亡 iT邦高手 1 級 ‧ 2019-12-11 22:57:56 檢舉

因為安全性問題,不會把Token放在localStorage
Cookie本身在前端已經設定HttpOnly所以也不可能從前端帶到後端

Laravel 跟 C# Web API 有設定要驗證JWT的 Route,都要在Header放Token才能通過JWT驗證

可是如果不能放在LocalStorage,也不能從Cookie取得放在Header
是不是就無法讓後端的API通過JWT驗證

dragonH iT邦超人 5 級 ‧ 2019-12-11 23:34:55 檢舉

因為安全性問題,不會把Token放在localStorage

我是覺得安不安全

跟你放在哪沒啥太大關係

反正前端都看的到

竄改的話

應該是後端負責把關

froce iT邦大師 1 級 ‧ 2019-12-12 09:55:33 檢舉

我的作法就放在vuex這種狀態管理器中,然後把它freeze起來。
不放在cookies中。

通靈亡 iT邦高手 1 級 ‧ 2019-12-12 17:16:11 檢舉

感謝force~~
你提供的做法在SPA確實可行

0
淺水員
iT邦大師 6 級 ‧ 2019-12-12 02:39:40

如果是希望 token 不被其他 javascript 存取
目前我想得到的方法是利用下面兩點:

  1. Closure 內的變數無法被外界的 javascript 讀取
  2. script 在沒有加上 defer 或 async 時會立刻執行

登入後的第一個頁面

<body>
    <!--下面這兩行放 body 最前面,注意 axios4api.js 不要加上 defer 或 async-->
    <input id='authToken' type='hidden' value='auth_token'>
    <script src="axios4api.js"></script>
    <!--後面放其他程式碼-->
</body>

axios4api.js

let axios4api=(()=>{
    let ele=document.querySelector('#authToken');
    let token=ele.value;
    ele.parentElement.removeChild(ele);
    ele=null;
    let myAxios=false;
    function wrap() {
        let params=Array.from(arguments);
        return getMyAxios().apply(null, params);
    }
    
    let methods=['request', 'get', 'delete', 'head', 'options', 'post', 'put', 'patch', 'getUri'];
    methods.forEach((method)=>{
        wrap[method]=function() {
            let params=Array.from(arguments);
            return getMyAxios()[method].apply(null, params);
        }
    });
    
    return wrap;
    
    function getMyAxios() {
        if(!myAxios) {
            myAxios=axios.create({
                headers: {'Authorization': token}
            });
        }
        return myAxios;
    }
})();

這樣後面使用時,把 axios 改成 axios4api 就可以夾帶 token 了

通靈亡 iT邦高手 1 級 ‧ 2019-12-12 17:19:10 檢舉

可是這個做法遇到換頁的話,Token是不是就不會保留了

淺水員 iT邦大師 6 級 ‧ 2019-12-13 11:36:34 檢舉

這的確換頁的話就消失了,所以每個新的頁面都要跑一次這個流程。因為一開始看到 SPA 以為不會有換頁的狀況。

我要發表回答

立即登入回答