JSch登录sftp时发现需要Kerberos身份验证

本问记录使用JSch登录sftps时遇到的Kerberos验证问题并记录了解决方法

项目场景:

项目开发中使用了SFTP,debug调试程序时发现了每次都需要手动输入 Kerberos的口令信息。这就很奇怪了难道每次连接SFTP时候都需要手动输入吗?

日志如下:

2023-06-26 17:26:00.125 [] [http-nio-11005-exec-1] WARN  o.g.j.s.ResourceModelConfigurator - Component of class interface cannot be instantiated and will be ignored.
Kerberos 用户名 [10001874]: 
10001874的 Kerberos 口令: 
2023-06-26 17:26:12.619 [] [http-nio-11005-exec-1] INFO  c.s.s.b.bank.util.impl.SftpUtil - 检测目录[/]
Kerberos 用户名 [10001874]: 10001874的 Kerberos 口令: 
2023-06-26 17:26:22.724 [] [http-nio-11005-exec-1] INFO  c.s.s.b.bank.util.impl.SftpUtil - 检测目录[/202306]
Kerberos 用户名 [10001874]: 10001874的 Kerberos 口令: 
2023-06-26 17:26:37.764 [] [http-nio-11005-exec-1] INFO  c.s.s.b.bank.util.impl.SftpUtil - 检测目录[/batchPhoneDestroyUser/202306]
2023-06-26 17:26:37.770 [] [http-nio-11005-exec-1] INFO  c.s.s.b.bank.util.impl.SftpUtil - Start to upload E:/202306/LN00_20230626_00010.txt to /202306
2023-06-26 17:26:37.773 [] [http-nio-11005-exec-1] INFO  c.s.s.b.bank.util.impl.SftpUtil - Start to upload E:/202306/LN00_20230626_00010.txt to /202306 success
2023-06-26 17:26:50.221 [] [http-nio-11005-exec-2] INFO  c.s.s.b.bank.util.impl.SftpUtil - 检测目录[/batchPhoneDestroyUser]
2023-06-26 17:26:50.225 [] [http-nio-11005-exec-2] INFO  c.s.s.b.bank.util.impl.SftpUtil - 检测目录[/batchPhoneDestroyUser/202306]
2023-06-26 17:26:50.228 [] [http-nio-11005-exec-2] INFO  c.s.s.b.bank.util.impl.SftpUtil - 检测目录[/batchPhoneDestroyUser/202306]
2023-06-26 17:26:50.233 [] [http-nio-11005-exec-2] INFO  c.s.s.b.bank.util.impl.SftpUtil - Start to upload E:/202306/LN00_20230626_00010.txt to /202306
2023-06-26 17:26:50.239 [] [http-nio-11005-exec-2] INFO  c.s.s.b.bank.util.impl.SftpUtil - Start to upload E:/202306/LN00_20230626_00010.txt to /202306 success

原因分析:

当提示输入Kerberos用户名和口令时,如果不输入用户名和口令,那么等一会就连接超时, 如果手工输入回车键,程序也能正常跑通。 从问题现象上看,使用JSch连接sftp时,自动做了kerberos认证。 

Kerberos认证协议:

Kerberos是一种网络认证协议,其设计目标是通过密钥系统为客户机 / 服务器应用程序提供强大的认证服务。使用Kerberos时,一个客户端需要经过三个步骤来获取服务:

  • 认证:客户端向认证服务器发送一条报文,并获取一个含时间戳的Ticket-Granting Ticket(TGT)。

  • 授权:客户端使用TGT向Ticket-Granting Server(TGS)请求一个服务Ticket。

  • 服务请求:客户端向服务器出示服务Ticket,以证实自己的合法性。该服务器提供客户端所需服务,在Hadoop应用中,服务器可以是namenode或jobtracker。

从com.jcraft.jsch.Session 的connect方法我们可以了解到Session通过Jsch读取PreferredAuthentications的值, 然后将值通过逗号分割,然后处理认证

package com.jcraft.jsch;
public class Session implements Runnable{

