Kerberos authentication

转自:http://www.sunchangming.com/blog/?p=4137

 

JAAS是Java 认证和授权服务(Java Authentication and Authorization Service)的缩写,是PAM框架的Java实现。

javax.sercurity.auth.Subject是一个不可继承的实体类,它表示单个实体的一组相关信息,与请求的来源相关。

javax.security.auth.Principal是一个接口,表示带有不同类型凭证的标识,基本上来说,Principal可以是任意对象。

JAAS的授权机制主要就是围绕着Subject和Principal。关于JAAS比较详细的参考是这里:http://docs.oracle.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html

几个比较重要的java属性:

java.security.krb5.realm

java.security.krb5.kdc

java.security.krb5.conf

 

 

hadoop的身份认证和授权都是建立在JAAS之上。

hadoop.security.authentication属性有2种值:

simple: Security is disabled。

kerberos: Security is enabled。

org.apache.hadoop.security.UserGroupInformation有一个静态方法:getCurrentUser()。它会返回一个UserGroupInformation类的实例(以下简称UGI)。如果subject为空,或者这个subject中与org.apache.hadoop.security.User对应的Principal为空,那么说明尚未登录过,调用getLoginUser()创建UserGroupInformation的实例。

getLoginUser()的流程:

1.创建LoginContext:

name:如果hadoop.security.authentication等于”kerberos”,那么是“hadoop-user-kerberos”或者“hadoop-keytab-kerberos”,否则是“hadoop-simple”。它的主要作用是作为appName传递给UserGroupInformation.HadoopConfiguration.getAppConfigurationEntry(String appName)方法。

subject:

callbackHandler: 空

Configuration: UserGroupInformation.HadoopConfiguration的实例。

2.login.login();

这个会调用HadoopLoginModule的login()和commit()方法。

HadoopLoginModule的login()方法是一个空函数,只打印了一行调试日志 LOG.debug("hadoop login");

commit()方法负责把Principal添加到Subject中。

此时一个首要问题是username是什么?

在使用了kerberos的情况下,从javax.security.auth.kerberos.KerberosPrincipal的实例获取username。

在未使用kerberos的情况下,优先读取HADOOP_USER_NAME这个系统环境变量,如果不为空,那么拿它作username。否则,读取HADOOP_USER_NAME这个java环境变量。否则,从com.sun.security.auth.NTUserPrincipal或者com.sun.security.auth.UnixPrincipal的实例获取username。

如果以上尝试都失败,那么抛出异常LoginException("Can’t find user name")。

最终拿username构造org.apache.hadoop.security.User的实例添加到Subject中。

 

测试登录:

HADOOP_JAAS_DEBUG=true HADOOP_ROOT_LOGGER=DEBUG,console  bin/hadoop  org.apache.hadoop.security.UserGroupInformation

其中,UGI应该是这样的形式:

UGI: host/xx.xx.xx.com@xx.xx.com (auth:KERBEROS)

如果是下面这样,就说明错了

12/03/28 18:44:52 DEBUG security.Groups: Returning fetched groups for ‘app_admin’ 
Groups: app_admin 
UGI: app_admin (auth:KERBEROS) 
Auth method KERBEROS 
Keytab false

据我观察,目前好像只有hadoop内部的通信可以用keytab。如果想在shell下执行bin/hdfs什么的,还是得手动调用kinit。而且,我不知道hadoop用keytab登录后,把Ticket cache放哪了。好像跟系统默认的不一样。

 

在执行kinit的时候,如果没有root权限,可以用KRB5_CONFIG这个环境变量来指定krb5.conf的位置。这个在kinit的文档中并没有提到,它只提到了KRB5CCNAME和KRBTKFILE。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GSSAPI可以用于实现Kerberos代理,通过代理服务器协助客户端完成Kerberos认证。下面是一个简单的GSSAPI实现Kerberos代理的示例: ```java public class KerberosProxy { public static void main(String[] args) throws Exception { // 创建ServerSocket并监听端口 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Kerberos Proxy started, listening on port 8888..."); // 循环等待客户端连接 while (true) { Socket clientSocket = serverSocket.accept(); System.out.println("Accepted connection from client: " + clientSocket.getInetAddress()); // 创建Kerberos上下文 String serviceName = "HTTP/example.com"; GSSManager manager = GSSManager.getInstance(); GSSName serverName = manager.createName(serviceName, null); GSSContext context = manager.createContext(serverName, null, null, GSSContext.DEFAULT_LIFETIME); // 循环处理客户端请求 byte[] token = new byte[0]; while (!context.isEstablished()) { // 接收客户端请求并转发给服务端 InputStream inputStream = clientSocket.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int len; while ((len = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, len); } byte[] request = outputStream.toByteArray(); outputStream.close(); token = context.initSecContext(request, 0, request.length); if (token != null && token.length > 0) { // 将服务端响应转发给客户端 OutputStream outputStream1 = clientSocket.getOutputStream(); outputStream1.write(token); outputStream1.flush(); } } // 认证成功,获取客户端Subject,并将认证结果发送给客户端 Subject clientSubject = new Subject(); Set<GSSCredential> creds = clientSubject.getPrivateCredentials(GSSCredential.class); GSSCredential credential = creds.iterator().next(); System.out.println("Kerberos authentication successful. Client principal: " + credential.getName()); clientSocket.getOutputStream().write("Kerberos authentication successful.".getBytes()); clientSocket.getOutputStream().flush(); clientSocket.close(); } } } ``` 在上述示例中,我们创建了一个ServerSocket并监听端口,循环等待客户端连接。当客户端连接时,我们创建了一个Kerberos上下文,并循环处理客户端请求。在处理客户端请求时,我们将请求转发给服务端,并将服务端响应转发给客户端。当Kerberos认证成功后,我们获取了客户端Subject,并将认证结果发送给客户端。 需要注意的是,上述示例仅用于演示如何使用GSSAPI实现Kerberos代理,并且还需要进行一些额外的配置,例如指定krb5配置文件等。具体配置和使用方法可以参考Java官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值