HttpClient请求开启Kerberos的服务之二

354 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

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配置文件来实现

序号配置项说明
1sun.security.krb5.principal覆盖配置文件中的principal
2{user.home}{file.separator}krb5.keytab如果配置文件中没有配置keytab路径时默认位置
3libdefaults.default_keytab_namekrb5.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";
};