0

对于我的 Mac OS X Cocoa 应用程序,我正在尝试

  • 连接到仅接受用户名/密码凭据的 SFTP 服务器
  • 获取远程目录的内容
  • 上传文件

并发现它非常复杂。

在尝试了 ConnectionKit(几乎没有文档)、NMSSH(同时上传时经常崩溃)、rsync(服务器不支持)、sftp(如果编写脚本需要密钥身份验证,不适用于用户名/密码),我现在回到 ConnectionKit:https ://github.com/karelia/ConnectionKit

但是,我正在努力应对身份验证挑战,因为我不知道如何处理委托方法中的凭据。

  • 我下载并编译了 ConnectionKit(显然是第 2 版)。
  • 我正在尝试按照自述文件指示使用 CK2FileManager(这是正确的方法吗?或者我应该使用libssh2_sftp-Cocoa-wrapper代替吗?……但是我之前在 NMSSH 中遇到了 libssh2 阻塞方法的问题)
  • 我正在成功设置我的连接 URL 和
  • 我的代表的 -didReceiveAuthenticationChallenge 被称为

但这是我挣扎的地方:我知道如何创建一个 NSURLCredential,但是,我不知道如何处理它 =>

- (void)fileManager:(CK2FileManager *)manager
 didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{
  NSURLCredential *credentials = [NSURLCredential 
    credentialWithUser:self.username
    password:[self getPassword]
    persistence:NSURLCredentialPersistenceForSession];

    // what to do now?
    // [manager useCredential:] doesn’t exist, nor is there a manager.connection?
    // ...
}

我已经阅读了标题,我搜索了此列表的档案,但所有答案似乎都已过时。我还搜索了 Google、Bing 和 StackOverflow,发现了一个 2011 年使用 CKFTPConnection 的有前景的示例,它似乎不再包含在当前框架中。

非常感谢任何指向正确方向的指针。


tl;博士

我不知道如何响应 ConnectionKit 的 CK2FileManager authenticationChallenge:见代码示例中的注释

4

2 回答 2

3

对于 CK2:

- (void)listDirectoryAtPath:(NSString *)path
{
    // path is here   @"download"
    NSURL *ftpServer = [NSURL URLWithString:@"sftp://companyname.topLevelDomain"];
    NSURL *directory = [CK2FileManager URLWithPath:path isDirectory:YES hostURL:ftpServer];

    CK2FileManager *fileManager = [[CK2FileManager alloc] init];
    fileManager.delegate = self;

    [fileManager contentsOfDirectoryAtURL:directory
               includingPropertiesForKeys:nil
                                  options:NSDirectoryEnumerationSkipsHiddenFiles
                        completionHandler:^(NSArray *contents, NSError *error) {
                            if (!error) {
                                NSLog(@"%@", contents);
                            } else {
                                NSLog(@"ERROR: %@", error.localizedDescription);
                            }
                        }];

}

而且你必须实现以下协议

- (void)fileManager:(CK2FileManager *)manager operation:(CK2FileOperation *)operation
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(CK2AuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler
{
    if (![challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault]) {
        completionHandler(CK2AuthChallengePerformDefaultHandling, nil);
        return;
    }

    NSString * username = @"<username>";
    NSString * pathToPrivateSSHKey = @"</Users/myNameOnLocalMaschine/.ssh/id_rsa>"

    NSURLCredential *cred = [NSURLCredential ck2_credentialWithUser:username
                                                       publicKeyURL:nil
                                                      privateKeyURL:[NSURL fileURLWithPath:pathToPrivateSSHKey]
                                                           password:nil
                                                        persistence:NSURLCredentialPersistenceForSession];
    completionHandler(CK2AuthChallengeUseCredential, cred);

}

就是这样。

调用-listDirectoryAtPath:,然后您将在内容数组中的完成处理程序块中获得位于给定路径上的所有文件:)

于 2014-01-18T00:36:26.470 回答
1

好的,这很容易,我可以自己发现;仅供参考:[[challenge sender] useCredential:credentials forAuthenticationChallenge:challenge];

很抱歉为我自己的问题奖励自己,但也许这个代码片段有助于填补缺失的文档,这就是我使用 ConnectionKit 连接到我的 SFTP 服务器的方式:

- (void)connectWithCompletionBlock:(void (^)(void))completionBlock {
    if(!self.cFileManager) {
        self.cFileManager = [[CK2FileManager alloc] init];
        self.cFileManager.delegate = self;
    }
    NSURL *sftpServer = [NSURL URLWithString:[@"sftp://" stringByAppendingString:self.server]];
    self.remoteFolder = [CK2FileManager URLWithPath:self.remotePath relativeToURL:sftpServer];
    // try to get the contents of the current directory
    [self.cFileManager contentsOfDirectoryAtURL:self.remoteFolder
        includingPropertiesForKeys:nil
        options:NSDirectoryEnumerationSkipsHiddenFiles
        completionHandler:^(NSArray *contents, NSError *error) 
    {
        NSLog(@"remote folder contents: \n%@", contents);
    // invoke completion block
    completionBlock();
    }];
}



- (void)fileManager:(CK2FileManager *)manager
 didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{
    NSURLCredential *credentials = [NSURLCredential 
      credentialWithUser:self.username
      password:[self getPassword]
      persistence:NSURLCredentialPersistenceForSession];
    [[challenge sender] useCredential:credentials forAuthenticationChallenge:challenge]
}
于 2013-11-15T11:34:40.757 回答