Как сохранить объекты в области сеанса в запросах POST с помощью Spring?

Я собираю несколько простых страниц с помощью Spring и хотел бы добавить некоторые данные в объект, который сохраняется для сеанса. Кажется, что это сохраняется для запросов GET, но не для тех, которые сделаны с использованием метода POST.

У меня есть компонент UserData следующим образом:

package com.mycompany.controllers.components;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("session")
public class UserData {

    private boolean loggedIn;

    public UserData() {
        loggedIn = false;
    }

    public boolean isLoggedIn() {
        return loggedIn;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }
}

У меня есть контроллер следующим образом:

package com.mycompany.controllers;
...
@RestController
@Scope("session")
public class DefaultController {

    @Autowired
    UserData userData;

    ...

    @GetMapping("/")
    public ResponseEntity index() {

        printUserData(userData);

        ResponseEntity entity;
        if((entity = authenticate(userData)) != null) {
            return entity;
        }
        ...
    }

    @GetMapping("/setloggedIn")
    public ResponseEntity setLoggedIn() {

        printUserData(userData);

        userData.setLoggedIn(true);
    }

    @PostMapping("/logIn" )
    public ResponseEntity logIn(@RequestBody LogInDTO dto) {

        printUserData(userData);
        ...
        userData.setLoggedIn(true);
    }


    protected static void printUserData(UserData user) {
        if(user== null) {
            LOG.info("UserData is null");
            return;
        }

        LOG.info("UserData logged in: {}", user.isLoggedIn());
    }
}
  • Когда я перехожу к «/», вывод UserData.isLoggedIn() оказывается ложным, как и ожидалось.

  • Когда я делаю почтовый запрос в «/logIn», вывод, как и ожидалось, снова оказывается ложным. После некоторой проверки параметров вызывается метод UserData.setLoggedIn(true), но при переходе к "/" вывод по-прежнему остается ложным.

  • Когда я перехожу к «/setLoggedIn», тогда loggedIn изначально имеет значение false, но это также устанавливает для loggedIn значение true, теперь все запросы к «/» или «/setLoggedIn» приводят к выводу true.

  • Дальнейшие POST-запросы к «/logIn» дают вывод false

Я что-то пропустил или это нормальное поведение?

ОБНОВЛЕНИЕ 1

Когда я проверяю идентификатор сеанса в запросах GET, я вижу, что он равен JSESSIONID, хранящемуся в моих файлах cookie. Я вижу другой идентификатор сеанса для каждого запроса POST.

Итак, вопрос в том, как отправить JSESSIONID вместе с запросом POST. В настоящее время я выполняю запрос следующим образом:

fetch('/logIn', {
    method: 'POST',
    body: JSON.stringify({
        username: txtUsername.value,
        password: txtPassword.value
    }),
    headers : {
        'Content-Type' : 'application/json'
    }
})
.then(result => {
    result.text().then(function(text) {
        if(result.status == 200) {
            location.reload();
        } else {
            alert("Error:\n" + text);
        }
    });
})
.catch(e => {
    console.log(e);
    alert("Error:\n" + e);

});

ОБНОВЛЕНИЕ 2

Я обнаружил, что файл cookie JSESSIONID является HttpOnly и не может быть прочитан JavaScript, и может ли это быть причиной того, что он не отправляется с запросом POST? Заставляет сервлет каждый раз создавать новый сеанс.


person Dan Thomas    schedule 24.09.2017    source источник


Ответы (1)


Команда fetch требует, чтобы для параметра «credentials: 'include» было установлено значение true. Это позволяет отправлять cookie-файлы только для http с почтовыми запросами, поэтому сервер может разрешить текущий сеанс. Рабочий код выборки выглядит следующим образом:

fetch('/logIn', {
  method: 'POST',
  body: JSON.stringify({
    username: txtUsername.value,
    password: txtPassword.value
  }),
  credentials: 'include', // <<< FIX
  headers : {
    'Content-Type' : 'application/json'
  }
})
.then(result => {
  result.text().then(function(text) {
    if(result.status == 200) {
        location.reload();
    } else {
        alert("Error:\n" + text);
    }
  });
})
.catch(e => {
  console.log(e);
  alert("Error:\n" + e);
});
person Dan Thomas    schedule 15.12.2017