使用Apache Mina SSHD我已经在我正在开发的 Android 应用程序中实现了一个 SSH 和 SFTP 服务器,我可以通过 SSH 登录,ls 根目录,cd 到“mnt/sdcard”和 ls - 所有这些工作正常。我也可以得到 su 并做任何我想做的事情。
但是,当我通过 SFTP 连接时,我无法列出大多数目录的内容(包括“/”、“/mnt/sdcard”)。但是,我可以列出“/mnt/sdcard/Download”的内容 - 以及从该目录下载和上传。
似乎某些文件正在停止其轨道中的目录列表 - 例如,在“/mnt/sdcard”中,“TWRP”似乎是问题的原因。这是我在 WinSCP 中得到的:
一般故障(服务器应提供错误描述)。
错误代码:4 来自服务器的错误消息:/mnt/sdcard/TWRP
这是我从 FileZilla 得到的(描述性要少得多):
命令:cd "/mnt/sdcard" 响应:新目录是:"/mnt/sdcard"
命令:ls 状态:列表目录/mnt/sdcard
错误:读取目录。:失败状态:目录列表成功
当试图在 WinSCP 中列出 '/' 中的目录时:
一般故障(服务器应提供错误描述)。
错误代码:4 来自服务器的错误消息:/charger
我已经实现了一个自定义 FileSystemFactory,以便默认传入 SFTP 连接到“/mnt/sdcard/Download”,但我希望能够 SFTP 到任何目录(如果需要,我不介意使用 su)
以下是设置 Android SSH/SFTP 服务器和设置自定义 FileSystemFactory 的相关代码:
//Initialize the server:
final Logger log = LoggerFactory.getLogger(server_service.class);
final SshServer sshd = SshServer.setUpDefaultServer();
final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
final SimplePublicKeyAuthenticator publicKeyAuth = new SimplePublicKeyAuthenticator();
passwordAuth.setUser(username_string);
passwordAuth.setPassword(password_string);
sshd.setPort(port);
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(server_info.getAppContext().getFilesDir().getPath() + "/key.ser"));
sshd.setShellFactory(new PseudoTerminalFactory("/system/bin/sh", "-i"));
sshd.setPasswordAuthenticator(passwordAuth);
sshd.setPublickeyAuthenticator(publicKeyAuth);
sshd.setSubsystemFactories(Arrays.<NamedFactory<Command>>asList(new SftpSubsystem.Factory()));
sshd.setFileSystemFactory(getModifiedNativeFileSystemFactory());
try {
sshd.start();
Log.i("SUCCESS: Server listening on port",Integer.toString(port));
server_info.sshd = sshd;
server_info.log = log;
} catch (Exception ex) {
Log.e("FAILURE: Server start failed", ex.toString());
ex.printStackTrace();
}
}
//Custom FileSystemFactory to change initial root directory on SFTP connection
NativeFileSystemFactory getModifiedNativeFileSystemFactory() {
return new NativeFileSystemFactory() {
@Override
public FileSystemView createFileSystemView(Session session) {
String userName = getUsername(session);
NativeFileSystemView nfsv = new ModifiedNativeFileSystemView(
userName, isCaseInsensitive());
Log.d("Creating a modified NativeFileSystemView for user", nfsv.getUserName());
return nfsv;
}
};
}
//Hook for testing without valid session
String getUsername(Session session) {
return session.getUsername();
}
//Class to return the altered FileSystemView with changed initial directory
class ModifiedNativeFileSystemView extends NativeFileSystemView {
String modifiedRootDir;
public ModifiedNativeFileSystemView(String userName,boolean caseInsensitive) {
super(userName, caseInsensitive);
modifiedRootDir = System.getProperty("user.dir") + File.separator + TARGET_DIR_NAME;
Log.d("Modified NativeFileSystemView created with root directory", modifiedRootDir);
}
@Override
public SshFile getFile(String file) {
return getFile(modifiedRootDir, file);
}
}
编辑:使用“su restorecon -FR /data/media/0”修复 SD 卡访问。 事实证明,在我升级到 Lollipop 后,TWRP 文件夹的权限不好(即使使用“su ls -l”它也不会返回权限,只是说访问被拒绝)。修复这些权限后,我就可以使用 SFTP 列出 sdcard 目录了。
但是,我仍然无法使用 SFTP 列出根目录('/'),但是在 SSH 中使用“su ls -l”执行此操作没有问题(没有 su 将无法工作)。我不认为这是同一个问题 - 我认为这只是我的 SFTP 访问权限不是 su。
谁能告诉我如何让 SFTP 以 su 身份运行?