简体   繁体   English

维护应用程序中两个http不同请求之间的会话状态

[英]Maintaining session state across two http different requests in an application

I have a scenario where I want to store session information across multiple sessions in Application # 2. We have two applications deployed on a tomcat server. 我有一个场景,我想在应用程序2中的多个会话之间存储会话信息。我们在tomcat服务器上部署了两个应用程序。 Our use case is as follows: 我们的用例如下:

A. Web Application # 1 makes a HTTP Post request to Application # 2 using a HTTP Rest Client. A. Web应用程序1使用HTTP Rest客户端向应用程序2发出HTTP发布请求。 POST request contains a JSON http request body encapsulating the data to be send to Application # 2. The code block is as follows: POST请求包含一个JSON http请求正文,该正文封装了要发送到Application#2的数据。代码块如下:

RestTemplate template = new RestTemplate();
final SearchCustomer customer = new SearchCustomer();
restTemplate.execute(
    SEND_CUSTOMER_PROFILE, HttpMethod.POST,
    new SearchRequestCallback(searchCustomer), null);

The request callback function is 请求回调函数是

static class SearchRequestCallback implements RequestCallback {


  /**
   * Write a JSON response to the request body.
   */
    @Override
    public void doWithRequest(ClientHttpRequest request) throws IOException {
      HttpHeaders httpHeaders = request.getHeaders();
      List<MediaType> acceptableMediaTypes = new LinkedList<>();
      acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
      httpHeaders.setAccept(acceptableMediaTypes);
      httpHeaders.setContentType(MediaType.APPLICATION_JSON);
      request.getBody().write(
          new Gson().toJson(this.searchCustomer).getBytes(StandardCharsets.UTF_8.displayName()));
    }
  }

The second application has a Spring controller with the following set up 第二个应用程序具有一个Spring控制器,具有以下设置

@Controller
public class SearchCustomerController {

  /**
   * Builds customer profile knowledge graph.
   * 
   * <p>This is invoked as an synchronous request.
   */
  @RequestMapping(value="/searchProfilePayload.go", method=RequestMethod.POST)
  @ResponseStatus(HttpStatus.OK)
  public void constructSearchCustomerProfileKnowledgeGraph(
      @RequestBody final SearchCustomer customer, HttpServletRequest request) {
    UserContext userContext =
        (UserContext) request.getSession().getAttribute("userContext");
    if (userContext == null) {
      // Perform heavy operation to fetch user session.
      userContext = UserContextHelper.getUserContext(request);
      request.getSession("userContext", userContext)
    }
    userContext.setCustomerProfile(customer);
  }
}

When I make a call to another URI within the application # 2 say via browser, I want it done in such as way that the session attributes are retained when making this call. 当我通过浏览器对应用程序2中的另一个URI进行调用时,我希望这样做的方式是在进行此调用时保留会话属性。 Is there a way to do that? 有没有办法做到这一点?

I know about URL rewriting that stores JSESSIONID in the cookie, but I don't think how you can set the value when making a rest call, and using the same JESSIONID to maintain session attributes. 我知道有关在cookie中存储JSESSIONID URL重写的信息,但是我不认为在进行rest调用并使用相同的JESSIONID维护会话属性时如何设置值。

Is there a better way to do this? 有一个更好的方法吗? These have no answers. 这些没有答案。 I have looked at these links, but none seem to answer my question. 我看过这些链接,但似乎没有一个回答我的问题。

HTTP and Sessions HTTP和会话
comparison of ways to maintain state 维持状态的方式比较

jraahhali is spot on. jraahhali上有现货。

Set the cookie header with the value of JSESSIONID=${sessionId} or use it directly in the url as per the URL rewriting link. 按照JSESSIONID = $ {sessionId}的值设置cookie标头,或者根据URL重写链接直接在url中使用它。

First step is to retrieve the JSESSIONID from the initial response (this will depend on how you decide to set the session id - URL or Cookies, lets assume by cookie for now) 第一步是从初始响应中检索JSESSIONID(这取决于您决定如何设置会话ID-URL或Cookies,现在让我们假设是cookie)

@Override
public void doWithRequest(ClientHttpRequest request) throws IOException {
  HttpHeaders httpHeaders = request.getHeaders();
  List<MediaType> acceptableMediaTypes = new LinkedList<>();
  acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
  httpHeaders.setAccept(acceptableMediaTypes);
  httpHeaders.setContentType(MediaType.APPLICATION_JSON);
  request.getBody().write(
      new Gson().toJson(this.searchCustomer).getBytes(StandardCharsets.UTF_8.displayName()));

  ClientHttpResponse response = request.execute();
  String sessionId = response.getHeaders().get(HttpHeaders.SET_COOKIE).split(":")[1].trim(); // I didnt test this, will prolly get a NPE :P
  this.sessionId = sessionId;
}

Then in subsequent requests (ie from the app #1 or a browser or whatever) 然后在随后的请求中(即来自应用程序1或浏览器或其他任何请求)

if (this.sessionId != null && !this.sessionId.equals(""))
  httpHeaders.set(HttpHeaders.COOKIE, "JSESSIONID=" + this.sessionId);

// ...
request.execute();

Note if you really want to use a browser as the other client then I would use the URL rewriting method for ease of use ... 请注意,如果您真的想使用浏览器作为其他客户端,那么我将使用URL重写方法以简化使用...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM