我是React的初学者,开始制作一个全栈应用程序(一个带有身份验证的小博客应用程序)。我使用在用户登录时放入Cookie中的JWT令牌。我在标题中打印登录用户的名称。在页面刷新之前,这一切都很完美。当我刷新页面时,我仍然可以访问受保护的路由,因为我在存储中有一个JWT cookie,但是我丢失了整个用户对象,当用户登录时,对象中充满了用户信息,当我刷新页面时,对象为空。
这是我的React Reducer:
export const userLoginReducer = (state = { user: {} }, action) => {
switch (action.type) {
case USER_LOGIN_REQUEST:
return { loading: true, isAuthenticated: false };
case USER_LOGIN_SUCCESS:
return {
...state,
loading: false,
isAuthenticated: true,
user: action.payload,
};
case USER_LOGIN_FAIL:
return { loading: false, isAuthenticated: false, error: action.payload };
case USER_LOGOUT:
return { loading: false, isAuthenticated: false, user: null };
default:
return state;
}
};
这是我的React Action:
const { data } = await API.post(
'/api/v1/users/login',
{ email, password },
config
);
dispatch({
type: USER_LOGIN_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
API配置为Axios:
export default axios.create({
baseURL: 'http://localhost:8000',
withCredentials: true,
credentials: 'include',
});
这是我的登录界面:
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const redirect = location.search ? location.search.split('=')[1] : '/';
const dispatch = useDispatch();
const userLogin = useSelector(state => state.userLogin);
const { loading, error, isAuthenticated } = userLogin;
在您的Thunk中调度USER_LOGIN_SUCCESS后,您可以将用户信息添加到本地存储:
const { data } = await API.post(
'/api/v1/users/login',
{ email, password },
config
);
dispatch({
type: USER_LOGIN_SUCCESS,
payload: data,
});
// Setting user to local storage
localStorage.setItem('user', JSON.stringify(data));
} catch (error) {...}};
然后在store.js文件(或者任何你配置store的文件)中,你可以从本地存储中获取user对象并将其添加到初始状态,如下所示:
const user = localStorage.getItem('user')
? JSON.parse(localStorage.getItem('user'))
: { user: null };
const initialState = {
// Add the user object from local storage to whatever slice of state is appropriate
auth: { user, loading: false },
...
};
刷新页面取回
为了在刷新页面时获取用户,我将在app.js文件中添加一个useEffect钩子:
// /app.js
useEffect(() => {
dispatch(login())
}, [])
user: action.payload
是用户对象吗?
这些数据没有被存储在cookie中,所以在页面刷新后它们不会持续存在。你需要在刷新时重新获取,或者将它们存储在持久存储(如localStorage)中,并在获取之前进行检查。
更新:
是,user: action。负载是用户对象,刷新后为空。你能给我一些建议如何重新获取用户吗?
一个临时的解决方案是通过调用您为reducer创建的操作来发出fetch请求:
- USER_LOGIN_REQUEST
- USER_LOGIN_SUCCESS
通过向后端服务提供JWT令牌进行身份验证来触发登录请求。返回经过身份验证的响应。你可以使用组件中的一个React生命周期钩子来做这件事(例如componentDidMount)。但我不认为这是一个好的长期解决方案。你可能想要查找React认证示例,并在组件被挂载之前发出fetch请求,因为这似乎是一个应用范围的需求。
您提到将JWT和cookie一起使用,这可能意味着从cookie中读取数据,或者仅使用cookie和JWT作为安全性。这可能不足以保护您的用户。OWASP有一些建议,您可以单独查看JWT安全性。