How do I ignore an "invalid" SSL certificate in Objective-C? - objective-c

Currently I have:
NSArray* array = [NSArray arrayWithObjects:#"auth.login",#"username",#"password", nil];
NSData* packed_array = [array messagePack];
NSURL* url = [NSURL URLWithString:#"https://192.168.1.149:3790/api/1.0"];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
//Previously the below had changed by hostname.
//[request setValue:#"RPC Server" forHTTPHeaderField:#"Host"];
[request setValue:#"binary/message-pack" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d",[packed_array length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:packed_array];
NSURLResponse *response;
NSError *error;
responseData = [NSMutableData dataWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]];
NSLog(#"response data: %#",[responseData messagePackParse]);
NSLog(#"error: %#",error);
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(#"called canAuthenticateAgainstProtectionSpace");
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(#"called didReceiveAuthenticationChallenge");
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
Which returns "Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid"…"
How should I be implementing the answer from this question and getting data back?

I figured out the problem(s). First I fixed the way I was using the delegate and secondly I changed the host. I edited the code to remove the changing of the host and commented it. I still don't think my question was a duplicate…

If your application flow needs the syncronous request, i answer something similar here Objective-C SSL Synchronous Connection

Related

Cocoa: POST headers/parameters lost when accessing protected resources in a Django site using NSURLConnection

I am trying to access protected resources on a Django site using NSURLConnection , OAuth2 Bearer token and HTTPS. I receive a token, which I then attach either to a GET parameter, POST parameter or header. I can access those URL:s which respond to GET parameter. But when I try to access urls using POST, the server returns me a 403 with a custom error message saying there is no header/post parameter containing the token. I have tried several solutions and HTTP libraries. This method uses AFNetworking, I tried it. We even changed the authorization to accept an alternative header due to warnings that apple does not like the modifying of "Authorization" header. My current code looks like this: (scheme == #"https")
-(void) logOut {
NSString *pget = #"/api/logout/";
NSString *path = [pget stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *absolutePath = [NSString stringWithFormat:#"%#://%#%#", scheme, host, path];
NSURL *url = [NSURL URLWithString:absolutePath];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
NSString *authValue = [NSString stringWithFormat:#"Bearer %#", accessToken];
[urlRequest setValue:authValue forHTTPHeaderField:#"Authorization_Extra"];
[urlRequest setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"content-type"];
[urlRequest setHTTPMethod: #"POST"];
/*
NSString *post = [NSString stringWithFormat:#"access_token_extra=%#", accessToken];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
[urlRequest setValue:postLength forHTTPHeaderField:#"Content-Length"];
[urlRequest setHTTPBody:postData];
*/
NSDictionary* headers = [urlRequest allHTTPHeaderFields];
NSLog(#"headers: %#",headers);
_originalRequest = urlRequest;
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:NO];
[connection start];
}
#pragma mark NSURLConnection Delegate Methods
- (NSURLRequest *)connection: (NSURLConnection *)connection
willSendRequest: (NSURLRequest *)request
redirectResponse: (NSURLResponse *)redirectResponse;
{
if (redirectResponse) {
// we don't use the new request built for us, except for the URL
NSURL *newURL = [request URL];
NSMutableURLRequest *newRequest = [_originalRequest mutableCopy];
[newRequest setURL: newURL];
NSLog(#"New Request headers: %#", [newRequest allHTTPHeaderFields]);
return newRequest;
} else {
return request;
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
NSLog(#"Received response statuscode: %ld", (long)[response statusCode]);
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"connection finished:");
[_delegate handleData:responseData];
}
The _Delegate handleData parses the response, and the custom response is always that I am lacking either the header or post parameter needed for the Bearer token.
It seems that even though I am replacing the request with a mutable copy of the original on every redirect, the headers/parameters still get stripped by NSURLConnection. But why, and how, since I'm sending a copy of the original request every time and I verify by logging that they are there?

NSURLConnection different result when get error

I'm using -[NSURLConnection initWithRequest...] to connect to a server,
and when the server side fails it will respond with an error 400 with a message in the body.
When there is no error, I can get response data in didReceiveData. But when the server returns an error 400, I do not receive any error message in didReceiveData.
However if I use -[NSURLConnection sendSynchronousRequest...] to do the same request
I do get error data from sendSynchronousRequest's return value.
I want to get the error message from didReceiveData, but I dont know why I cannot get it.
What is different between the do, can someone help me?
This way I can get the error message:
NSURL *url = [NSURL URLWithString:#"http://devapi.xxx.com/v1/debug/error"];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:240] autorelease];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
NSLog(#"STATUS:%d", [((NSHTTPURLResponse *)response) statusCode]);
NSLog(#"ERROR:%#", error);
This way I cannot get it:
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://devapi.xxx.com/v1/debug/error"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:240] autorelease];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
urlConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"statusCode:%d",((NSHTTPURLResponse *)response).statusCode);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
NSLog(#"DATA:%#",[NSString stringWithCString:[receivedData bytes] encoding:NSASCIIStringEncoding]);
}
Use this delegate method for handling such errors.
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#" Failed with error---%#",error);
}
I think I found what happen it is,
When I get a error status code in didReceiveResponse,
I immediately try to get data and cancel connection,
But it is wrong,
Because didReceiveData still in receive after didReceiveResponse.
Thanks a lot!

Urban Airship - Send Push with NSURLConnection

I'm working on a simple prototype and need to test sending push notifications from one device to another.
I've emailed Urban Airship to turn on the "Allow Push From Device" for my application - and they did turn it on.
I'm trying to use NSURLConnection to send the push notification from the device.
This is my code:
- (void) test {
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://go.urbanairship.com/api/push"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSDictionary * push = #{#"device_tokens":#[#"<token>"], #"aps":#{#"alert":#"TEST", #"sound":#"default"}};
NSData * pushdata = [NSJSONSerialization dataWithJSONObject:push options:0 error:NULL];
[request setHTTPBody:pushdata];
[NSURLConnection connectionWithRequest:request delegate:self];
}
- (void) connection:(NSURLConnection *) connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *) challenge {
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]) {
NSURLCredential * credential = [[NSURLCredential alloc] initWithUser:#"<app key>" password:#"<app secret>" persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
[credential release];
}
}
- (void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response {
NSHTTPURLResponse * res = (NSHTTPURLResponse *) response;
NSLog(#"response: %#",res);
NSLog(#"res %i\n",res.statusCode);
}
Anyone else done this successfully?
Taking a look at Urban Airship's guide to troubleshooting HTTP status codes, and the documentation for the push API, my guess would be that you need to add a trailing slash to the URL:
[NSURL URLWithString:#"https://go.urbanairship.com/api/push/"]
Example Using the V3 API...
-(void)richPushNotification{
NSDictionary *push = #{
#"audience" : #{
#"device_token" : deviceToken
},
#"device_types" : #[ #"ios" ],
#"notification" : #{
#"ios" : #{
#"alert":Message,
#"sound":#"default",
#"badge":#"auto",
}
},
#"message": #{
#"title": Message,
#"body": #"<html><body><h1>blah blah</h1> etc...</html>",
#"content_type": #"text/html",
#"extra": #{
#"offer_id" : #"608f1f6c-8860-c617-a803-b187b491568e"
}
}
};
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://go.urbanairship.com/api/push/"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/vnd.urbanairship+json; version=3;" forHTTPHeaderField:#"Accept"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", appKey, appMasterSecret];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:push
options:0 // Pass 0 if you don't care about the readability of the generated string
error:NULL];
request.HTTPBody = jsonData;
[NSURLConnection connectionWithRequest:request delegate:self];
}
And The Response:
- (void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response {
NSHTTPURLResponse * res = (NSHTTPURLResponse *) response;
NSLog(#"response: %#",res);
NSLog(#"res %li\n",(long)res.statusCode);
if (res.statusCode == 202) {
//Show Alert Message Sent
}else{
//Handle Error
}
}

Loading stringWithContentsofURL that requires credentials

I am trying to parse an HTML page, but the page requires a username/password to access the data.
How do I pass the credentials to the server so I can load the webpage into my NSData object?
UPDATE for Comments Below
Normally if you are using a web browser, it will pop up a login window for you to type in the credentials. When I execute it in iOS, it doesn't give me anything.
Thanks a lot!
Alan
You can use ASIFormDataRequest. Take a look at it here
NSURL *tempUrl = [NSURL URLWithString:#"http://www.yoursitetoparse.com"];
ASIFormDataRequest *request = [[ASIFormDataRequest alloc] init];
request = [ASIFormDataRequest requestWithURL:tempUrl];
[request setDelegate:self];
[request setRequestMethod:#"POST"];
[request setUsername:#"username"]; //Username
[request setPassword:#"password"]; //Password
[request startAsynchronous];
And it's delegate methods:
-(void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
NSLog(#"Failed %# with code %d and with userInfo %#",[error domain],[error code],[error userInfo]);
}
-(void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"Finished : %#",[theRequest responseString]);
}

How do make Json request to server?

I'm doing an application that should work with the server.
Need to be authorized on the server through the program using the username and password.
I need to make a request to the server with the line:
{"login": "mad_fashist", "password": "eqeeuq313371", "method": "authentificator"}
The string must be in Json.
In response, I should get a line if authentication fails:
{"validated": "false", "kuid": "", "sid": "", "uid": ""}
And if authentication is passed:
{"validated":"true","kuid":"6","sid":"834fe9b4626502bf9ff23485a408ac40","uid":"69"}
The question is how to send and receive all of the above?
Use SBJson framework. and do smth like:
-(void)requestProjects
{
//I prepare the string
NSString *preparedString=[NSString stringWithFormat:#"%# %#", self.lastDate, self.currentCategory];
NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:preparedString forKey:#"request"];
//Prepare convert to json string
NSString *jsonRequest = [jsonDict JSONRepresentation];
NSLog(#"jsonRequest is %#", jsonRequest);
//Set the URL YOU WILL PROVIDE
NSURL *url = [NSURL URLWithString:#"http:xxxxxxxxxxxxxxxxxxx"];
//PREPARE the request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
//Prepare data which will contain the json request string.
NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];
//Set the propreties of the request
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:jsonRequest forHTTPHeaderField:#"Query-string"];
//set the data prepared
[request setHTTPBody: requestData];
//Initialize the connection with request
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
//Start the connection
[delegate showIndicator];
[connection start];
}
//delegate methods:
//METHODS TO HANßDLE RESPONSE
#pragma mark NSURLConnection delegate methods
//WHen receiving the response
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#" Did receive respone");
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//While receiving the response data
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//When failed just log
[delegate hideIndicator];
NSLog(#"Connection failed!");
NSLog(#"Error %#", error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//When the response data is downloaded
// NSLog(#" Data obtained %#", responseData);
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
// NSLog(#" Response String %#", responseString);
//converted response json string to a simple NSdictionary
//If the response string is really JSONABLE I will have the data u sent me displayed succefully
NSMutableArray *results = [responseString JSONValue];
NSLog(#"Response: %#", results);
/// la la al alal alaa
}
It's your back end who should define how the response in Json will look like
Refer NSJsonSerialization class. Which is newly included in ios5.0. which is the most flexible one for your need. you can access it in apple developer site.
link to NSJSONSerialization