JAVA - запомнить логин пользователя с помощью JAX-RS и JSON Web Token

Я разрабатываю Backend Service, используя JAX-RS и JWT для аутентификации. Но с JWT, когда пользователь входит в систему на новых устройствах, будет сгенерирован новый токен JWT, а предыдущий токен JWT для этого пользователя будет недействительным. Итак, как я могу использовать сеанс или что-то в этом роде, чтобы запомнить логин пользователя на всех устройствах, которые у него есть?

Вот мой код для входа и проверки аутентификации:

    @POST
    @Path("/authenticate")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response authenticateCredentials(@HeaderParam("email") String email,
            @HeaderParam("password") String password, @HeaderParam("accessToken") String accessToken,
            @HeaderParam("type") String loginType)
            throws JsonGenerationException, JsonMappingException, IOException {

        logger.info("Authenticating User Credentials...loginType : " + loginType);

        StatusMessage<Users> statusMessage = null;
        String jweSerialization = null;

        if (loginType == null){
            statusMessage = new StatusMessage();
            statusMessage.setStatus(Status.PRECONDITION_FAILED.getStatusCode());
            statusMessage.setMessage("login type value is missing...");
            return Response.status(Status.PRECONDITION_FAILED.getStatusCode()).entity(statusMessage).build();
        }

        LoginType type = LoginType.valueOf(loginType);

        switch (type) {
        case systems:
            if (email == null){
                statusMessage = new StatusMessage();
                statusMessage.setStatus(Status.PRECONDITION_FAILED.getStatusCode());
                statusMessage.setMessage("email value is missing...");
                return Response.status(Status.PRECONDITION_FAILED.getStatusCode()).entity(statusMessage).build();
            }

            if (password == null){
                statusMessage = new StatusMessage();
                statusMessage.setStatus(Status.PRECONDITION_FAILED.getStatusCode());
                statusMessage.setMessage("password value is missing...");
                return Response.status(Status.PRECONDITION_FAILED.getStatusCode()).entity(statusMessage).build();
            }

            Users user = usersDAO.validate(email, password);
            logger.info("user after validate : " + user);
            if (user == null){
                statusMessage = new StatusMessage();
                statusMessage.setStatus(Status.NOT_FOUND.getStatusCode());
                statusMessage.setMessage("User not found...");
                return Response.status(Status.NOT_FOUND.getStatusCode()).entity(statusMessage).build();
            }
            jweSerialization = getJWEToken(user);
            user.setPassword(null); //not return password and OTP
            user.setOTP(null);
            statusMessage = new StatusMessage<Users>();
            statusMessage.setStatus(Status.OK.getStatusCode());
            statusMessage.setMessage(jweSerialization);
            statusMessage.setData(user);
            logger.info("statusMessage : " + statusMessage);

            return Response.status(Status.OK.getStatusCode()).entity(statusMessage).build();

        case facebook:
            if (email == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.PRECONDITION_FAILED.getStatusCode());
                statusMessage.setMessage("email value is missing...");
                return Response.status(Status.PRECONDITION_FAILED.getStatusCode()).entity(statusMessage).build();
            }
            if (accessToken == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.PRECONDITION_FAILED.getStatusCode());
                statusMessage.setMessage("facebook access token value is missing...");
                return Response.status(Status.PRECONDITION_FAILED.getStatusCode()).entity(statusMessage).build();
            }


            FacebookAuth facebookAuth = new FacebookAuth();
            SocialUser fbUser = facebookAuth.verifySocialUser(accessToken);
            if (fbUser == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.FORBIDDEN.getStatusCode());
                statusMessage.setMessage("Fail while verify facebook user...");
                return Response.status(Status.FORBIDDEN.getStatusCode()).entity(statusMessage).build();
            }

            Users fb_user = usersDAO.validate(fbUser.getEmail(), null);
            if (fb_user == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.NOT_FOUND.getStatusCode());
                statusMessage.setMessage("User not found...");
                return Response.status(Status.NOT_FOUND.getStatusCode()).entity(statusMessage).build();
            }

            jweSerialization = getJWEToken(fb_user);
            fb_user.setPassword(null); //not return password and OTP
            fb_user.setOTP(null);
            statusMessage = new StatusMessage<Users>();
            statusMessage.setStatus(Status.OK.getStatusCode());
            statusMessage.setMessage(jweSerialization);
            statusMessage.setData(fb_user);
            logger.info("statusMessage : " + statusMessage);

            return Response.status(Status.OK.getStatusCode()).entity(statusMessage).build();
        case google:
            if (email == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.PRECONDITION_FAILED.getStatusCode());
                statusMessage.setMessage("email value is missing...");
                return Response.status(Status.PRECONDITION_FAILED.getStatusCode()).entity(statusMessage).build();
            }
            if (accessToken == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.PRECONDITION_FAILED.getStatusCode());
                statusMessage.setMessage("google access token value is missing...");
                return Response.status(Status.PRECONDITION_FAILED.getStatusCode()).entity(statusMessage).build();
            }

            GoogleAuth googleAuth = new GoogleAuth();
            SocialUser ggUser = googleAuth.verifySocialUser(accessToken);
            if (ggUser == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.FORBIDDEN.getStatusCode());
                statusMessage.setMessage("Fail while verify Goolge user...");
                return Response.status(Status.FORBIDDEN.getStatusCode()).entity(statusMessage).build();
            }

            Users gg_User = usersDAO.validate(ggUser.getEmail(), null);
            if (gg_User == null){
                statusMessage = new StatusMessage<Users>();
                statusMessage.setStatus(Status.NOT_FOUND.getStatusCode());
                statusMessage.setMessage("User not found...");
                return Response.status(Status.NOT_FOUND.getStatusCode()).entity(statusMessage).build();
            }

            jweSerialization = getJWEToken(gg_User);
            gg_User.setPassword(null); //not return password and OTP
            gg_User.setOTP(null);
            statusMessage = new StatusMessage<Users>();
            statusMessage.setStatus(Status.OK.getStatusCode());
            statusMessage.setMessage(jweSerialization);
            statusMessage.setData(gg_User);
            logger.info("statusMessage : " + statusMessage);

            return Response.status(Status.OK.getStatusCode()).entity(statusMessage).build();

        default:
            statusMessage = new StatusMessage<Users>();
            statusMessage.setStatus(Status.FORBIDDEN.getStatusCode());
            statusMessage.setMessage("Wrong login type...");
            return Response.status(Status.FORBIDDEN.getStatusCode()).entity(statusMessage).build();
        }
    }
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
1 330
1

