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

时间:2017-09-24 18:04:54

标签: java spring spring-boot spring-session

我正在用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。

  • 对" / logIn"的进一步POST请求输出假

我错过了什么或这是正常行为吗?

更新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每次都创建一个新会话。

1 个答案:

答案 0 :(得分:0)

fetch命令需要“”凭据:'include'“设置为true。这允许使用post请求发送仅http cookie,因此服务器能够解析当前会话。工作获取代码看起来像这样:

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