1

我正在为 Swift 中的基本身份验证而苦苦挣扎。

我有一个通过 SSL 和基本身份验证的 Rest 后端服务。我的 Objective-C 客户端代码运行良好,但相应的 Swift 代码由于身份验证失败而无法运行。

这是斯威夫特代码:

let sUrl = "HTTPS://localhost:8443/Test_1/rest/Service/returnInfo"
let url: URL = URL(string: sUrl)!
let request: URLRequest = URLRequest(url: url);
let session: URLSession = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue())
let task: URLSessionDataTask = session.dataTask(with: request) { (data, response, inError) in {

   ...
   let httpResponse = response as! HTTPURLResponse
   if (httpResponse.statusCode != 200) {
        let details = [NSLocalizedDescriptionKey: "HTTP Error"]
        let error = NSError(domain:"WS", code:httpResponse.statusCode, userInfo:details)
        completionHandler(nil, error);
        return
   }
   ...
}
task.resume()

委托方法与 Objective-c 中的对应方法非常相似:

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

    guard challenge.previousFailureCount == 0 else {
        challenge.sender?.cancel(challenge)
        // Inform the user that the user name and password are incorrect
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }

    let proposedCredential = URLCredential(user: user!, password: password!, persistence: .none)
    completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, proposedCredential)
}

httpResponse.statusCode 始终为401

委托方法只被调用一次,而在 Objective-c 中对应的方法被调用了两次。

我哪里错了?

更新对应的Objective-c代码:

NSString *sUrl = [NSString stringWithFormat:@"HTTPS://localhost:8443/Test_1/rest/Service/returnInfo"];
NSURL *url = [NSURL URLWithString:sUrl];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *inError) {
    if (inError != nil) {
        completionHandler(0, inError);
        return;
    }
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    if (httpResponse.statusCode != 200) {
        NSDictionary *details = @{NSLocalizedDescriptionKey:@"HTTP Error"};
        NSError *error = [NSError errorWithDomain:@"WS" code:httpResponse.statusCode userInfo:details];
        completionHandler(0, error);
        return;
    }
    NSError *jsonError;
    NSDictionary *valueAsDictionary = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
    if (jsonError != nil) {
        completionHandler(0, jsonError);
        return;
    }
    if (![valueAsDictionary[@"ret"] boolValue]) {
        NSInteger code = [valueAsDictionary[@"code"] integerValue];
        NSDictionary *details = @{NSLocalizedDescriptionKey:(valueAsDictionary[@"message"]!=nil) ? valueAsDictionary[@"message"] : @""};
        NSError *error = [NSError errorWithDomain:@"WS" code:code userInfo:details];
        completionHandler(0, error);
        return;
    }
    completionHandler(valueAsDictionary[@"value"], nil);
}];
[task resume];

这是委托功能:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {

if ([challenge previousFailureCount] == 0) {
    NSURLCredential *newCredential = [NSURLCredential credentialWithUser:_user password:_password persistence:NSURLCredentialPersistenceNone];
        completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
} else {
    completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}

}
4

3 回答 3

2

我最终设法让它在 Swift 中工作,即使我不知道,因为它以前不能工作。显然,用户和密码必须显式添加到 HTTP 标头中。

let sUrl = "HTTPS://localhost:8443/Test_1/rest/Service/returnInfo"
let url: URL = URL(string: sUrl)!
let request: URLRequest = URLRequest(url: url);

// Changes from here ...

let config = URLSessionConfiguration.default
let userPasswordData = "\(user!):\(password!)".data(using: .utf8)
let base64EncodedCredential = userPasswordData!.base64EncodedString(options: Data.Base64EncodingOptions.init(rawValue: 0))
let authString = "Basic \(base64EncodedCredential)"
config.httpAdditionalHeaders = ["Authorization" : authString]
let session: URLSession = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())

// ... to here

let task: URLSessionDataTask = session.dataTask(with: request) { (data, response, inError) in {

   ...
   let httpResponse = response as! HTTPURLResponse
   if (httpResponse.statusCode != 200) {
      let details = [NSLocalizedDescriptionKey: "HTTP Error"]
      let error = NSError(domain:"WS", code:httpResponse.statusCode, userInfo:details)
      completionHandler(nil, error);
      return
   }
   ...
}
task.resume()
于 2017-03-01T12:45:49.900 回答
1

这段代码在 Swift 3.0.1 中为我工作:

    let login = "username"
    let password = "password"

    let sUrl = NSURL(string: (urlString as NSString) as String)
    let request: URLRequest = URLRequest(url: sUrl as! URL);

    let config = URLSessionConfiguration.default
    let userPasswordData = "\(login):\(password)".data(using: .utf8)
    let base64EncodedCredential = userPasswordData!.base64EncodedString(options: Data.Base64EncodingOptions.init(rawValue: 0))
    let authString = "Basic \(base64EncodedCredential)"
    config.httpAdditionalHeaders = ["Authorization" : authString]
    let session: URLSession = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())

    let task = session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
         print("response \(data)")

        let httpResponse = response as! HTTPURLResponse
        if (httpResponse.statusCode != 200) {
            print(error?.localizedDescription as Any)
            print("Handle Error")
        }
        else{
            do {
                if let jsonResult = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary {
                    print("Synchronous\(jsonResult)")
                }
            } catch let error as NSError {
                print(error.localizedDescription)
            }
        }
    }
        task.resume()
  }
于 2017-04-20T09:38:20.143 回答
0

根据您的问题,这是您的请求(行)实例。

让请求: URLRequest = URLRequest(url: url);

您尚未在此处为您的请求实例设置任何标头参数。请将请求标头和正文参数与您的目标 C 客户端进行比较。

标头参数可能包括 - 内容类型以及其他有用的机密参数,例如 API 密钥。

检查您的目标 C 客户端请求并在您的 swift 代码中设置相同的参数

于 2017-02-28T13:05:20.683 回答