JWT:JSON Web Token
JWT的作用是用户授权(Authorization),而不是用户的身份认证(Authentication)
授权(Authorization)vs认证(Authentication)
- 用户认证指的是使用用户名、密码来验证当前用户的身份
- 就是用户登录
- 错误状态码:401 Unauthorized(未授权)
- 用户授权指当前用户有足够的权限访问特定的资源
- 错误状态码: 403 forbidden(禁止访问)
传统的Session登录
- 用户登录后,服务器会保存登录的session信息
- Session ID会通过cookie传递给前端
- http请求会附带cookie
- 是有状态登录
JWVT 彻底改变了用户授权与认证的过程
- 替换cookie
- JWT 信息只需要保存在客户端
- 是无状态登陆
Session vs JWT
- Session需要保存在服务器上,而Session ID则保存在前端cookie中
- JWT信息只需要保存在客户端
- 无状态登陆优势:分布式部署
JWT的优点与缺点
JWT官网:https://jwt.io/
优点
- 无状态,简单、方便,完美支持分布式部署
- 非对称加密,Token 安全性高
缺点
- 无状态,token一经发布则无法取消(无解 …)
- 明文传递,Token 安全性低(使用https可以解决)
redux-persist 登录持久化
cokkie 、session和web storage
- cookie和web Storage保存在浏览器中;session保存于服务器上
- cookie不超过4K,Web Storage上限5MB以上;session 无上限
- cookie和web Storage 安全性差,session 性能差
- cookie在http请求中会被自动携带;web Storage不会自动发送
无状态登录:JWT 只能选择使用cookie或者web storage来保存
Web Storage 好处
- 有效降低网络流量
- 快速显示数据
- 临时存储
Web Storage 类型
- SessionStorage:仅在当前浏览器窗口关闭之前有效
- localStorage:始终有效,窗口或浏览器关闭也一直保存
使用redux-persist做持久化
使用
npm install redux-persist
修改以下store.ts
import { createStore, applyMiddleware } from 'redux';
import languageReducer from "./language/languageReducer";
import recommendProductsReducer from "./recommendProducts/recommendProductsReducer";
import thunk from "redux-thunk";
import { actionLog } from "./middlewares/actionLog";
import { productDetailSlice } from "./productDetail/slice";
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { productSearchSlice } from "./productSearch/slice";
import { userSlice } from "./user/slice";
const rootReducer = combineReducers({
language: languageReducer,
recommendProducts: recommendProductsReducer,
productDetail: productDetailSlice.reducer,
productSearch: productSearchSlice.reducer,
user: userSlice.reducer
})
// const store = createStore(rootReducer, applyMiddleware(thunk, actionLog));
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => [...getDefaultMiddleware(), actionLog],
devTools: true,
});
export type RootState = ReturnType<typeof store.getState>
export default store;
修改为以下
import { createStore, applyMiddleware } from 'redux';
import languageReducer from "./language/languageReducer";
import recommendProductsReducer from "./recommendProducts/recommendProductsReducer";
import thunk from "redux-thunk";
import { actionLog } from "./middlewares/actionLog";
import { productDetailSlice } from "./productDetail/slice";
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { productSearchSlice } from "./productSearch/slice";
import { userSlice } from "./user/slice";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
const persistConfig = {
key: "root",
storage,
whitelist: ["user"]
}
const rootReducer = combineReducers({
language: languageReducer,
recommendProducts: recommendProductsReducer,
productDetail: productDetailSlice.reducer,
productSearch: productSearchSlice.reducer,
user: userSlice.reducer
})
const persistedReducer = persistReducer(persistConfig, rootReducer)
// const store = createStore(rootReducer, applyMiddleware(thunk, actionLog));
const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) => [...getDefaultMiddleware(), actionLog],
devTools: true,
});
const persistor = persistStore(store)
export type RootState = ReturnType<typeof store.getState>
export default { store, persistor };
以下引用
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import 'antd/dist/antd.css';
import "./i18n/configs"
import { Provider } from "react-redux";
import store from "./redux/store";
import axios from "axios";
axios.defaults.headers['x-icode'] = 'FB80558A73FA658E';
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
修改成
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import "antd/dist/antd.css";
import "./i18n/configs";
import { Provider } from "react-redux";
import rootStore from "./redux/store";
import axios from "axios";
import { PersistGate } from "redux-persist/integration/react";
axios.defaults.headers["x-icode"] = "FB80558A73FA658E";
ReactDOM.render(
<React.StrictMode>
<Provider store={rootStore.store}>
<PersistGate persistor={rootStore.persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);