我已经使用JAX-RS实现了一个REST服务器,它提供了一些使用x-www-form-urlencoded数据并使用XML响应的端点。
我有两个客户端:浏览器中的HTML页面和使用Jersey 2客户端API发送请求的Java客户端。
到目前为止,每件事都很好。现在,当我尝试在服务器和客户端上实现基本身份验证时,事情开始变得棘手。我的第一种方法是使用servlet身份验证工作正常。我在tomcat-users.xml中添加了用户和角色,并在我的服务器的web.xml中启用了基本身份验证。
问题是我必须在javax.servlet.Filter中为此练习实现应用程序级别身份验证。因此,基本上过滤器应拦截对服务器的任何请求,并针对包含有效用户凭证的HashMap检查Base64解码的“授权”标头内容,如果未找到匹配则使用401状态代码进行响应。
令人惊讶的是,这有效。 但只要我保持servlet身份验证运行。一旦我停用servlet级别身份验证,我的应用程序级别身份验证就不再起作用了。我已经检查过我的过滤器没有被忽略,方法是在Hashmap中添加未包含在tomcat-users.xml中的条目,反之亦然。只有具有通过servlet身份验证和我自己的身份验证的凭据才能将其发送到服务器。
调试显示,一旦关闭servlet身份验证,所有请求都会错过Authorization标头。我的猜测是,servlet身份验证会以某种方式弥补我所犯的错误并“修复”我的请求,但我看不出如何。
以下是相关的客户端代码:
HttpAuthenticationFeature httpAuthenticationFeature =
HttpAuthenticationFeature
.basic("ceo", "123456");
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(httpAuthenticationFeature);
javax.ws.rs.client.Client client = ClientBuilder.newClient(clientConfig);
webTarget = client.target("http://" + hostname + ":" + port)
.property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "ceo")
.property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "123456")
.path("RESTService");
Form form = new Form();
form.param("field1", value1);
form.param("field2", value2);
String response = webTarget.path("rest").path("service").path("endpoint")
.request(MediaType.APPLICATION_XML)
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
这是服务器代码:
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements javax.servlet.Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
String authCredentials = req.getHeader(HttpHeaders.AUTHORIZATION);
// authenticate() returns true if credentials are valid
if (authenticate(authCredentials))
chain.doFilter(request, response);
// should return proper 401 response, but apparently does not
// as browser shows no prompt for credentials
else if (response instanceof HttpServletResponse) {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
// ...
}
提前致谢!