我正在使用Apache olingo开发OData客户端,凭据包含本机字符,对于“授权”标头的Base64编码,应使用UTF-8读取。
第一种方法是Olingo提出的标准建议:
EdmEnabledODataClient client = ODataClientFactory.getEdmEnabledClient(endpointURI, ContentType.JSON);
client.getConfiguration().setHttpClientFactory(new BasicAuthHttpClientFactory(username, password));
但这对我不起作用,因为Olingo读取了用于Base64编码的US-ASCII字符集中的“用户名”和“密码”字节,而我的用户名变成了??? 。
在HTTP客户端级别,有一种方法可以将charset传递给org.apache.http.impl.auth.BasicSchemeFactory,但是我发现没有办法在Olingo级别对其进行自定义。
我的第二次尝试是添加原始标头:
URI searchURI = client.newURIBuilder(endpointURI)
.appendEntitySetSegment(segment)
.top(10)
.addQueryOption(QueryOption.FORMAT, "json")
.build();
ODataEntitySetRequest<ClientEntitySet> request = client.getRetrieveRequestFactory().getEntitySetRequest(searchURI);
String auth = Base64.encodeBase64String(String.format("%s:%s", username, password).getBytes(StandardCharsets.UTF_8));
request.addCustomHeader("Authorization", "Basic "+ auth);
ODataRetrieveResponse<ClientEntitySet> response = request.execute();
但是看来Olingo实际上在request.execute调用下发送了2个HTTP请求。第一个用于数据,它包含我的标头,传递的授权并返回数据-很好。但是,第二个请求是对元数据的请求,没有授权头,并且返回401未经授权。所以最终结果是例外。
我需要一种添加基本身份验证的方法。可以在整个Olingo请求周期中正常工作(多个http请求,并使用UTF-8字符集作为我的凭据。或者,以某种方式禁用元数据调用(如果Olingo始终将其用于响应对象构造,则可能无法实现)
最佳答案
找到了解决方案,但仍对Olingo的推荐方式感兴趣
EdmEnabledODataClient client = ODataClientFactory.getEdmEnabledClient(endpointURI, ContentType.JSON);
final String auth = Base64.encodeBase64String(String.format("%s:%s", username, password).getBytes(StandardCharsets.UTF_8));
client.getConfiguration().setHttpClientFactory(new DefaultHttpClientFactory() {
@SuppressWarnings("deprecation")
@Override
public DefaultHttpClient create(HttpMethod method, URI uri) {
final DefaultHttpClient client = super.create(method, uri);
client.addRequestInterceptor(new HttpRequestInterceptor() {
@Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
request.addHeader("Authorization", "Basic " + auth);
}
});
return client;
}
});