cookie только для http + токен: двойная работа? - PullRequest
0 голосов
/ 17 января 2019

Dears,

Я пытаюсь выяснить, как управлять аутентификацией на стороне клиента с помощью файла cookie только для hhtp, отправляемого сервером.

Что я не понимаю, так это то, что интерфейсный файл не может получить доступ только к HTTP-cookie, как интерфейс знает, что пользователь (все еще) аутентифицирован?

Пока единственное решение, если оно найдено, - это отправить клиенту токен, когда аутентификация пройдет успешно. И сохраните этот токен во втором файле cookie, созданном клиентом.

Но мне кажется, что я делаю одну и ту же работу дважды.

1 - управление HTTP-cookie только на стороне сервера, особенно срок действия 2 - также управление на стороне клиента датой истечения срока действия второго cookie.

Как можно избежать этого? Я хотел бы управлять аутентификацией на стороне клиента на основе файла cookie только HTTP-сервера. Если есть файл cookie сервера, продолжайте, иначе перенаправьте на страницу входа.

Я использую узел / экспресс на стороне сервера и реагирую на клиентский. Сеанс хранится в Redis, обе стороны используют HTTPS с использованием сертификатов.

Thks

1 Ответ

0 голосов
/ 18 января 2019

Вам не нужно хранить другой файл cookie.Я полагаю, вы используете аутентификацию на основе токенов на вашей конечной точке, например.JWT.Затем вы думаете об этом сценарии:

  1. Пользователь отправляет имя пользователя / пароль на сервер.
  2. Проверьте учетные данные пользователя и, если они действительны, создайте файл cookie только для http с токеном
    const user = await getUser({ where: { email } });

    const valid = await bcrypt.compare(password, user.password);
    if (!valid) {
      throw new UserInputError('Form Arguments invalid', {
        invalidArgs: {
          'password': 'Invalid password!',
        },
      });
    }

    const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
    /
    res.cookie('token', token, {
      httpOnly: true,
      maxAge: 1000 * 60 * 60 * 24 * 365,
    });

Напишите auth middlerware, чтобы поместить userId в запрос для будущих запросов на доступ к
const jwt = require('jsonwebtoken');
const { AuthenticationError } = require('apollo-server');

module.exports = async function(req, res, next) {
  const { token } = req.cookies;

  if (token) {
    try {
      const { userId } = jwt.verify(token, process.env.APP_SECRET);
      if (userId)
        req.userID = userId;

      if (!userId) return next();
      req.userId = userId;

    } catch (e) {
      console.log(e);
    }
  }

  next();
};
Проверка на каждый запрос userId.Если userId отсутствует, пользователь не вошел в систему
  if (!req.userId) {
     throw new AuthenticationError('Log in!');
   }
Если токен пользователя недействителен / истек срок действия, вы получите AuthenticationError.Поймайте его и перенаправьте на страницу входа. Если ваш пользовательский интерфейс зависит от статуса пользователя, вы можете создать простой в использовании компонент (я использую React), чтобы проверить его.

Пользовательский компонент:

import { Query } from 'react-apollo';
import gql from 'graphql-tag';
import PropTypes from 'prop-types';

const CURRENT_USER_QUERY = gql`
  query CURRENT_USER_QUERY {
    me {
      userId
      firstName
      lastName
      profilePictureUrl
    }
  }
`;

const User = props => (
  <Query {...props} query={CURRENT_USER_QUERY} fetchPolicy={'cache-first'}>
    {payload => props.children(payload)}
  </Query>
);

User.propTypes = {
  children: PropTypes.func.isRequired,
};

export default User;

Если мы получаем me объект с сервера, вы знаете, что вошел в систему пользователь, поэтому вы можете визуализировать в зависимости от статуса пользователя:

import { Link } from 'react-router-dom';
import React from 'react';

<User>
  {({ loading, error, data: { me } }) => {
    if (loading || error || !me) return (
      <Button component={Link} to={'/login'}>Login</Button>
    );
    if(me) return (
      <Button component={Link} to={'/dashboard'}>Go to dashboard</Button>
    )
  }}
</User>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...