Ответы 1

Вы можете получить доступ к ресурсам в JAX-RS, как к сервлету, поскольку JAX-RS фактически построен поверх сервлетов. Итак, да, вы можете получить доступ к сеансу и сохранить информацию о вашем клиенте в сеансах для поддержания состояний (Вот пример).

Однако строго не рекомендуется поддерживать состояния в сеансе веб-служб, как мы это делаем в настройках клиент / сервер. HTTP - это протокол без сохранения состояния, поэтому серверы должны обслуживать каждый запрос изолированно. Стоимость поддержания состояний для каждого из клиентов растет с увеличением количества клиентов и может исчерпать ресурсы вашего сервера. Мы компенсируем эту стоимость в режиме клиент / сервер, чтобы обеспечить лучший пользовательский опыт. Например, сервер может кэшировать часто используемые данные (на основе предыдущих шаблонов запросов) в сеансе, так что время отклика снижается с течением времени за счет минимальных накладных расходов на связь. Напротив, в веб-сервисах серверы фактически обслуживают другие серверы. Таким образом, в этом сценарии компромисс не так полезен, как фактическая настройка клиент / сервер. Потому что для сервера с сервером пропускная способность канала связи не является проблемой. Сервер (действующий как клиент) может предоставить любую необходимую информацию при запросе ресурса на другой сервер.

У вас есть веские основания использовать сеанс. Поскольку вы фактически общаетесь с клиентами, используя JAX-RS, и вам необходимо поддерживать состояния (по крайней мере, для целей аутентификации). Ниже приводится набор рекомендаций, которым вы можете следовать.

После входа в систему с именем пользователя и паролем вы можете предоставить пользователю токен аутентификации и сохранить информацию о пользователе с токеном. Для каждого последующего запроса клиент может отправить токен на сервер, чтобы сервер мог найти идентификатор пользователя. В следующем потоке вы можете увидеть протокол defacto более подробно.

Вы можете рассмотреть возможность использования любого стандартного механизма кэширования (например, JCS, Ehcache, Redis, Memcached и т. д.) Для хранения ваших сеансов, чтобы вы могли в полной мере воспользоваться балансировкой нагрузки экземпляров сервера. Если вы используете сервер приложений JBoss, вам уже доступен Infinispan. Если вы используете сервер Weblogic, вы можете использовать прилагаемый к нему Oracle Coherence. Просто выберите тот, который вам больше всего подходит.

Большое спасибо за ответ, Саззадур. Ваша информация очень-очень полезна для меня. Я буду исследовать, следуя вашему руководству, чтобы найти решение, которое мне подходит. Спасибо

AcidBurn 17.07.2018 06:57

Другие вопросы по теме