ApacheWink客户端-使用FormAuth测试REST服务

ApacheWink客户端-使用FormAuth测试REST服务,rest,jax-rs,junit4,functional-testing,apache-wink,Rest,Jax Rs,Junit4,Functional Testing,Apache Wink,我试图使用Wink RestClient在Rest服务端点上进行功能测试。我使用mock进行单元测试,但我希望将其作为端点使用者进行功能测试 我知道有些人会反对我在使用基于表单的身份验证时将其称为REST端点,但这是我目前的体系结构 我要测试的大多数资源都是受保护的资源,应用程序(在Tomcat6上运行)受表单身份验证的保护。(如下面的web.xml代码段所示) 到目前为止,我尝试的是对未受保护的资源进行初始调用,以获取包含JSSessionID的set-cookie标头,并在后续请求中使用标头

我试图使用Wink RestClient在Rest服务端点上进行功能测试。我使用mock进行单元测试,但我希望将其作为端点使用者进行功能测试

我知道有些人会反对我在使用基于表单的身份验证时将其称为REST端点,但这是我目前的体系结构

我要测试的大多数资源都是受保护的资源,应用程序(在Tomcat6上运行)受表单身份验证的保护。(如下面的web.xml代码段所示)

到目前为止,我尝试的是对未受保护的资源进行初始调用,以获取包含JSSessionID的set-cookie标头,并在后续请求中使用标头中的JSSessionID(通过resource.cookie()),但这不会产生结果

web.xml

<login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/login.html?failure=true</form-error-page>
    </form-login-config>
</login-config>

如果您有任何使用Wink RestClient来使用form auth保护的资源的想法或经验,我们将不胜感激。我想我会考虑其他框架,我听说过REST Assured和其他框架,但是由于应用程序使用Wink,并且REST客户端似乎为我提供了我所需要的,我想我会坚持使用它。

找到了问题和解决方案

j#u security_check用#302/重定向响应我的POST请求(进行身份验证)。之后是wink RestClient,但我的JSESSIONID cookie没有附加到它。这导致响应(来自重定向的URL)包含一个集cookie头和一个新头。我在随后的调用中插入了第一个调用中的JSESSIONID,但调用失败,因为cookie已过期。我所需要做的就是指示RestClient不要遵循重定向。如果重定向是必要的,我会自己构造它,包含适当的cookie

Chromium和Firefox将cookie从原始请求传送到重定向请求,因此一切正常

下面是一些为我工作的代码,使用JUnit4,来自ApacheWink项目的RestClient(和Jackson ObjectMapper)


发现了问题,找到了解决方案

j#u security_check用#302/重定向响应我的POST请求(进行身份验证)。之后是wink RestClient,但我的JSESSIONID cookie没有附加到它。这导致响应(来自重定向的URL)包含一个集cookie头和一个新头。我在随后的调用中插入了第一个调用中的JSESSIONID,但调用失败,因为cookie已过期。我所需要做的就是指示RestClient不要遵循重定向。如果重定向是必要的,我会自己构造它,包含适当的cookie

Chromium和Firefox将cookie从原始请求传送到重定向请求,因此一切正常

下面是一些为我工作的代码,使用JUnit4,来自ApacheWink项目的RestClient(和Jackson ObjectMapper)


结果是j#u security_check以一个[#302临时移动]响应——当我用嗅探器截获请求并将JSESSIONID cookie附加到重定向请求上时,一切都很好。问题是,我似乎无法从wink RestClient对象(或资源或响应)对象中获得这一点。重定向发生在幕后。有人知道如何指示Resource.post()方法停止重定向,或者指示ClientResponse捕获重定向吗?我还看不出有什么办法。原来j#u security_check的响应是[#302暂时移动]-当我用嗅探器截获请求并将JSESSIONID cookie附加到重定向的请求上时,一切都很好。问题是,我似乎无法从wink RestClient对象(或资源或响应)对象中获得这一点。重定向发生在幕后。有人知道如何指示Resource.post()方法停止重定向,或者指示ClientResponse捕获重定向吗?我还看不出有什么办法。由于缺乏好的Apache Wink客户端示例,您的示例非常有用。由于缺乏好的Apache Wink客户端示例,您的示例非常有用。
ClientConfig config = new ClientConfig();
config.setBypassHostnameVerification(true);
RestClient restClient = new RestClient(config);

