我正在使用 KerberosTemplate 向经过 kerberos 身份验证的 rest API 发出 POST 请求。
我可以在命令行上成功运行不安全的请求,但是当我尝试使用 HTTP 客户端进行安全调用时,它返回 401 未经授权的错误。
我尝试关闭证书检查,因为我们不使用它,并且我还尝试了没有域的用户名,但这也没有影响。
我也尝试过 kerb4j 休息模板,但我遇到了同样的问题。从代码中您还可以看到我正在检查 keytab 文件是否存在。
感谢一些帮助,谢谢。
import ErrorHandlers.KerberosRestTemplateResponseErrorHandler;
import POJOs.PostBody;
import POJOs.PostResponse;
import com.fasterxml.jackson.databind.SerializationFeature;
//import com.kerb4j.client.spring.KerberosRestTemplate;
import org.springframework.security.kerberos.client.KerberosRestTemplate;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
public class KerbTemplate {
public static void main(String[] args) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
PostBody postRequestBody = new PostBody();
postRequestBody.setAggregation("data");
postRequestBody.setEndDate("2119-03-30");
postRequestBody.setStartDate("1900-03-30");
postRequestBody.setMetadata(new String[] {"PARTIAL"});
postRequestBody.setSymbols(new String[] {"requestdata"});
postRequestBody.setModifiedDate("2019-07-20");
postRequestBody.setFirstWeekday("0");
TrustStrategy acceptingTrustStrategy = ((X509Certificate[] chain, String authType) -> true);
SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
String base = System.getProperty("user.dir");
String keytab = base+ File.separator+"src"+File.separator+"main"+File.separator+"resources"+File.separator+"username.keytab";
System.out.println(keytab);
File f = new File(keytab);
if(f.exists() && !f.isDirectory()) {
System.out.println("File exists");
}
KerberosRestTemplate kerberosRestTemplate = new KerberosRestTemplate( keytab,"'username@domain",requestFactory.getHttpClient());
kerberosRestTemplate.setErrorHandler(new KerberosRestTemplateResponseErrorHandler());
MappingJackson2HttpMessageConverter jsonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
jsonHttpMessageConverter.getObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
kerberosRestTemplate.getMessageConverters().add(jsonHttpMessageConverter);
// Add CSRF header if required:
HttpHeaders headers = new HttpHeaders();
headers.set("X-Requested-By", "'username@domain");
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Client-Type","Web");
headers.set("Client-UI-Component","Jim");
HttpEntity<PostBody> postRequest = new HttpEntity<PostBody>(postRequestBody, headers);
PostResponse pr = kerberosRestTemplate.postForObject("https://url.com/1/data/loadList", postRequest, PostResponse.class);
}
}
package ErrorHandlers;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseErrorHandler;
import java.io.IOException;
public class KerberosRestTemplateResponseErrorHandler implements ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse httpResponse) throws IOException {
return (
httpResponse.getStatusCode().series() == HttpStatus.Series.CLIENT_ERROR
|| httpResponse.getStatusCode().series() == HttpStatus.Series.SERVER_ERROR);
}
@Override
public void handleError(ClientHttpResponse httpResponse) throws IOException {
System.out.println("Error Response code " + httpResponse.getRawStatusCode());
System.out.println(httpResponse.getStatusText());
System.out.println(httpResponse.getBody().toString());
}
}
更新了部分日志
540 [main] DEBUG org.apache.http.client.protocol.RequestAddCookies - 已选择 CookieSpec:默认 21:58:30.561 [main] DEBUG org.apache.http.client.protocol.RequestAuthCache - 未在上下文中设置身份验证缓存 21 :58:30.565 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 连接请求:[路由:{s}->myendpoint.com:443][总存活:0;分配的路线:2 条中的 0 条;总分配:0 of 20] 21:58:30.587 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 连接租用:[id: 0][route: {s}->myendpoint.com:443] [存活总数:0;分配的路线:2 条中的 1 条;总分配:1 of 20] 21:58:30.591 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - 打开连接 {s}->myendpoint.com:443 21:58:30.617 [main] DEBUG org .apache.http.impl.conn。
21:58:30.962 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - 执行请求 POST /1/data/loadList HTTP/1.1 21:58:30.963 [main] DEBUG org.apache.http.impl。 execchain.MainClientExec - 目标身份验证状态: UNCHALLENGED 21:58:30.968 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - 代理身份验证状态: UNCHALLENGED 21:58:30.976 [main] DEBUG org.apache.http。 headers - http-outgoing-0 >> POST /1/data/loadList HTTP/1.1 21:58:30.979 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Accept: application/json, application /+json 21:58:30.979 [main] 调试 org.apache.http.headers - http-outgoing-0 >> 客户端类型:Fred 21:58:30.980 [main] 调试 org.apache.http.headers - http-传出-0 >> 内容类型:application/json 21:58:30.981 [main] 调试 org.apache.http.headers - http-outgoing-0 >> Client-UI-Component:Jim 21:58:30.981 [main ] 调试 org.apache.http.headers - http-outgoing-0 >> 内容长度:220 21:58:30.982 [main] 调试 org.apache.http.headers - http-outgoing-0 >> 主机:myendpoint。 com 21:58:30.983 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> 连接:Keep-Alive 21:58:30.983 [main] DEBUG org.apache.http.headers - http-outgoing -0 >> 用户代理:Apache-HttpClient/4.5.9 (Java/1.8.0_212-3-redhat) 21:58:30.983 [main] DEBUG org.apache.http.headers - http-outgoing-0 >>接受编码:gzip,放气 21:58:30.984 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /1/data/loadList HTTP/1.1[\r][\n]" 21:58:30.984 [main] DEBUG org .apache.http.wire - http-outgoing-0 >> “接受:应用程序/json,应用程序/+json[\r][\n]" 21:58:30.984 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "客户端类型:Fred[\r][\n]" 21:58:30.985 [main] 调试 org.apache.http.wire - http-outgoing-0 >> “Content-Type: application/json[\r][\n]” 21:58:30.986 [main] 调试org.apache.http.wire - http-outgoing-0 >> "Client-UI-Component: Jim[\r][\n]" 21:58:30.986 [main] 调试 org.apache.http.wire - http -outgoing-0 >> "Content-Length: 220[\r][\n]" 21:58:30.986 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Host: myendpoint. com[\r][\n]" 21:58:30.988 [main] 调试 org.apache.http.wire - http-outgoing-0 >> "连接:保持活动 [\r][\n]" 21 :58:30.990 [main] 调试 org.apache.http.wire - http-outgoing-0 >> "用户代理:Apache-HttpClient/4.5.9 (Java/1.8.0_212-3-redhat)[\r][\n]" 21:58:30.990 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "接受编码:gzip,deflate[\r ][\n]" 21:58:30.991 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]" 21:58:30.992 [main] DEBUG org .apache.http.wire - http-outgoing-0 >> "{"firstWeekday":"0","metadata":["All"],"endDate":"2119-03-30","modifiedDate": "2019-07-20","聚合":"DAILY","symbols":["symbol1","symbol2"],"startDate":"1900-03-30"}" 21:58:31.043 [main ] 调试 org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 401 [\r][\n]"接受编码:gzip,deflate[\r][\n]" 21:58:30.991 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]" 21:58:30.992 [main] 调试 org.apache.http.wire - http-outgoing-0 >> "{"firstWeekday":"0","metadata":["All"],"endDate":"2119 -03-30","modifiedDate":"2019-07-20","聚合":"DAILY","symbols":["symbol1","symbol2"],"startDate":"1900-03-30 "}" 21:58:31.043 [main] 调试 org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 401 [\r][\n]"接受编码:gzip,deflate[\r][\n]" 21:58:30.991 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]" 21:58:30.992 [main] 调试 org.apache.http.wire - http-outgoing-0 >> "{"firstWeekday":"0","metadata":["All"],"endDate":"2119 -03-30","modifiedDate":"2019-07-20","聚合":"DAILY","symbols":["symbol1","symbol2"],"startDate":"1900-03-30 "}" 21:58:31.043 [main] 调试 org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 401 [\r][\n]"> "{"firstWeekday":"0","元数据":["All"],"endDate":"2119-03-30","modifiedDate":"2019-07-20","聚合":" DAILY","symbols":["symbol1","symbol2"],"startDate":"1900-03-30"}" 21:58:31.043 [main] 调试 org.apache.http.wire - http-outgoing -0 << "HTTP/1.1 401 [\r][\n]"> "{"firstWeekday":"0","元数据":["All"],"endDate":"2119-03-30","modifiedDate":"2019-07-20","聚合":" DAILY","symbols":["symbol1","symbol2"],"startDate":"1900-03-30"}" 21:58:31.043 [main] 调试 org.apache.http.wire - http-outgoing -0 << "HTTP/1.1 401 [\r][\n]"“HTTP/1.1 401 [\r][\n]”“HTTP/1.1 401 [\r][\n]”
nosniff[\r][\n]" 21:58:31.044 [main] 调试 org.apache.http.wire - http-outgoing-0 << "X-XSS-Protection: 1; mode=block[\r][\n]" 21:58:31.044 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Cache-Control: no-cache, no-store, max -age=0, must-revalidate[\r][\n]" 21:58:31.044 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Pragma: no-cache[\r ][\n]" 21:58:31.044 [main] 调试 org.apache.http.wire - http-outgoing-0 << "Expires: 0[\r][\n]" 21:58:31.044 [main ] DEBUG org.apache.http.wire - http-outgoing-0 << "Strict-Transport-Security: max-age=31536000 ; includeSubDomains[\r][\n]" 21:58:31.044 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-Frame-Options: DENY[\r][\n] " 21:58:31.044 [主要] 调试 org.apache.http。
1个;mode=block 21:58:31.051 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Cache-Control: no-cache, no-store, max-age=0, must-revalidate 21: 58:31.051 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Pragma: no-cache 21:58:31.051 [main] DEBUG org.apache.http.headers - http-outgoing-0 < < 过期:0 21:58:31.051 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Strict-Transport-Security: max-age=31536000 ;includeSubDomains 21:58:31.051 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-Frame-Options: DENY 21:58:31.051 [main] DEBUG org.apache.http.headers - http -outgoing-0 << Transfer-Encoding: chunked 21:58:31.051 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Date: Wed, 11 Sep 2019 20:58:31 GMT 21: 58:31.063 [主]调试 org.apache.http.impl.execchain。
21:58:31.096 [main] 调试 org.apache.http.wire - http-outgoing-0 << "0[\r][\n]" 21:58:31.097 [main] 调试 org.apache.http。电线 - http-outgoing-0 << "[\r][\n]" 21:58:31.097 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 连接 [id: 0] [路由: { s}->myendpoint.com:443] 可以无限期地保持活动状态 21:58:31.097 [main] DEBUG org.apache.http.impl.conn.DefaultManagedHttpClientConnection - http-outgoing-0: set socket timeout to 0 21:58 :31.097 [main] DEBUG org.apache.http.impl.conn.PoolingHttpClientConnectionManager - 连接释放:[id: 0][route: {s}->myendpoint.com:443][保持活跃的总数:1;分配的路线:2 条中的 1 条;总分配:1 of 20]
进程以退出代码 0 结束