javascript - 在 React 中如何正確地將存取權杖儲存在記憶體中
我正在尋找一種在 React 中存儲我的存取權杖的乾淨方法。
- 首先:我不想使用本地存儲。我不需要使我的訪問令牌持久化,因為我隨時都可以刷新它。
- 我也排除了使用 cookie,因為我想防止 CSRF 攻擊。事實上,通過僅將訪問令牌存儲在記憶體中,頁面需要加載以獲取令牌並進行請求認證(刷新令牌只能用於刷新)
- 我曾想過使用 redux/context,然而,呼叫 API 的函數不是組件的子元素,所以我無法從那裡取得 token。此外,我也不想把 token 作為參數傳遞,因為我想保持 HTTP 邏輯的解耦。也許有一個乾淨的方法來使用它?
經過一番研究,我發現使用全域變數是一種可行的“捷徑”,可以達到我想要的結果。然而,我在猜是否有更清楚的方法獲得同樣的結果。
//token.js
const access_token= "";
export const setAccessToken(token){
access_token=token;
}
export const getAccessToken(){
return access_token;
}
//NOTICE:
// -ON LOGIN/REFRESH: I set the access token
// -ON API CALLS: I get the access token and I add it to the header
api.js
const baseURL= "http://my_base_url";
const generateApiInterface = ()=>{
let headers : any= {
};
token=getAccessToken(); //HERE I NEED TO RETRIEVE MY ACCESS TOKEN
if(token){
headers={
'Authorization': 'Token '+ token,
...headers //append other basic proprieties
}
}
return axios.create({
baseURL: baseURL,
headers: headers
});
}
const api = generateApiInterface();
答案#1
你這樣做是為了將任何東西保存在記憶體中比較好。如果這是在伺服器端,那麼你會想確保在完成後刪除該令牌,但如果不是,則目前的方法是可取的。注意,你正在使用 const,你可能想將其改為 let。另一個想法是使用 session storage,但那會涉及到 XSS 的問題。
不過,React 提供了一種方式來擁有「全局」狀態——這就是使用 provider 和 context。這裡有一個例子:
// provider.tsx
import React, { useContext, createContext, FC, useState } from 'react'
type AccessTokenContext = [string, React.Dispatch<React.SetStateAction<string>>]
const AccessTokenProvider: FC = (props) => {
const [accessToken, setAccessToken] = useState<string>(null)
return <AccessToken.Provider value={[accessToken, setAccessToken]} {...props} />
}
const AccessToken = createContext<AccessTokenContext>(null)
const useAccessToken = (): AccessTokenContext => useContext<AccessTokenContext>(AccessToken)
export { AccessTokenProvider, useAccessToken }
你必須將你的應用程式容器包裹在 AccessTokenProvider 中:
// index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import { AccessTokenProvider } from './providers/AccessTokenProvider'
ReactDOM.render(
<AccessTokenProvider>
<App />
</AccessTokenProvider>,
document.getElementById('app')
)
然後你可以在 App 和 App 的任何子組件中使用這個 hook useAccessToken。當然,這個 provider 不必在根層級,但將它放在這裡是最簡單的方式。
// app.tsx
import React, { FC } from 'react'
const App: FC = props => {
const [accessToken, setAccessToken] = useAccessToken()
return <div>{/* content */}</div>
}
export default App
