本文已参与「新人创作礼」活动,一起开启掘金创作之路。
Kerberos是一种计算机网络授权协议,用来在非安全网络中,对个人通信以安全的手段进行身份验证。 这个词又指麻省理工学院为这个协议开发的一套计算机软件。软件设计上采用客户端/服务器结构,并且能够相互认证,即客户端和服务器端均可对对方身份进行认证。 可以用于防窃听、防止重放攻击、保护数据完整性等场合,是一种应用对称密钥体制进行密钥管理的系统。
运行
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 = "ws@HENGHE.COM";
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认证的高级设置:
- 看源码说明(通过这个配置可以实现与HttpUrlConnect一样的效果)
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<HttpResponse> 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="admin@HADOOP.COM";
};
or
com.sun.security.jgss.initiate {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
useTicketCache=false
keyTab=" /admin.keytab"
principal="admin@HADOOP.COM";
};