  public String getConfig(String key){
    Object foo=null;
    if(config!=null){
      foo=config.get(key);
      if(foo instanceof String) return (String)foo;
    }
    //Session获取jsch 的config属性
    foo=jsch.getConfig(key);
    if(foo instanceof String) return (String)foo;
    return null;
  }

 public void connect(int connectTimeout) throws JSchException{

        //略
        //获取PreferredAuthentications配置属性
        //实际上这里是获取jsch 成员config的信息
        String cmethods=getConfig("PreferredAuthentications");
        
        //通过逗号分割字符串
        String[] cmethoda=Util.split(cmethods, ",");
        
        String smethods=null;
        if(!auth){
          smethods=((UserAuthNone)ua).getMethods();
          if(smethods!=null){
            smethods=smethods.toLowerCase();
          }
          else{
            // methods: publickey,password,keyboard-interactive
            //smethods="publickey,password,keyboard-interactive";
            smethods=cmethods;
          }
        }
        
        String[] smethoda=Util.split(smethods, ",");
        int methodi=0;
        
        //循环认证处理
        loop:
        while(true){
            while(!auth &&  cmethoda!=null && methodi<cmethoda.length){
                
            }
        }
    }
}

在查看com.jcraft.jsch.JSch中的getConfig方法实现会发现, PreferredAuthentications信息是存储在内部的一个HashTable表中默认值是"gssapi-with-mic,publickey,keyboard-interactive,password",之前了解到属性值会被逗号分割,然后处理。

package com.jcraft.jsch;
public class JSch{

      static java.util.Hashtable config=new java.util.Hashtable();
      static{
          //...
          config.put("PreferredAuthentications", "gssapi-with-mic,publickey,keyboard-interactive,password");
          //...
      }
      
      
      public static String getConfig(String key){ 
          synchronized(config){
            return (String)(config.get(key));
          } 
     }
  }

  • publickey:基于公共密钥的安全验证方式(public key authentication method),通过生成一组密钥(public key/private key)来实现用户的登录验证。

  • keyboard-interactive:基于键盘交互的验证方式(keyboard interactive authentication method),通过服务器向客户端发送提示信息,然后由客户端根据相应的信息通过手工输入的方式发还给服务器端。

  • password:基于口令的验证方式(password authentication method),通过输入用户名和密码的方式进行远程机器的登录验证。

  • gssapi-with-mic: (Generic Security Services Application Programming Interface with Message Integrity Check)是一种客户端/服务端应用程序编程接口,它提供了一种标准的身份验证机制和消息完整整保护机制, 它使用Kerberos票据进行身份验证,并使用数字签名的消息完整性进行保护,GSSAPI通常与Kerberos秘钥分分系统一起使用,这意味着用户只需使用一个Kerberos身份验证标识符就可以访问多个服务器

可见本问题是PreferredAuthentications默认配置了gssapi-with-mic引起的。 

gssapi-with-mic的身份验证流程

1.客户端通过用户名和口令在Kerberos服务器上获取票证

2.客户端将该票证联通自己的身份验证请求一起发送到服务器

3.服务器使用Kerberos秘钥分发系统来检查接收和拒绝请求

gssapi的数据完整性保护流程

1.客户端向服务器端发送数据

2.客户端使用加密算法对数据加密

3.客户端将哈希值(HMAC)追加到加密数据的末尾

4.服务器使用哈斯算法计算收到的数据和哈希值,然后将其和客户端发送的哈希值进行对比


解决方案:

使用JSch实现sftp连接时设置PreferredAuthentications属性,取消gssapi-with-mic支持后就不会再要求验证Kerberos 口令了

参考代码如下:

@Override
public ChannelSftp create() throws Exception {
    JSch jSch = new JSch();
    Session session = jSch.getSession(username, host, port);
    session.setPassword(password);
    session.setConfig("StrictHostKeyChecking", "no");
    //设置PreferredAuthentications 不使用gssapi-with-mic
    session.setConfig(
            "PreferredAuthentications",
            "publickey,keyboard-interactive,password");
    session.connect();

    ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
    channelSftp.connect();

    return channelSftp;
}

参考资料


上一篇:如何使用SonarQube+ SonarScanner分析项目

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

=PNZ=BeijingL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值