2013-03-01 4 views
1

Я пытаюсь использовать Wink RestClient для функционального тестирования на конечной точке службы Rest. Я использую mocks для модульного тестирования, но я бы хотел функционально протестировать его как конечного потребителя.Apache Wink Client - проверка службы REST с использованием формы auth

Я понимаю, что некоторые из них возражают против того, что я называю это конечной точкой REST при использовании auth на основе формы, но это текущая архитектура, которую я имею.

Большинство ресурсов, которые я хочу протестировать, являются защищенными ресурсами, а приложение (работает на Tomcat6) защищено путем проверки подлинности формы. (как в следующем фрагменте web.xml).

До сих пор я пытался сделать первый вызов незащищенного ресурса, чтобы получить заголовок set-cookie, содержащий JSESSIONID, и использовать этот 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/не включает файл cookie jsessionid, а вызов защищенного ресурса говорит о том, что у меня произошел сбой. Полезная нагрузка для вызова функции 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); 

Любых мысли или опыт использования моргания RestClient осуществлять формы-AUTH защищенных ресурсов был бы весьма признателен. Я предполагаю, что я буду использовать другие фреймворки, я слышал об REST-Assured и других, но поскольку приложение использует Wink, и RestClient, кажется, предоставляет мне то, что мне нужно, я решил, что буду придерживаться его.

+0

Оказывается j_security_check реагирует с [# 302 Временно перемещено] - Когда я перехватывать запрос с помощью сниффера и добавление cookie JSESSIONID к этому перенаправленному запросу, все в порядке. Проблема в том, что я не могу понять, что из объекта объекта RestClient объекта (или ресурса или ответа). Переадресация происходит за кулисами. Кто-нибудь знает, как проинструктировать метод Resource.post() STOP при перенаправлении или ClientResponse, чтобы уловить перенаправление? Я еще не вижу пути. – rogodeter

ответ

1

Нашли проблему, и решение

j_security_check отвечал на запрос моей POST (для проверки подлинности), с # 302/редиректа. За этим последовал подмигивание RestClient, но мой файл cookie JSESSIONID не был добавлен к нему. Это вызвало ответ (от перенаправленного URL), содержащий заголовок set-cookie, с новым заголовком. Мои последующие вызовы, в которые я вставил JSESSIONID с первого вызова, не удалось, поскольку этот файл cookie истек. Все, что мне нужно было сделать, - дать RestClient указание НЕ следовать переадресации. Если перенаправление было необходимо, я бы построил его самостоятельно, содержащий соответствующий файл cookie.

Chromium и Firefox переносят куки-файлы с исходного запроса на перенаправленный запрос, поэтому все в порядке.

Вот код, который работал для меня, используя JUnit4, RestClient из проекта Apache Wink (и Джексон 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); 
} 
+0

Учитывая недостаток хороших примеров Apache Wink Client, ваши были наиболее полезными. –