import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthSchemeProvider;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Lookup;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.impl.auth.SPNegoSchemeFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.login.AppConfigurationEntry;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import java.io.IOException;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class RequestKerberosUrlUtils {
public static Logger logger = LoggerFactory.getLogger(RequestKerberosUrlUtils.class);
private String principal;
private String keyTabLocation;
public RequestKerberosUrlUtils() {
}
public RequestKerberosUrlUtils(String principal, String keyTabLocation) {
super();
this.principal = principal;
this.keyTabLocation = keyTabLocation;
}
public RequestKerberosUrlUtils(String principal, String keyTabLocation, boolean isDebug) {
this(principal, keyTabLocation);
if (isDebug) {
System.setProperty("sun.security.spnego.debug", "true");
System.setProperty("sun.security.krb5.debug", "true");
}
}
public RequestKerberosUrlUtils(String principal, String keyTabLocation, String krb5Location, boolean isDebug) {
this(principal, keyTabLocation, isDebug);
System.setProperty("java.security.krb5.conf", krb5Location);
}
//模拟curl使用kerberos认证
private static HttpClient buildSpengoHttpClient() {
HttpClientBuilder builder = HttpClientBuilder.create();
Lookup<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create().
register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build();
builder.setDefaultAuthSchemeRegistry(authSchemeRegistry);
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(null, -1, null), new Credentials() {
@Override
public Principal getUserPrincipal() {
return null;
}
@Override
public String getPassword() {
return null;
}
});
builder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = builder.build();
return httpClient;
}
public HttpResponse callRestUrl(final String url, final String userId) {
logger.warn(String.format("Calling KerberosHttpClient %s %s %s", this.principal, this.keyTabLocation, url));
Configuration config = new Configuration() {
@SuppressWarnings("serial")
@Override
public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
return new AppConfigurationEntry[]{new AppConfigurationEntry("com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, new HashMap<String, Object>() {
{
put("useTicketCache", "false");
put("useKeyTab", "true");
put("keyTab", keyTabLocation);
//Krb5 in GSS API needs to be refreshed so it does not throw the error
//Specified version of key is not available
put("refreshKrb5Config", "true");
put("principal", principal);
put("storeKey", "true");
put("doNotPrompt", "true");
put("isInitiator", "true");
put("debug", "true");
}
})};
}
};
Set<Principal> princ = new HashSet<Principal>(1);
princ.add(new KerberosPrincipal(userId));
Subject sub = new Subject(false, princ, new HashSet<Object>(), new HashSet<Object>());
try {
//认证模块:Krb5Login
LoginContext lc = new LoginContext("Krb5Login", sub, null, config);
lc.login();
Subject serviceSubject = lc.getSubject();
return Subject.doAs(serviceSubject, new PrivilegedAction<HttpResponse>() {
HttpResponse httpResponse = null;
@Override
public HttpResponse run() {
try {
HttpUriRequest request = new HttpGet(url);
HttpClient spnegoHttpClient = buildSpengoHttpClient();
httpResponse = spnegoHttpClient.execute(request);
return httpResponse;
} catch (IOException ioe) {
ioe.printStackTrace();
}
return httpResponse;
}
});
} catch (Exception le) {
le.printStackTrace();
}
return null;
}
}
package com.post;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthSchemeProvider;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Lookup;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.SPNegoSchemeFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.security.Principal;
import java.security.PrivilegedAction;
public class RequestKerberosUrlUtilsClassPath {
public static Logger logger = LoggerFactory.getLogger(RequestKerberosUrlUtilsClassPath.class);
public RequestKerberosUrlUtilsClassPath() {
}
public RequestKerberosUrlUtilsClassPath(boolean isDebug) {
if (isDebug) {
System.setProperty("sun.security.spnego.debug", "true");
System.setProperty("sun.security.krb5.debug", "true");
}
}
public RequestKerberosUrlUtilsClassPath(String krb5Location, boolean isDebug) {
System.setProperty("java.security.krb5.conf", krb5Location);
}
//模拟curl使用kerberos认证
private static HttpClient buildSpengoHttpClient() {
HttpClientBuilder builder = HttpClientBuilder.create();
Lookup<AuthSchemeProvider> authSchemeRegistry = RegistryBuilder.<AuthSchemeProvider>create().
register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true)).build();
builder.setDefaultAuthSchemeRegistry(authSchemeRegistry);
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(null, -1, null), new Credentials() {
@Override
public Principal getUserPrincipal() {
return null;
}
@Override
public String getPassword() {
return null;
}
});
builder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = builder.build();
return httpClient;
}
public HttpResponse get(final String url) {
try {
Subject serviceSubject = getSubject();
return Subject.doAs(serviceSubject, new PrivilegedAction<HttpResponse>() {
HttpResponse httpResponse = null;
@Override
public HttpResponse run() {
try {
HttpUriRequest request = new HttpGet(url);
HttpClient spnegoHttpClient = buildSpengoHttpClient();
httpResponse = spnegoHttpClient.execute(request);
return httpResponse;
} catch (IOException ioe) {
ioe.printStackTrace();
}
return httpResponse;
}
});
} catch (Exception le) {
le.printStackTrace();
}
return null;
}
public HttpResponse post(final String url, final String params) {
try {
Subject serviceSubject = getSubject();
return Subject.doAs(serviceSubject, new PrivilegedAction<HttpResponse>() {
HttpResponse httpResponse = null;
@Override
public HttpResponse run() {
try {
HttpPost httpPost = new HttpPost();
httpPost.setEntity(new StringEntity(params, ContentType.APPLICATION_JSON));
HttpClient spnegoHttpClient = buildSpengoHttpClient();
httpResponse = spnegoHttpClient.execute(httpPost);
return httpResponse;
} catch (IOException ioe) {
ioe.printStackTrace();
}
return httpResponse;
}
});
} catch (Exception le) {
le.printStackTrace();
}
return null;
}
private Subject getSubject() throws LoginException {
String property = System.getProperty("java.security.auth.login.config");
if (null != property) {
Configuration configuration = Configuration.getConfiguration();
//认证模块:Krb5Login
LoginContext lc = new LoginContext("Krb5Login", null, null, configuration);
lc.login();
return lc.getSubject();
}
return new Subject();
}
}
package com.post;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class RequestKerberosUrlUtilsTest {
public static void main(String[] args) {
params();
classPath();
}
public static void params() {
String user = "[email protected]";
String keytab = "D:\\ysstest\\post\\src\\main\\resources\\ws.keytab";
String krb5Location = "D:\\ysstest\\post\\src\\main\\resources\\krb5.conf";
try {
RequestKerberosUrlUtils restTest = new RequestKerberosUrlUtils(user, keytab, krb5Location, false);
// refer to https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html#Open_and_Read_a_File
String url_liststatus = "http://localhost:8083/offset/test";
// location
HttpResponse response = restTest.callRestUrl(url_liststatus, user);
InputStream is = response.getEntity().getContent();
System.out.println("Status code " + response.getStatusLine().getStatusCode());
System.out.println("message is :" + Arrays.deepToString(response.getAllHeaders()));
System.out.println("string:\n" + new String(IOUtils.toByteArray(is), StandardCharsets.UTF_8));
} catch (Exception exp) {
exp.printStackTrace();
}
}
public static void classPath() {
String krb5Location = "D:\\ysstest\\post\\src\\main\\resources\\krb5.conf";
System.setProperty("java.security.auth.login.config", "D:\\ysstest\\post\\src\\main\\resources\\http.conf");
System.setProperty("java.security.krb5.conf", "D:\\ysstest\\post\\src\\main\\resources\\krb5.conf");
try {
RequestKerberosUrlUtilsClassPath restTest = new RequestKerberosUrlUtilsClassPath();
// refer to https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/WebHDFS.html#Open_and_Read_a_File
String url_liststatus = "http://localhost:8083/offset/test";
// location
HttpResponse response = restTest.get(url_liststatus);
InputStream is = response.getEntity().getContent();
System.out.println("Status code " + response.getStatusLine().getStatusCode());
System.out.println("message is :" + Arrays.deepToString(response.getAllHeaders()));
System.out.println("string:\n" + new String(IOUtils.toByteArray(is), StandardCharsets.UTF_8));
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
1、 基于Apache Http Client 实现kerberos认证的高级设置:
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.KerberosCredentials;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import sun.misc.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
/**
* @author
* @description
* @create 2021-07-13 17:20
**/
public class HttpClient {
public static void main(String[] args) throws IOException {
// System.setProperty("java.security.krb5.conf", "D:/apache/business-data/src/main/resources/krb5.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
HttpClientBuilder builder = HttpClientBuilder.create();
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(null, -1, null), new KerberosCredentials(null));
builder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpClient httpClient = builder.build();
HttpUriRequest request = new HttpGet("http://master-55:50070");
CloseableHttpResponse response = httpClient.execute(request);
InputStream is = response.getEntity().getContent();
System.out.println("Status code " + response.getStatusLine().getStatusCode());
System.out.println("message is :" + Arrays.deepToString(response.getAllHeaders()));
System.out.println("string:\n" + new String(IOUtils.readFully(is,-1,false)));
}
}
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.KerberosCredentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import sun.misc.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
/**
* @author
* @description
* @create 2021-07-13 17:20
**/
public class HttpClient2 {
public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
// System.setProperty("java.security.krb5.conf", "D:/apache/business-data/src/main/resources/krb5.conf");
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
HttpAsyncClientBuilder builder = HttpAsyncClientBuilder.create();
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(null, -1, null), new KerberosCredentials(null));
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("username", "password"));
builder.setDefaultCredentialsProvider(credentialsProvider);
CloseableHttpAsyncClient httpAsyncClient = builder.build();
httpAsyncClient.start();
HttpUriRequest request = new HttpGet("http://master-55:50070");
Future execute = httpAsyncClient.execute(request, null);
HttpResponse response = execute.get();
InputStream is = response.getEntity().getContent();
System.out.println("Status code " + response.getStatusLine().getStatusCode());
System.out.println("message is :" + Arrays.deepToString(response.getAllHeaders()));
System.out.println("string:\n" + new String(IOUtils.readFully(is, -1, false)));
httpAsyncClient.close();
}
}
2、通过Jaas配置文件来实现
序号 | 配置项 | 说明 |
---|---|---|
1 | sun.security.krb5.principal | 覆盖配置文件中的principal |
2 | {user.home}{file.separator}krb5.keytab | 如果配置文件中没有配置keytab路径时默认位置 |
3 | libdefaults.default_keytab_name | krb5.conf中的默认配置项 |
3、 创建文件http.conf
通过-Djava.security.auth.login.config 传递参数
com.sun.security.jgss.krb5.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
useTicketCache=false
keyTab=" /admin.keytab"
principal="[email protected]";
};
or
com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
useTicketCache=false
keyTab=" /admin.keytab"
principal="[email protected]";
};