我正在运行这段代码,但得到一个异常。
Session session = null;
Channel channel = null;
JSch jsch = new JSch();
session = jsch.getSession(ftpUserName, ftpHost, ftpPort);
if (session == null) {
throw new Exception("session is null");
}
session.setPassword(ftpPassword);
session.setTimeout(100000);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(); 此代码在本地开发环境中正常工作。然而,当部署在测试环境中时,报告出现异常。测试环境为linux环境,部署中间件为weblogic11,使用jdk为oracle1.6.45。
Exception:
java.lang.IllegalArgumentException: No Configuration was registered that can handle the configuration named com.sun.security.jgss.krb5.initiate
at com.bea.common.security.jdkutils.JAASConfiguration.getAppConfigurationEntry(JAASConfiguration.java:130)
at sun.security.jgss.LoginConfigImpl.getAppConfigurationEntry(LoginConfigImpl.java:139)
at javax.security.auth.login.LoginContext.init(LoginContext.java:243)
at javax.security.auth.login.LoginContext.<init>(LoginContext.java:499)
at sun.security.jgss.GSSUtil.login(GSSUtil.java:244)
at sun.security.jgss.krb5.Krb5Util.getTicket(Krb5Util.java:136)
at sun.security.jgss.krb5.Krb5InitCredential$1.run(Krb5InitCredential.java:328)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.jgss.krb5.Krb5InitCredential.getTgt(Krb5InitCredential.java:325)
at sun.security.jgss.krb5.Krb5InitCredential.getInstance(Krb5InitCredential.java:128)
at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:106)
at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:172)
at sun.security.jgss.GSSManagerImpl.getMechanismContext(GSSManagerImpl.java:209)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:195)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:162)
at com.jcraft.jsch.jgss.GSSContextKrb5.init(GSSContextKrb5.java:129)
at com.jcraft.jsch.UserAuthGSSAPIWithMIC.start(UserAuthGSSAPIWithMIC.java:135)
at com.jcraft.jsch.Session.connect(Session.java:470)
at com.jcraft.jsch.Session.connect(Session.java:183)
at com.sinosoft.FXQ.util.SftpUtils.downloadSftpFile(SftpUtils.java:57)
at com.sinosoft.FXQ.blackList.action.BLBlackListAction.extractBlackList(BLBlackListAction.java:47)
at com.sinosoft.FXQ.task.DownBlackListDataTask.run(DownBlackListDataTask.java:93)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)发布于 2017-10-18 06:27:07
正如@Chris已经回答的那样,JSch默认尝试Kerberos/GSSAPI身份验证。
由于您似乎不希望这样,请将Kerberos/GSSAPI (gssapi-with-mic)从身份验证方法(gssapi-with-mic,publickey,keyboard-interactive,password)的默认JSch列表中删除:
session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");发布于 2017-10-18 04:05:39
解释
您收到的错误消息属于Kerberos,这是一种网络身份验证协议。我看到,在会话配置中,您没有显式地指定身份验证协议。正因为如此,我相信,无论出于什么原因,JSch都默认为Kerberos,即使您提供的是用户名和密码。
修正
我认为解决这一问题的最简单方法是修改setConfig方法,使其包含多种身份验证协议。所有这些都已启用,并且指定了用户名和密码,您可能会在大多数环境中进行身份验证。
Hashtable<String, String> properties = new Hashtable<String, String>();
properties.put("PreferredAuthentications", "gssapi-with-mic,publickey,keyboard-interactive,password");
properties.put("StrictHostKeyChecking", "no");
session.setConfig(properties);还不起作用?
如果上述修改不起作用,请尝试以下操作。
创建一个名为SessionUserInfo.java的新类
public class SessionUserInfo implements UserInfo, UIKeyboardInteractive {
private String password;
private String passPhrase;
public SessionUserInfo() {
password = "";
passPhrase = "";
}
public SessionUserInfo (String password, String passPhrase) {
this.password = password;
this.passPhrase = passPhrase;
}
public String getPassphrase() {
return passPhrase;
}
public String getPassword() {
return password;
}
public boolean promptPassphrase(String phrase) {
return true;
}
public boolean promptPassword(String password) {
return false;
}
public boolean promptYesNo(String bool) {
return true;
}
public void showMessage(String message) {
// Do Nothing
}
}然后按以下方式修改代码。
public static void downloadSftpFile(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort, String ftpPath, String localPath,
String fileName) throws Exception {
Session session = null;
Channel channel = null;
JSch jsch = new JSch();
session = jsch.getSession(ftpUserName, ftpHost, ftpPort);
if (session == null) {
throw new Exception("session is null");
}
session.setPassword(ftpPassword);
session.setTimeout(100000);
Hashtable<String, String> properties = new Hashtable<String, String>();
properties.put("PreferredAuthentications", "gssapi-with-mic,publickey,keyboard-interactive,password");
properties.put("StrictHostKeyChecking", "no");
session.setConfig(properties);
session.setUserInfo(new SessionUserInfo(ftpPassword, null));
session.connect();
channel = session.openChannel("sftp");
channel.connect();
ChannelSftp chSftp = (ChannelSftp) channel;
String ftpFilePath = ftpPath + "/" + fileName;
String localFilePath = localPath + File.separatorChar + fileName;
try {
chSftp.get(ftpFilePath, localPath);
} catch (Exception e) {
e.printStackTrace();
logger.info("download error.");
throw e;
} finally {
chSftp.quit();
channel.disconnect();
session.disconnect();
}
} 没有经过JSch代码(在GitHub BTW上可用),我相信在连接之前向会话添加用户信息POJO与将密码添加到会话本身有不同的效果。
伐木--一个事后的思考
我上面的海报用我贴出的代码解决了问题,解决了原来的海报问题。我在JSch库中查看了会话代码,并发现为JSch启用日志将对您在这里大有帮助。下面是一个启用日志记录的示例。
MyLogger类
Jsch示例中的代码
public static class MyLogger implements com.jcraft.jsch.Logger {
static java.util.Hashtable name=new java.util.Hashtable();
static{
name.put(new Integer(DEBUG), "DEBUG: ");
name.put(new Integer(INFO), "INFO: ");
name.put(new Integer(WARN), "WARN: ");
name.put(new Integer(ERROR), "ERROR: ");
name.put(new Integer(FATAL), "FATAL: ");
}
public boolean isEnabled(int level){
return true;
}
public void log(int level, String message){
System.err.print(name.get(new Integer(level)));
System.err.println(message);
}
}为了启用它,只需修改您的代码
Session session = null;
Channel channel = null;
JSch.setLogger(new MyLogger());
JSch jsch = new JSch();
session = jsch.getSession(ftpUserName, ftpHost, ftpPort);
if (session == null) {
throw new Exception("session is null");
}
session.setPassword(ftpPassword);
session.setTimeout(100000);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(); https://stackoverflow.com/questions/46802110
复制相似问题