我正在尝试使用Wink RestClient在Rest服务端点上进行功能测试。我使用模拟进行单元测试,但我想在功能上测试它作为端点消费者。
我理解有些人会反对我在使用基于表单的身份验证时将其称为REST端点,但这是我当前的架构。
我想要测试的大部分资源都是受保护资源,而应用程序(在Tomcat6上运行)受表单身份验证保护。 (如下面的web.xml片段)。
我到目前为止尝试的是初始调用不受保护的资源,获取包含JSESSIONID的set-cookie标头,并在后续标题中使用该JSESSIONID(通过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>
My Wink RestClient代码如下所示。所有响应都是200,但我注意到的两件事是来自/ j_security_check /的调用的响应不包括jsessionid cookie,并且对受保护资源的调用表示我有一个signin失败。调用j_security_check的有效负载直接从截获的上一个成功的浏览器请求中捕获。
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);
使用Wink RestClient执行表单身份验证的资源的任何想法或经验将不胜感激。我想我会接受其他框架,我听说过REST-Assured和其他框架,但由于应用程序使用Wink而RestClient似乎为我提供了我需要的东西,我想我会坚持下去。
答案 0 :(得分:1)
发现问题和解决方案
j_security_check正在响应我的POST请求(进行身份验证),使用#302 / redirect。接下来是wink RestClient,但我的JSESSIONID cookie没有附加到它上面。这导致响应(来自重定向的URL)包含一个带有新标头的set-cookie标头。我在第一次调用中插入JSESSIONID的后续调用失败,因为该cookie已过期。我需要做的只是指示RestClient不遵循重定向。如果重定向是必要的,我会自己构建它,包含适当的cookie。
Chromium和Firefox将cookie从原始请求带到重定向的请求,所以这一切都很好。
这里有一些代码对我有用,使用JUnit4,来自Apache Wink项目的RestClient(以及Jackson ObjectMapper)
@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 );
}