hadoop_book/common/authenticated.md

105 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 客户端认证
客户端的入口函数为 KerberosAuthenticator.authenticate函数
## 连接HTTP服务端
```java
HttpURLConnection conn = token.openConnection(url, connConfigurator);
conn.setRequestMethod(AUTH_HTTP_METHOD);
conn.connect();
```
## SPNEGO认证
对于普通的HTTP的kerberos认证(SPNEGO)需要现在客户端登录KDC服务。核心代码在函数doSpnegoSequence里面。
首先需要登录KDC服务端
```java
subject = new Subject();
LoginContext login = new LoginContext("", subject,
null, new KerberosConfiguration());
// 登录KDC服务
login.login();
```
下面主要是开始认证的时候的逻辑。核心处理逻辑流程图如下:
![pic](https://pan.zeekling.cn/zeekling/hadoop/common/Hadoop_auth_client_spnego.png)
主要代码逻辑如下。
```java
GSSManager gssManager = GSSManager.getInstance();
// 设置服务端的域名由于是HTTP协议所以当前要求principal的格式为HTTP/HOST_NAME的方式。
String servicePrincipal = KerberosUtil.getServicePrincipal("HTTP",
KerberosAuthenticator.this.url.getHost());
Oid oid = KerberosUtil.NT_GSS_KRB5_PRINCIPAL_OID;
GSSName serviceName = gssManager.createName(servicePrincipal,
oid);
oid = KerberosUtil.GSS_KRB5_MECH_OID;
// 创建获取token的上下文信息。
gssContext = gssManager.createContext(serviceName, oid, null,
GSSContext.DEFAULT_LIFETIME);
gssContext.requestCredDeleg(true);
gssContext.requestMutualAuth(true);
byte[] inToken = new byte[0];
byte[] outToken;
boolean established = false;
// Loop while the context is still not established
while (!established) {
HttpURLConnection conn =
token.openConnection(url, connConfigurator);
// 获取客户端的token。对于第一次的场景inToken为空。
// 对于中间过程需要将服务端给的token传进去校验。
outToken = gssContext.initSecContext(inToken, 0, inToken.length);
if (outToken != null) {
// 将token发送给服务端
sendToken(conn, outToken);
}
if (!gssContext.isEstablished()) {
// 读取服务端发送的token。
inToken = readToken(conn);
} else {
// 认证完成,认证结束
established = true;
}
}
```
## 认证完成/无须认证
如果HTTP服务端返回的是HTTP_OK则认为服务端是不需要认证的或者是已经认证完成了。在已经完成认证的场景下
需要解析Token。
```java
AuthenticatedURL.extractToken(conn, token);
if (isTokenKerberos(token)) {
return;
}
needFallback = true;
```
## 其他自定义
其他自定义认证的场景可以通过指定Authenticator的方式实现具体实现可以自定义主要保证服务端和客户端一致即可。
```java
// 当前主要适用于对认证方式需要扩展的场景。
Authenticator auth = getFallBackAuthenticator();
auth.setConnectionConfigurator(connConfigurator);
auth.authenticate(url, token);
```
# 服务端认证