3. Spring Session Restful 风格API

在Java web应用, Session 会话保持是依靠浏览器传入一个name为SESSON的cookie而实现的, 默认情况下, spring session 也是采用基于这种方式实现的, spring session会解析请求对象中的cookie. 而Restful风格的API, 倡导的时无状态的请求, 也就是说没有会话保持这个概念的, 即没有session的概念. 通常会采取每个请求都传递一个token 来实现认证参数的传递. spring session对Restful 风格的API 也提供了支持, 可以将Token 存入request Header 中

1. spring session 的两种SessionId 解析器

1.1 HeaderHttpSessionIdResolver VS CookieHttpSessionIdResolver

  • CookieHttpSessionIdResolver 和 HeaderHttpSessionIdResolver 均为sessionId 的解析器.
  • CookieHttpSessionIdResolver 会从请求携带的Cookie中解析名为SESSION的Cookie, 然后进行base64为解码, 解码后的值为sessionId; 响应结束时, 将sessionId, 以Set-Cookie:SESSION 存入header, 然后返回给客户端
  • HeaderHttpSessionIdResolver 会从请求头中解析headerName 为x-Auth-Token 或 authenticationInfo 的值, 解析的值即为sessionId; 响应结束后, 将sessionId, 以x-Auth-Token或authenticationInfo 存入header, 然后返回客户端.

1.2 CookieHttpSessionIdResolver 响应头信息

Set-Cookie:SESSION=M2ZlNzA3YjItNmQzZi00YjkzLThmNjItYTI3MzY5ODQzYzJl; Path=/; HttpOnly; SameSite=Lax
Content-Type:text/plain;charset=UTF-8
Content-Length:66
Date:Wed, 17 Apr 2019 06:10:34 GMT

1.3 HeaderHttpSessionIdResolver 响应头信息

X-Auth-Token:b9088e9e-3547-48d2-b60a-245835e5c198
Content-Type:text/plain;charset=UTF-8
Content-Length:66
Date:Wed, 17 Apr 2019 05:52:22 GMT

2. 测试HeaderHttpSessionIdResolver

2.1 配置HeaderHttpSessionIdResolver 解析器

  • 只需要在Spring 容器中注入HeaderHttpSessionIdResolver 解析器即可, 默认注入的是CookieHttpSessionIdResolver
  • HeaderHttpSessionIdResolver 有两个静态方法用于返回解析器实例:
    • xAuthToken: 响应头中通过x-Auth-Token 存放sessionId
    • authenticationInfo: 响应头中通过 Authentication-Info 存放sessionId
@Bean
public HttpSessionIdResolver httpSessionIdResolver() {
    return HeaderHttpSessionIdResolver.xAuthToken();
}

1.2 定义Restful 接口

  • spring 使用RestController 来定于Restful 风格的API
@RestController
@RequestMapping("/rest/hello")
public class RestHelloController {

    @GetMapping("/say.json")
    public String say() {

        String result = "sessionId:" + session.getId() + "\n session.isNew:" + session.isNew();

        return result;
    }
}

3. 测试

3.1 添加依赖

由于浏览器中直接输入网址方式没有办法设置请求头携带x-Auth-Token, 所以笔者使用HttpClient 来进行接口调用

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.6</version>
</dependency>

3.2 测试用例

  • 笔者使用HttpClient 创建两个两个测试用例, test()请求头中不携带参数x-Auth-Token, 另一个请求头中携带x-Auth-Token.
  • x-Auth-Token的值并不是随便设置的, 而是从之前的请求响应中获取的
public class TestHttpUtilRestuful {

    String url = "http://localhost:8180/rest/hello/say.json"; 

    // 请求参数不携带x-Auth-Token, 每次获取的都是新的token
    @Test
    public void test(){

        HttpGet httpGet = new HttpGet(url);

        CloseableHttpClient httpClient = HttpClients.createDefault();

        try {
            CloseableHttpResponse response = httpClient.execute(httpGet);

            System.out.println("\n******************** 响应 ********************");
            String result = EntityUtils.toString(response.getEntity());
            System.out.println("response:" + result);

            // 返回header 信息
            for (Header header : response.getAllHeaders()) {
                System.out.println(header.getName() + ":" + header.getValue());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 请求参数携带接口返回的x-Auth-Token, 则返回session 为已存在token
    @Test
    public void test_with_header(){

        // 使用token 测试
        String xAuthToken = "d075cdbd-87d4-46b8-b52f-a89b86edd25a2";

        HttpGet httpGet = new HttpGet(url);

        CloseableHttpClient httpClient = HttpClients.createDefault();

        try {

            httpGet.setHeader("X-Auth-Token", xAuthToken);

            CloseableHttpResponse response = httpClient.execute(httpGet);

            System.out.println("\n******************** 响应 ********************");
            String result = EntityUtils.toString(response.getEntity());
            System.out.println("response:" + result);

            // 返回header 信息
            for (Header header : response.getAllHeaders()) {
                System.out.println(header.getName() + ":" + header.getValue());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.3 测试结果-未携带header

  • 请求响应头中, 会新增x-Auth-Token, 值为sessionId. 如果不开启Restful支持的话, 响应头中不会包含此参数.
  • 请求Header不携带x-Auth-Token, 则每次请求都会新创建一个session. 响应结果中session.isNew 为true.
response:sessionId:b9088e9e-3547-48d2-b60a-245835e5c198
 session.isNew:true
X-Auth-Token:b9088e9e-3547-48d2-b60a-245835e5c198
Content-Type:text/plain;charset=UTF-8
Content-Length:66
Date:Wed, 17 Apr 2019 05:52:22 GMT

3.4 携带header

  • 将x-Auth-Token 修改为已存在token, 查看输出session.isNew 为false, 证明已不是新的session
  • 如果x-Auth-Token 设置的值不存在, 则spring session 会创建一个新的session, 返回session.isNew 为true
response:sessionId:b9088e9e-3547-48d2-b60a-245835e5c198
session.isNew:false
Content-Type:text/plain;charset=UTF-8
Content-Length:67
Date:Wed, 17 Apr 2019 05:52:58 GMT

你可能感兴趣的:(spring,session)