如何使用Jersey Client对启用了JAAS的Web服务器进行身份validation?

我有以下情况:

服务器:Jetty(配置JAAS)

客户端:通过JUnit调用Jersey(通过Maven)

我在Web服务器中设置了JAAS。 我使用客户端部分作为测试。

在服务器端,用户通过具有通过JAAS处理的基本身份validation的表单进行身份validation。 显然,用户需要在能够查看某些页面之前进行身份validation。

我想在尝试访问安全页面之前能够通过Jersey登录。 如何才能做到这一点? 我已经检查过你可以定义一个filter,但我不太清楚如何使用它。 并且 – 一旦用户通过表单登录,我该如何进行(从客户端)到我真正感兴趣的页面?

我真的很感激,如果有人能告诉我如何在客户端与泽西这样做的例子。

我有以下JUnit测试用例方法:

@Test public void testLogin() throws IOException { String URL_LOGIN = "http://localhost:9080/foo/auth.html"; Client client = Client.create(); String username = "me"; String password = "me"; final HTTPBasicAuthFilter authFilter = new HTTPBasicAuthFilter(username, password); client.addFilter(authFilter); client.addFilter(new LoggingFilter()); WebResource webResource = client.resource(URL_LOGIN); // I even tried: // webResource.header("Authorization", "Basic " + "base64encoded_userid:password").type("application/xml"); String page = webResource.post(String.class); System.out.println(page); } 

请注意:

1) http:// localhost:9080 / foo / auth.html是我应该在成功validation后看到的页面。

2)我实际上看到了http:// localhost:9080 / foo / login.html的输出 。

3)显然,通过浏览器,我可以通过login.html页面成功登录。

我在这里似乎错过了什么?

使用Basic auth,您根本不需要访问任何登录页面。 如果服务器配置为使用Basic auth,那么如果在请求中包含基本auth标头,则可以向任何受保护页面发出请求。 泽西filter负责这一点。 因此,如果Basic auth确实是服务器正在使用的,那么您的代码应该可行。

鉴于它不起作用以及它不起作用的方式我很确定服务器配置为使用基于表单的身份validation而不是基本身份validation。

要使基于表单的身份validation起作用,您必须发送包含用户名和密码的表单数据的post请求以登录,然后将从服务器收到的cookie设置为后续请求(因为服务器 – 一旦您登录in – 将设置会话cookie)。

看看login.html的样子 – 它应该包含一个表单。 如果它使用标准servlet格式auth。,那个表单的操作URL应该是“j_security_check”,并且应该有两个表单参数:j_username和j_password。 如果是这种情况,您可以尝试以下内容:

 String URL_LOGIN = "http://localhost:9080/foo/j_security_check"; String URL_DATA = "http://localhost:9080/foo/auth.html"; Client client = Client.create(); // add a filter to set cookies received from the server and to check if login has been triggered client.addFilter(new ClientFilter() { private ArrayList cookies; @Override public ClientResponse handle(ClientRequest request) throws ClientHandlerException { if (cookies != null) { request.getHeaders().put("Cookie", cookies); } ClientResponse response = getNext().handle(request); // copy cookies if (response.getCookies() != null) { if (cookies == null) { cookies = new ArrayList(); } // A simple addAll just for illustration (should probably check for duplicates and expired cookies) cookies.addAll(response.getCookies()); } return response; } }); String username = "me"; String password = "me"; // Login: WebResource webResource = client.resource(URL_LOGIN); com.sun.jersey.api.representation.Form form = new Form(); form.putSingle("j_username", username); form.putSingle("j_password", password); webResource.type("application/x-www-form-urlencoded").post(form); // Get the protected web page: webResource = client.resource(URL_DATA); String response = webResource.get(String.class); 

我没有测试过这个,所以也许会有一些错别字或错误。

我不使用泽西岛,但这本身并不是泽西岛问题。

首先,您必须使用FORM登录或BASIC身份validation; 除非这是一个自定义开发,我怀疑你使用的是“具有基本身份validation的表单”。

如果您使用的是基本身份validation,那么事情非常简单(虽然效率低下):BASIC身份validation是无状态的,您必须在每个请求上发送Authorization:Basic xxxx HTTP头。

如果您正在使用FORM登录,那么事情会更复杂一些。 在每个请求中,您应该发送会话ID(存储在Cookie中或使用URL重写)。 如果您没有发送一个,或者关联的会话无效(因为它已过期),服务器将发送302(重定向)和登录表单。 然后,您应该使用用户名和密码作为参数对表单中指示的URL执行FORM POST。 如果身份validation成功,则服务器将响应发送到原始请求(以及新的会话ID)。 因此,在这种情况下,程序化请求必须能够

  • 1.处理cookie(除非你强制URL重写,这是不可能的)
  • 2.检测他们何时获得302并返回请求的登录表格,并在继续之前填写所需的表格post。

对于任何HTTP调用(AJAX,REST等等)都是如此,请注意,您的服务器使用JAAS或其他身份validation和授权机制这一事实无关紧要:这是一个会话管理问题。

或者,通过拦截呼叫可以获得针对泽西岛的特定解决方案,此处:

如何在服务器上获取泽西日志?

JAAS的自动化:

  String URL_DATA = "http://localhost:9080/foo/auth.html"; Client client = Client.create(); String username = "me"; String password = "me"; client.addFilter(new HTTPBasicAuthFilter(username, password)); // Get the protected web page: WebResource webResource = client.resource(URL_DATA); String response = webResource.get(String.class); System.out.println(response); 

对我来说,这些变化解决了这个问题

 String URL_LOGIN = "http://localhost:9080/foo/j_security_check"; String URL_DATA = "http://localhost:9080/foo/auth.html"; Client client = Client.create(); // add a filter to set cookies received from the server and to check if login has been triggered client.addFilter(new ClientFilter() { private ArrayList cookies; @Override public ClientResponse handle(ClientRequest request) throws ClientHandlerException { if (cookies != null) { request.getHeaders().put("Cookie", cookies); } ClientResponse response = getNext().handle(request); // copy cookies if (response.getCookies() != null) { if (cookies == null) { cookies = new ArrayList(); } // A simple addAll just for illustration (should probably check for duplicates and expired cookies) cookies.addAll(response.getCookies()); } return response; } }); String username = "me"; String password = "me"; // Get the protected web page: (this will make the server know that someone will try to access the protected resource) WebResource webResource = client.resource(URL_DATA); String response = webResource.get(String.class); // Login: webResource = client.resource(URL_LOGIN); com.sun.jersey.api.representation.Form form = new Form(); form.putSingle("j_username", username); form.putSingle("j_password", password); webResource.type("application/x-www-form-urlencoded").post(form); // Get the protected web page: (this time the service will return the data) webResource = client.resource(URL_DATA); response = webResource.get(String.class);