【问题标题】:How do I forward authorization with the user JWT token in the header and compare it to the JWT token in the cookie to Auth user?如何使用标头中的用户 JWT 令牌转发授权并将其与 cookie 中的 JWT 令牌进行比较以验证用户?
【发布时间】:2021-12-07 06:10:01
【问题描述】:

我的登录用户有问题,当我刷新页面时,用户迷路了。这就是我分配 JWT 令牌的方式:

const signToken = id => {
  return jwt.sign({ id }, 'my-ultra-secure-and-ultra-long-secret', {
    expiresIn: '14d',
  });
};

这也是我使用此函数向 cookie 发送令牌的方式:

const createSendToken = (user, statusCode, res) => {
  const token = signToken(user._id);

  const cookieOptions = {
    expires: new Date(Date.now() + 14 * 1000 * 60 * 24),
    httpOnly: true,
  };

  res.cookie('jwt', token, cookieOptions);

  // Remove password from output
  user.password = undefined;

  res.status(statusCode).json({
    status: 'success',
    token,
    data: {
      user,
    },
  });
};

这是我的登录控制器:

exports.login = catchAsync(async (req, res, next) => {
  const { email, password } = req.body;

  // 1) Check if email and password exist
  if (!email || !password) {
    return next(new AppError('Please provide email and password!', 400));
  }
  // 2) Check if user exists && password is correct
  const user = await User.findOne({ email }).select('+password');

  if (user && (await user.correctPassword(password, user.password))) {
    createSendToken(user, 200, res);
  } else {
    return next(new AppError('Incorrect email or password', 401));
  }
});

这是我的 Protect 控制器(保护中间件):

exports.protect = catchAsync(async (req, res, next) => {

  // 1) Getting token and check of it's there
  let token;
  if (
    req.headers.authorization &&
    req.headers.authorization.startsWith('Bearer')
  ) {
    token = req.headers.authorization.split(' ')[1];
  }
  if (!token) {
    return next(
      new AppError('You are not logged in! Please log in to get access.', 401)
    );
  }
  // 2) Verification token
  const decoded = await promisify(jwt.verify)(
    token,
    'my-ultra-secure-and-ultra-long-secret'
  );
  // 3) Check if user still exists
  const currentUser = await User.findById(decoded.id);
  if (!currentUser) {
    return next(
      new AppError(
        'The user belonging to this token does no longer exist.',
        401
      )
    );
  }
  // 4) Check if user changed password after the token was issued
  if (currentUser.changedPasswordAfter(decoded.iat)) {
    return next(
      new AppError('User recently changed password! Please log in again.', 401)
    );
  }
  // GRANT ACCESS TO PROTECTED ROUTE
  req.user = currentUser;
  res.locals.user = currentUser;
  next();
});

这是我使用这个中间件的私有路由:

router.route('/:id').get(authController.isLoggedIn, postController.getPost);

问题是当我登录时我得到一个 cookie,但我无法访问受保护的路由(我得到一个错误令牌未定义)。当我刷新页面时,用户丢失了,但 cookie 仍在存储中。当我尝试通过邮递员访问保护路由并将授权承载添加到标题时.....(令牌)我可以访问它。

这是我的前端用户减速器:

export const userLoginReducer = (state = {}, action) => {
  switch (action.type) {
    case USER_LOGIN_REQUEST:
      return { loading: true, isAuthenticated: false };
    case USER_LOGIN_SUCCESS:
      return {
        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;
  }
};

这是我的用户操作:

export const login = (email, password) => async dispatch => {
  try {
    dispatch({
      type: USER_LOGIN_REQUEST,
    });

    const config = {
      headers: {
        'Content-Type': 'application/json',
      },
    };

    const { data } = await axios.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,
    });
  }
};

这是我的登录屏幕:

  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;
  console.log(isAuthenticated);

  useEffect(() => {
    if (isAuthenticated) {
      history.push(redirect);
    }

    if (error) {
      console.log(error);
    }
  }, [isAuthenticated, history, redirect, error]);

  const submitHandler = e => {
    e.preventDefault();
    dispatch(login(email, password));
  };

我在这里停留了大约 2 天,试图完成这个。请有人帮助我:)

【问题讨论】:

    标签: node.js reactjs redux jwt mern


    【解决方案1】:

    当您在 cookie 中设置 jwt 令牌时,您可以在发出请求时从那里读取它。您可以通过在您的 axios 配置对象中添加 withCredentials: true 来使用 axios 自动发送 cookie,例如:

    axios({
     withCredentials: true
    })
    

    在服务器端,您可以通过查看req.cookies 对象来获取 jwt cookie 值,例如:

    let token;
    if (req.cookies.jwt) {
      token = req.cookies.jwt;
    }
    

    【讨论】:

    • 我不知道为什么会这样,但它可以“让令牌;如果(req.cookies.jwt){令牌= req.cookies.jwt;}”现在当我有cookie时,我可以访问受保护的路线,当我从存储中删除 cookie 或注销时,我不能。那很好。现在我想知道如何让用户保持登录状态。登录时我在标题中显示用户名,这没关系,但是当我刷新页面时,我的用户消失了并得到错误 user.name is undefind
    • 要了解 cookie 的工作原理,您可以查看expressjs.com/en/resources/middleware/cookie-parser.html。对于刷新页面问题,我认为有另一条路线来检查用户会话,比如让控制器验证 jwt 令牌并将用户信息作为名称返回,而在前端你可以在等待时处于加载状态用于用户会话检查。如果您使用的是反应路由器,这可以帮助您reactrouter.com/web/example/auth-workflow
    • 当我登录并刷新您发送给我的链接上的页面(右侧输出)时,同一用户丢失了
    猜你喜欢
    • 2019-06-04
    • 2021-08-17
    • 2021-03-10
    • 2018-01-20
    • 2016-12-13
    • 2018-11-01
    • 2017-10-21
    • 2021-07-22
    • 2018-07-01
    相关资源
    最近更新 更多