Resource unprotectedResource = restClient.resource( BASE_URL + "/");
unprotectedResource.header( "Accept", "*/*" );
ClientResponse clientResponse = unprotectedResource.get();
String response = clientResponse.getEntity(String.class);

// get jSession ID
String jSessionId = clientResponse.getHeaders().get("set-cookie").get(0);
jSessionId = jSessionId.split(";")[0];
System.out.println(jSessionId);

// create a request to login via j_security_check
Resource loginResource = restClient.resource(BASE_URL + "/j_security_check/");
loginResource.accept("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
loginResource.header("referer", "http://localhost:8080/contextroot/");
loginResource.cookie( jSessionId );
loginResource.header("Connection", "keep-alive");
loginResource.header("Content-Type", "application/x-www-form-urlencoded");
loginResource.header("Content-Length", "41");

ClientResponse loginResponse = loginResource.post("j_username=*****&j_password=*************");

/*  the loginResponse, as this point, does not have the jsessionid cookie, my browser client does */

Resource protectedResource = restClient.resource(BASE_URL + "/protected/test/");
systemResource.accept("application/json");
systemResource.cookie( jSessionId );

ClientResponse systemResponse = systemResource.get();
response = clientResponse.getEntity(String.class);
System.out.println(response);
@Test
public void testGenerateZipEntryName() throws JsonGenerationException, JsonMappingException, IOException
{
    final ObjectMapper mapper = new ObjectMapper();

    final String BASE_URL = "http://localhost:8080/rest";

    // Configure the Rest client
    ClientConfig config = new ClientConfig();
    config.proxyHost("localhost");    // helpful when sniffing traffic
    config.proxyPort(50080);          // helpful when sniffing traffic
    config.followRedirects(false);    // This is KEY for form auth
    RestClient restClient = new RestClient(config);


    // Get an unprotected resource -- to get a JSESSIONID
    Resource resource = restClient.resource( BASE_URL + "/");
    resource.header( "Accept", "*/*" );
    ClientResponse response = resource.get();
    // extract the jSession ID, in a brittle and ugly way
    String jSessId = response.getHeaders().get("set-cookie").get(0).split(";")[0].split("=")[1];


    // Get the login resource *j_security_check*
    resource = restClient.resource(BASE_URL + "/j_security_check");
    resource.cookie("j_username_tmp=admin; j_password_tmp=; JSESSIONID=" + jSessId);
    resource.header("Content-Type", "application/x-www-form-urlencoded");
    resource.header("Content-Length", "41");

    // Verify that login resource redirects us
    response = resource.post("j_username=admin&j_password=***********");
    assertTrue( response.getStatusCode() == 302 );


    // Grab a public resource
    resource = restClient.resource(BASE_URL + "/");
    resource.cookie("j_username_tmp=admin; j_password_tmp=; JSESSIONID=" + jSessId);
    response = resource.get();
    // verify status of response
    assertTrue( response.getStatusCode() == 200 );


    // Grab a protected resource
    resource = restClient.resource(BASE_URL + "/rest/system");
    resource.cookie("j_username_tmp=admin; j_password_tmp=; JSESSIONID=" + jSessId);

    // Verify resource returned OK
    response = resource.contentType("application/json").accept("*/*").get();
    assertTrue( response.getStatusCode() == 200 );

    // Deserialize body of protected response into domain object for further testing 
    MyObj myObj = mapper.readValue(response.getEntity(String.class), MyObj.class );
    assertTrue( myObj.customerArchived() == false );
}