如何在使用 Spring 的 POST 请求中将对象保留在会话范围内?

How do I persist objects in the session scope on POST requests with 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());
    }
}

我是不是遗漏了什么或者这是正常现象?

更新 1

当我检查 GET 请求的会话 ID 时,我可以看到它等于存储在我的 cookie 中的 JSESSIONID。我看到每个 POST 请求都有不同的会话 ID。

所以问题是,如何将 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

我发现 JSESSIONID cookie 是 HttpOnly,无法被 JavaScript 读取,这可能是它没有随 POST 请求一起发送的原因吗?导致 servlet 每次都创建一个新会话。

fetch 命令需要“"credentials: 'include'" 设置为真。这允许 http-only cookie 与 post 请求一起发送,因此服务器能够解析当前会话。工作获取代码如下所示:

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);
});