使用JWT存储用户数据

发布于 2025-02-07 20:55:02 字数 1375 浏览 0 评论 0原文

我正在通过Apollo客户端从GraphQL后端获取用户数据。我的目标是保持用户登录,因此我用所有用户数据签署了JWT令牌,将其传递给LocalStorage(仅代币),将其解码,并将所有值传递给Redux-store。

       UserModel:
 userSchema.methods.createJWT = function (payload) {
      return jwt.sign({ ...payload }, process.env.JWT_SECRET, {
        expiresIn: '1d',
      });
    };

UserLogin:

      await user.save();
      return {
        ...user._doc,
        id: user._id,
        token: user.createJWT(user._doc),
}

ReduxSlice

const userSlice = createSlice({
  name: 'user',
  initialState: {
    userInfo: localStorage.getItem('jwtToken')
      ? jwtDecode(localStorage.getItem('jwtToken'))
      : null,
  },  
  reducers: {
    loginUser: (state, action) => {
      localStorage.setItem('jwtToken', action.payload.token);
      state.userInfo = action.payload;
    },

我想知道该令牌是否可以持有太多信息,这是否还可以 像:

{
  "_id": "62a9ee3878c4979fedb471c5",
  "username": "***",
  "email": "***",
  "password": "$2a$12$hN2lfCtEbqOOFSlHpapyfuxYAHdEGUYKeHY4BMK1YvYOtSG7zHwcS",
  "isAdmin": false,
  "shippingAddress": [],
  "createdAt": "2022-06-15T14:35:36.877Z",
  "updatedAt": "2022-06-16T09:04:59.367Z",
  "__v": 0,
  "firstName": "***",
  "lastName": "***",
  "shoeSize": 4,
  "iat": 1655371413,
  "exp": 1655457813
}

还有另一种保存用户数据并保持他登录的有效方法?

I am fetching user data from the graphql backend through the apollo client. My goal is to keep the user logged in, so I signed jwt token with all user data, passed it to localStorage(only the token), decoded it, and passed all values to redux-store.

       UserModel:
 userSchema.methods.createJWT = function (payload) {
      return jwt.sign({ ...payload }, process.env.JWT_SECRET, {
        expiresIn: '1d',
      });
    };

userLogin:

      await user.save();
      return {
        ...user._doc,
        id: user._id,
        token: user.createJWT(user._doc),
}

reduxSlice

const userSlice = createSlice({
  name: 'user',
  initialState: {
    userInfo: localStorage.getItem('jwtToken')
      ? jwtDecode(localStorage.getItem('jwtToken'))
      : null,
  },  
  reducers: {
    loginUser: (state, action) => {
      localStorage.setItem('jwtToken', action.payload.token);
      state.userInfo = action.payload;
    },

I am wondering if this is ok that the token is holding too much info
like:

{
  "_id": "62a9ee3878c4979fedb471c5",
  "username": "***",
  "email": "***",
  "password": "$2a$12$hN2lfCtEbqOOFSlHpapyfuxYAHdEGUYKeHY4BMK1YvYOtSG7zHwcS",
  "isAdmin": false,
  "shippingAddress": [],
  "createdAt": "2022-06-15T14:35:36.877Z",
  "updatedAt": "2022-06-16T09:04:59.367Z",
  "__v": 0,
  "firstName": "***",
  "lastName": "***",
  "shoeSize": 4,
  "iat": 1655371413,
  "exp": 1655457813
}

There is another effective way to save user data and keep him logged in?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凡间太子 2025-02-14 20:55:02

不建议(实际上非​​常危险)使用JWT令牌特别密码返回所有信息。我认为USERID就足够了!
但是您也可以返回用户名,firstName,lastname,等。
但是,在某些情况下,由于某些用户隐私原因,甚至返回电子邮件地址也不是一个好方法。

我的意思是,您只需要一旦有用户就可以获取用户ID,并且凭据是正确的,那么:

const userToken = {
  userId: user._id,
  username: user.username,
};
 
return {
  user,
  token: user.createJWT(userData)
};

现在,在签署了JWT令牌后,您可以在某些Redux状态甚至React上下文(选择您的喜欢)中设置用户中的任何数据,但不要在LocalStorage中设置任何密码。

更新:最后,您应该从有效载荷中存储用户:

state.userInfo = action.payload.user;

顺便说一句,您应该检查localStorage仅用于获取令牌并验证它,然后根据用户ID进行获取用户并存储它,以下是一个示例:

  const getUser = React.useCallback(async (userId) => {
    try {
      const res = await axios.post('/auth/login', {userId}, {
        credentials: 'include',
        withCredentials: true
      });
      const { accessToken, user } = res.data;
      setState((currentState: IState) => ({
        ...currentState,
        user,
        loading: false,
        isAuth: !!accessToken,
        accessToken
      }));
    } catch (err) {
      setState((currentState: IState) => ({
        ...currentState,
        user: null,
        loading: false,
        isAuth: false,
        accessToken: ''
      }));
    }
  }, []);

  useEffect(() => {
    getUser(userId);
  }, [getUser]);

  useEffect(() => {
  const jwtToken = localStorage.getItem('jwtToken');
    if (jwtToken && jwt_decode(jwtToken)) {
      const { exp } = jwt_decode(jwtToken);
      const currentTime = Date.now() / 1000;
      if (exp < currentTime) {
        getUserById(userId);
      }
    }
  }, [getUser]);

it's not recommended (actually very dangerous) to return all information with the jwt token especially password. I think userId is enough!
But you can also return username, firstName, lastName, etc.
But in some cases even returning email address is not a good approach for some user privacy reasons.

I mean by that you have only to get the userId once there is a user and the credentials are correct, then :

const userToken = {
  userId: user._id,
  username: user.username,
};
 
return {
  user,
  token: user.createJWT(userData)
};

Now after signing the jwt token , you can set whatever data from user inside some redux state or even react context , (choose your favorite) , but DON'T set any password in the localStorage.

Update: at the end you should store the user from the payload like this :

state.userInfo = action.payload.user;

Btw you should check the localStorage only to get the token and verify it , then based on userId you need to fetch the user and store it, here is an example :

  const getUser = React.useCallback(async (userId) => {
    try {
      const res = await axios.post('/auth/login', {userId}, {
        credentials: 'include',
        withCredentials: true
      });
      const { accessToken, user } = res.data;
      setState((currentState: IState) => ({
        ...currentState,
        user,
        loading: false,
        isAuth: !!accessToken,
        accessToken
      }));
    } catch (err) {
      setState((currentState: IState) => ({
        ...currentState,
        user: null,
        loading: false,
        isAuth: false,
        accessToken: ''
      }));
    }
  }, []);

  useEffect(() => {
    getUser(userId);
  }, [getUser]);

  useEffect(() => {
  const jwtToken = localStorage.getItem('jwtToken');
    if (jwtToken && jwt_decode(jwtToken)) {
      const { exp } = jwt_decode(jwtToken);
      const currentTime = Date.now() / 1000;
      if (exp < currentTime) {
        getUserById(userId);
      }
    }
  }, [getUser]);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文