在iPhone上使用HTTPS进行JSON POST请求

11

我有一个托管的WCF服务,并尝试在iPhone应用程序中将其作为JSON POST请求使用。 我打算稍后使用JSON序列化器,但这是我当前的请求:

    NSString *jsonRequest = @"{\"username\":\"user\",\"password\":\"letmein\"}";
    NSLog(@"Request: %@", jsonRequest);

    NSURL *url = [NSURL URLWithString:@"https://mydomain.com/Method/"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];

    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody: requestData];

    [NSURLConnection connectionWithRequest:[request autorelease] delegate:self];

我收到的数据只是打印在控制台上:

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSMutableData *d = [[NSMutableData data] retain];
    [d appendData:data];

    NSString *a = [[NSString alloc] initWithData:d encoding:NSASCIIStringEncoding];

    NSLog(@"Data: %@", a);
}

在这个响应中,我收到了这条消息:

Data: <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Request Error</title>
    <style>
        <!-- I've took this out as there's lots of it and it's not relevant! -->
    </style>
  </head>
  <body>
    <div id="content">
      <p class="heading1">Request Error</p>
      <p xmlns="">The server encountered an error processing the request. Please see the <a rel="help-page" href="https://mydomain.com/Method/help">service help page</a> for constructing valid requests to the service.</p>
    </div>
  </body>
</html>

有人知道为什么会出现这种情况以及我哪里做错了吗?

我已经阅读了关于使用ASIHTTPPost的文章,但是我无法在iOS4上运行演示 :(

谢谢

编辑:

我刚刚使用CharlesProxy来嗅探我从iPhone (Simulator)调用时发生的情况,这是它给我的结果: alt text

我唯一注意到的奇怪事情是它说“此主机未启用SSL代理:请在代理设置中启用,SSL位置”。有人知道这是什么意思吗? (这也发生在我正在工作的Windows客户端中)。

我刚刚在我的Windows客户端上运行了这个程序,唯一不同的是请求和响应文本被加密了。 我是否忘记了某些东西以便使用安全的HTTP连接来执行此操作?

新编辑: 这可以与非HTTPS请求一起使用,例如: http://maps.googleapis.com/maps/api/geocode/json?address=UK&sensor=true。因此,我猜问题出在 iPhone 上正确地通过 SSL 发送POST上?

我还在使用这些方法:

- (void) connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
        forAuthenticationChallenge:challenge];
    }

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

- (void) connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        return YES;
    }
}

这让我走到了这一步。如果我不使用它们,就会收到一个错误消息:

该服务器的证书无效。您可能正在连接到一个假冒“mydomain.com”的服务器,这可能会危及您的机密信息。


如果服务器的日志中有任何有趣的内容,你能看到吗? - willcodejavaforfood
我现在无法访问它们。不过我知道该服务已经设置好并且正在为其他客户提供服务。 - ingh.am
4个回答

12

已解决!

修改后:

[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

至:

[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

你还需要这两个方法:

- (void) connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
        forAuthenticationChallenge:challenge];
    }

    [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}

- (void) connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
    if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        return YES;
    }
}

顺便问一句,你在最后一个方法的最后一行忘记写“return NO;”了吧? - Artem
我不确定,我在一个无返回值的方法中返回了YES。现在我记不清原因了。 - ingh.am
@ing0,你能把这行代码翻译成 Swift 吗?[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; - Qadir Hussain
@QadirHussain 抱歉我没有写过太多的Swift。不过请查看这个答案:https://dev59.com/52Af5IYBdhLWcg3wwkwV#24321320 - ingh.am

3

我完全不了解Objective C,但建议您将"Accept"头部设置为application/json而非application/jsonrequest


之前试过了。不管怎样应该是这样的吗?我刚刚又试了一遍,但仍然得到相同的响应!:( - ingh.am
1
application/json 是 JSON 数据的正确 MIME 类型。请参阅 https://dev59.com/cXRB5IYBdhLWcg3w4bKv - Jon
你确定你的 web service 接受 url-encoded 格式的数据并以 json 格式响应吗?如果你执行 curl 命令并在 obj-C 中编写相同的代码,那么很容易找出问题所在。 - Chaitanya
不幸的是,我没有编写这个服务。我有一个使用类似过程的.NET应用程序,完全符合我的要求。因此,我知道这不是服务器问题! - ingh.am
比较是相同的,除了加密的请求和响应文本... :( - ingh.am
显示剩余3条评论

0

dic是具有对象和键的NSMutable字典。

baseUrl是您的服务器Web服务URL。

 NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic
                                                       options:NSJSONWritingPrettyPrinted error:nil];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
   NSString *encodedString = [jsonString base64EncodedString];

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@wsName",baseUrl]];
    NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
    [theRequest addValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [theRequest setHTTPMethod:@"POST"];
    [theRequest setValue:encodedString forHTTPHeaderField:@"Data"];

0

变更

NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];

NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接