如何使用Cookie在HttpBuilder中保持会话

在我的实际场景中,我有一个用于AJAX的REST服务。 它为图形呈现数据系列。 我想用groovy出色的HttpBuilder进行测试。 但是,存在一个问题–这些请求仅适用于已经登录的用户。 在这篇文章中,我提出了一个完整的解决方案来维护HttpBuilder请求之间的会话状态。

HttpBuilder中的会话

首先,快速提醒一下会话。 会话是HTTP请求状态的模拟,HTTP请求本质上是无状态的。 登录后,您将收到一个唯一的cookie(一个或多个),该cookie标识您的连续请求。 每次发送请求时,都会发送此cookie。 这样,服务器会识别您并将您与您的会话匹配,该会话将保留在服务器上。 一旦您注销或超时(例如,闲置20分钟后),Cookie就会受到攻击。 下次访问页面时,您将获得一个新的唯一Cookie。

为了使会话在HttpBuilder中保持活动状态,我需要:

  1. 登录到我的Grails应用程序
  2. 收到JSESSIONID cookie作为响应
  3. 存储该cookie并将其与每个后续请求一起发送

我创建了包装HttpBuilder的RestConnector类。 它的主要改进是将收到的Cookie保留在列表中。

package eu.spoonman.connectors.RestConnector

import groovyx.net.http.Method
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import groovyx.net.http.HttpResponseDecorator

class RestConnector {
    private String baseUrl
    private HTTPBuilder httpBuilder
    private List<String> cookies

    RestConnector(String url) {
        this.baseUrl = url
        this.httpBuilder = initializeHttpBuilder()
        this.cookies = []
    }

    public def request(Method method, ContentType contentType, String url, Map<String, Serializable> params) {
        debug("Send $method request to ${this.baseUrl}$url: $params")
        httpBuilder.request(method, contentType) { request ->
            uri.path = url
            uri.query = params
            headers['Cookie'] = cookies.join(';')
        }
    }

    private HTTPBuilder initializeHttpBuilder() {
        def httpBuilder = new HTTPBuilder(baseUrl)

        httpBuilder.handler.success = { HttpResponseDecorator resp, reader ->
            resp.getHeaders('Set-Cookie').each {
                //[Set-Cookie: JSESSIONID=E68D4799D4D6282F0348FDB7E8B88AE9; Path=/frontoffice/; HttpOnly]
                String cookie = it.value.split(';')[0]
                debug("Adding cookie to collection: $cookie")
                cookies.add(cookie)
            }
            debug("Response: ${reader}")
            return reader
        }
        return httpBuilder
    }

    private debug(String message) {
        System.out.println(message) //for Gradle
    }
}

上一课中需要注意的几件事。 构造函数设置基本URL并创建可重用的HttpBuilder实例。 接下来,有一个成功请求的处理程序,用于检查我是否收到任何cookie。 它将收到的cookie添加到列表中。 最后,有一个调用HttpBuilder#requestrequest方法,但是它将cookie添加到HTTP标头中,以便服务器可以将我识别为登录用户。

发送每个请求的cookie是此处的核心部分。 它模拟浏览器的行为并维护会话。

如何使用它?

我将在下面的Spock测试中向您展示如何使用此实用程序类。 这很简单。

首先,我登录到我的应用程序,并确保我收到一个返回的cookie,它等效于登录。然后,我发送一个带有HTTP标头中发送的cookie的请求。 这是一个实现它的Spock测试:

package eu.spoonman.specs.rest

import eu.spoonman.connectors.RestConnector.RestConnector
import groovyx.net.http.ContentType
import groovyx.net.http.Method
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Stepwise

@Stepwise
class RestChartSpec extends Specification {
    @Shared
    RestConnector restConnector

    def setupSpec() {
        restConnector = new RestConnector('http://localhost:8080')
    }

    def "should login as test"() {
        given:
            Map params = [j_username: 'test', j_password: 'test']
        when:
            restConnector.request(Method.POST, ContentType.ANY, '/frontoffice/j_spring_security_check', params)
        then:
            !(restConnector.cookies.empty)
    }

    def "should allow access to chart data series"() {
        given:
            Map params = [days: 14]
        when:
            Map result = restConnector.request(Method.POST, ContentType.JSON, "frontoffice/chart/series", params)
        then:
            result != null
            result.series.size() > 0
    }
}

我使用应用程序的基本URL在setupSpec创建一个新的RestConnector实例。 请注意,它具有@Shared批注,因此可以在测试之间共享。

@Stepwise是此规范的关键注释。 这意味着Spock完全按照定义的顺序执行测试。 我需要确保首先执行登录。 我还需要断言我收到一个cookie,并且列表不为空。 我也可以将此步骤移到setupSpec方法中,但我更喜欢将其作为规范中的第一个测试。 第二次测试始终在登录后执行,因此它将在请求标头中发送cookie。 这正是我想要实现的目标。

参考: 如何通过refaktor博客上的JCG合作伙伴 TomaszKalkosiński的cookie保持 HttpBuilder中的会话

翻译自: https://www.javacodegeeks.com/2013/06/how-to-keep-session-in-httpbuilder-with-cookies.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值