I am trying to load a secure website in a UIWebView my basic approach is to create a NSURL, the n a NSURLRequest, then a NSURLConnection, then to load the NSURLRequest in the UIWebView. When the website is loaded I receive
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
I respond to the challenge sender with
- (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
But after that I get nothing... it just hangs. I put in break points so I know that
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
is being called. If I wait till I am sure that the NSURLConnection is not going to complete then reload the view no authentication challenge is sent but the view will load. I do not have any control over the server. I am open to using AFNetworking, but only if necessary.
The full listing of source code is provided below:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:
(NSURLAuthenticationChallenge *)challenge
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if ([challenge previousFailureCount] == 0)
{
NSString *username = #"username";
NSString *password = #"passsword";
NSURLCredential * cred = [NSURLCredential credentialWithUser:username
password:password
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
}
else
{
}
}
-(void)updateCard
{
NSURL * url = [NSURL URLWithString:#"https://ssl.letu.edu/applications/chapelattendance/attendance.html"];
NSURLRequest * request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:50.0];
self.webView =[[UIWebView alloc] initWithFrame:self.bounds];
self.webView.delegate = self;
[self.webView loadRequest:request];
self.connection = [[ NSURLConnection alloc]initWithRequest:request delegate:self];
[self.connection start];
}
Where did I go wrong?
You need to first retrieve the "authentication method" the server is requesting for:
[[challenge protectionSpace] authenticationMethod]
These are the authentication methods (which are string constants) which the expression above returns:
NSURLAuthenticationMethodDefault
NSURLAuthenticationMethodHTTPBasic
NSURLAuthenticationMethodHTTPDigest
NSURLAuthenticationMethodHTMLForm
NSURLAuthenticationMethodNegotiate
NSURLAuthenticationMethodNTLM
NSURLAuthenticationMethodClientCertificate
NSURLAuthenticationMethodServerTrust
Then, you have these options:
If you want to provide the credentials for the given authentication method, you invoke
useCredential:forAuthenticationChallenge:
If you don't want to handle that authentication method yourself and want the system try
to authenticate, you may invoke performDefaultHandlingForAuthenticationChallenge:
which may then fail or not, depending whether the system is capable to handle that type
of authentication and whether it can find credentials in well known storages.
If you cant handle that authentication method -- say authentication method
NSURLAuthenticationMethodNTLM for example -- you can skip this protection
space and try another protection space if another one
exists in this authentication challenge. Then you may possibly get an
authentication method NSURLAuthenticationMethodHTTPBasic which you
are capable to handle.
In order to reject the current protection space you send method
rejectProtectionSpaceAndContinueWithChallenge: to the
authentication challenge sender. Then, NSURLConnection will send
once again willSendRequestForAuthenticationChallenge: to your
delegate with another protection space if any further exists.
You may try to continue without providing credentials at all.
Likely, the authentication will fail. You can try it through
sending message continueWithoutCredentialForAuthenticationChallenge:
to the authentication challenge sender.
And finally, you can cancel the request through canceling the
authentication challenge: send cancelAuthenticationChallenge: to
the authentication challenge sender.
Note: NSURLAuthenticationMethodHTTPBasic and NSURLAuthenticationMethodHTTPDigest authentication methods can be handled with the same NSURLCredential object created with +credentialWithUser:password:persistence:
If anyone comes along and has the same problem be sure I want to share the solution I found. Use AFNetworking.
Here is the revised code:
-(void)updateCard
{
if(!self.webView)
{
self.webView =[[UIWebView alloc] initWithFrame:self.bounds];
self.webView.delegate = self;
}
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
NSString *username = #"username";
NSString *password = #"password";
NSURL *url = [NSURL URLWithString:#"https://ssl.letu.edu/"];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL: url];
[client setAuthorizationHeaderWithUsername:username password:password];
NSMutableURLRequest *request = [client requestWithMethod:#"GET" path:#"applications/chapelattendance/attendance.html"
parameters:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
[self.webView loadRequest:request];
}
failure: ^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Could not load chapel attendance");
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
}
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
operation.securityPolicy.allowInvalidCertificates = YES;
You need to send the username and password combination with the http header to authenticate the request while sending the same.
NSData *authData = [#"username:password" dataUsingEncoding:NSASCIIStringEncoding];
NSString *authorization = [NSString stringWithFormat:#"Basic %#", [authData base64Encoding]];
[mutableRequest addValue:authorization forHTTPHeaderField:#"Authorization"];
Related
This issue is all over Stack Overflow and I have spent the past 2 days trying countless combinations of ATP configurations and getting my app to work. I'm going to be thorough with my problem as it appears the tiniest thing can affect how to resolve this.
I have just recently set up an Ubuntu 14 server with SSL and TLS 1.2 enabled. On my server are my server-side scripts which my app depends on. In my app I use a NSMutableURLRequest to request my API from the server like so:
NSString * noteDataString = [NSString stringWithFormat:#"email=%#&password=%#&type=%#", companyEmail, companyPassword, #"login"];
NSData * postData = [noteDataString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString * postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"https://mydomain.me:443/path/to/file.php"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSHTTPURLResponse * urlResponse = nil;
NSError * error = nil;
NSData * responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error];
NSString * result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response Code: %ld", (long)[urlResponse statusCode]);
When I copy the url into Chrome the correct PHP return is shown. When requesting from Xcode 7 on iOS 9 I get this error:
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
I have used countless info.plist settings as seen across similar issues. I have tried disabling the need for forward secrecy, I have tried enabling arbitrary loads, I have tried using the exception domain mydomain.me and its subdomains. The only progress I achieve is an error code -9813 switching to -9802.
I am aware of adding delegate methods for NSURLRequest but these are never called and assumed redundant for solving this problem.
I built a lot of the app off a MAMP server using localhost and http and the requests worked when I enabled arbitrary loads then, so nothing wrong with my plist.
It's mind-boggling onto why I have a special case, and I knew Stack Overflow was the place for such situations!
Thanks, and I hope that this helps many more developers beyond me when solved.
Solution. Thank you everybody in the comments for pointing me in the right direction. The solution was to create an NSObject that handled NSURLRequests for this special case.
Credit to: https://www.cocoanetics.com/2010/12/nsurlconnection-with-self-signed-certificates/
The following is almost a direct copy from the tutorial in the link, but I figured it'd be easier to stay here.
So,
I had to create a new NSObject class with the following code:
BWWebService.h
#import <Foundation/Foundation.h>
#interface BWWebService : NSObject{
NSMutableData *receivedData;
NSURLConnection *connection;
NSStringEncoding encoding;
}
- (id)initWithURL:(NSURL *)url;
#end
BWWebService.m
#import "BWWebService.h"
#implementation BWWebService
- (id)initWithURL:(NSURL *)url{
if (self = [super init]){
NSURLRequest * request = [NSURLRequest requestWithURL:url];
connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
}
return self;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
// Every response could mean a redirect
receivedData = nil;
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)
[response textEncodingName]);
encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
if (!receivedData){
// No store yet, make one
receivedData = [[NSMutableData alloc] initWithData:data];
}else{
// Append to previous chunks
[receivedData appendData:data];
}
}
// All worked
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSString * xml = [[NSString alloc] initWithData:receivedData encoding:encoding];
NSLog(#"%#", xml);
}
// And error occurred
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"Error retrieving data, %#", [error localizedDescription]);
}
// To deal with self-signed certificates
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace{
return [protectionSpace.authenticationMethod
isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]){
// we only trust our own domain
if ([challenge.protectionSpace.host isEqualToString:#"myuntrusteddomain.me"]){
NSURLCredential * credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:credential forAuthenticationChallenge:challenge];
}
}
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
}
#end
And if that wasn't enough, to make the request I used the following in replacement of my original request:
NSURL * url = [NSURL URLWithString:#"https://myuntrusteddomain.me:443/path/to/script.php"];
BWWebService * webService;
webService = [[BWWebService alloc] initWithURL:url];
I know that this does not POST data like the original, but that comes later. I am sure it will be a matter of handling the POST in initWithURL.
Thanks everyone.
Edit: It appears this application of the solution only works with Allows Arbitrary Loads set to YES.
Open Xcode, Command-Shift-2, enter 9813, and you immediately find -9813 = errSSLNoRootCert, which was to be expected since your self signed certificate has no root certificate, while -9802 = errSSLFatalAlert (you really buggered it up).
The problem seems to be that for security reasons, some software doesn't like self signed certificates. This can often be fixed by creating and installing your own root certificate, and having a certificate signed by your own root certificate.
I have a server with a self-signed SSL certificate installed. However, once I call the following method it doesn't get any response. Once I change the URL back to http, it works.
- (void)getAccountInfoWithCompletion:(void (^)(NSDictionary *json_response, NSError *error))completion
{
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:
[NSString stringWithFormat:#"%#/api/account/%d/get_info", BASE_HOST_URL_IP, [self getUserID]]
]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error)
{
if (completion)
{
//completion(#"error", error);
}
} else {
NSString *response_string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *json_object = [NSJSONSerialization JSONObjectWithData:[response_string dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
if (completion)
{
completion(json_object, error);
}
}
}];
}
My reason for the delegate is so I can use the self-signed certificate in my app. The following tutorial is what I was using, but then I realized I couldn't use the delegate with the completionHandler method. I need to keep the completionHandler method though.
http://www.cocoanetics.com/2010/12/nsurlconnection-with-self-signed-certificates/
What could I do in order to receive a response from the SSL site?
In the case you describe, you (pretty much) have to use a delegate.
What's happening here is that sendAsynchronousRequest:queue:completion: uses the default behavior of the URL loading system. The URL loading system sees your self signed certificate, can't verify it, so it can't trust it - and won't connect. You should see the NSError passed in to the completion handler populated with information about the problem.
This is all described in depth in Technote 2232: HTTPS Server Trust Evaluation
To allow your self signed certificate, you can't use sendAsynchronousRequest:queue:completion: unless you have a way to make your self-signed certificate trusted and stored in the keychain - on iOS this is only practical in managed devices. For testing, and ONLY for testing, you can use a private Apple API to alter the default trust behavior.
For production code, you must implement a NSURLConnectionDelegate that handles evaluating the server provided credentials and allows your self-signed certificate. This is also described (at a high level) in Technote 2232. If you do not implement this correctly you may create a security vulnerability in your app - and that would be bad, mmmmmk?
I would not suggest following the guidance of the Cocoanetics post you reference. The material is outdated and of questionable quality. Refer to the documentation for NSURLConnectionDelegate and the mentioned Technote 2232 instead. If you would like more information on transport level security for mobile applications in general, there are plenty of resources available.
If you STILL want to use a self signed certificate, you can implement SSL public key pinning to match the remote (self signed) public key against a known local value stored inside your application. This is much better than attempting to match just the hostname. Some example code to get you started is here
ViewController.h:
#interface ViewController : UIViewController <NSURLSessionDelegate>
#end
ViewController.m:
- (void)getAccountInfoWithCompletion:(void (^)(NSDictionary *json_response, NSError *error))completion
{
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:
[NSString stringWithFormat:#"%#/api/account/%d/get_info", BASE_HOST_URL_IP, [self getUserID]]
]];
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration ephemeralSessionConfiguration];
defaultConfigObject.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
if (error == nil && data != nil)
{
NSString *response_string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *json_object = [NSJSONSerialization JSONObjectWithData:[response_string dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
if (completion)
{
completion(json_object, error);
}
}
}];
[dataTask resume];
}
The new beautiful delegate method which lets us replace NSURLConnection's sendAsynchronousRequest method (which couldn't handle SSL)
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
NSString *host = challenge.protectionSpace.host;
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
if ([host rangeOfString:#"yourHost.net"].location != NSNotFound)
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
}
else
{
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge,nil);
}
}
}
I am trying create a login screen which sends login info sharepoint server and i expect to be able to successfully login.
There are plenty of old examples and libraries which I am not able to use. But after spending hours I found this link to have the crux of all
http://transoceanic.blogspot.com/2011/10/objective-c-basic-http-authorization.html
My code looks like this now:
- (void) startLogin {
NSURL *url = [NSURL URLWithString:#"http://site-url.com"];
NSString *loginString =(NSMutableString*)[NSString stringWithFormat:#"%#:%#",usernameTextField.text,passwordTextField.text];
NSData *encodedLoginData=[loginString dataUsingEncoding:NSASCIIStringEncoding];
NSString *authHeader=[NSString stringWithFormat:#"Basic %#", [encodedLoginData base64Encoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:3.0];
// [request setValue:authHeader forKey:#"Authorization"];
[request setValue:authHeader forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"POST"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
There are three issues:
the commented out line-code doesn't give any error but it crashes on that line(while debugging)
on [request setValue:authHeader forHTTPHeaderField:#"Authorization"]; i am getting error "No visible interface for NSURLRequest declares selector setHTTPHeaderField"
Also, I am getting warning - unused variable "connection" in last line. I am not sure how this whole thing works and any simple example or correction is appreciated.
I would also like to know if there are any other simple methods for basic auth.
UPDATE: Delegate methods
- (void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
// Access has failed two times...
if ([challenge previousFailureCount] > 1)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Authentication Error"
message:#"Too many unsuccessul login attempts."
delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
else
{
// Answer the challenge
NSURLCredential *cred = [[NSURLCredential alloc] initWithUser:#"admin" password:#"password"
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:cred forAuthenticationChallenge:challenge];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"Connection success.");
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Connection failure.");
}
Change NSURLRequest to NSMutableURLRequest to access it's setValue:forHTTPHeaderField method, and add a HOST header as well if it's a shared web host.
At the end, you have to start the connection:
[connection start];
Also, make sure you've set up your NSURLConnectionDelegate delegate methods for the call backs.
With an update to the client's API the HTTPBasicAuthication method has been replace with a OAuth2 Bearer Authorization header.
With the old API I would do the following:
NSURLCredential *credential = [NSURLCredential credentialWithUser:self.account.username
password:self.account.token
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *space = [[NSURLProtectionSpace alloc] initWithHost:kAPIHost
port:443
protocol:NSURLProtectionSpaceHTTPS
realm:#"my-api"
authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
But this will not work with the Bearer header.
Now normally I would just add the header my self by adding it like so:
NSString *authorization = [NSString stringWithFormat:#"Bearer %#",self.account.token];
[urlRequest setValue:authorization forHTTPHeaderField:#"Authorization"];
But the problem with this solutions is that the API redirect most of the calls to other URLs, this has to do with security.
After the NSURLRequest gets redirected the Authorization header is removed from the request and since I'm unable to add the Bearer method to the NSURLCredentialStorage it can't authenticate any more after being redirected.
What would be a good solutions? I can only think to catch the redirect and modify the NSURLRequest so it does include the Bearer header. But how?
Well after much research I found out that I will just have to replace the NSURLRequest when a call is redirected.
Not as nice as I would like it to be, but is does work.
I used AFNetworking and added the redirect block, then check wether the Authorization header is still set if not I create a new NSMutableURLRequest and set all the properties to match the old request (I know I could have just created a mutable copy):
[requestOperation setRedirectResponseBlock:^NSURLRequest *(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse) {
if ([request.allHTTPHeaderFields objectForKey:#"Authorization"] != nil) {
return request;
}
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:request.URL cachePolicy:request.cachePolicy timeoutInterval:request.timeoutInterval];
NSString *authValue = [NSString stringWithFormat:#"Bearer %#", self.account.token];
[urlRequest setValue:authValue forHTTPHeaderField:#"Authorization"];
return urlRequest;
}];
I'm using AFNetworking Library
Find AFHttpClient.m and you have a method
- (void)setAuthorizationHeaderWithToken:(NSString *)token {
[self setDefaultHeader:#"Authorization" value:[NSString stringWithFormat:#"Token token=\"%#\"", token]];
}
replace this method with the following or if you need it for back compatibility keep it an add with a different name and use that name
- (void)setAuthorizationHeaderWithToken:(NSString *)token {
[self setDefaultHeader:#"Authorization" value:[NSString stringWithFormat:#"Bearer %#", token]];
}
then make the request with oauth access token. (Following is a GET method service)
NSURL *url = [EFServiceUrlProvider getServiceUrlForMethod:methodName];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
[httpClient setAuthorizationHeaderWithToken:#"add your access token here"];
[httpClient getPath:#"" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *response = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//
}];
Updated
Use Oauth2 Client on AFNetworking written by matt
https://github.com/AFNetworking/AFOAuth2Client
If you happen to be having this issue with Django rest framework and the routers the problem might be related to the trailing slash being clipped by the NSUrlRequest. if the trailing slash is clipped then django will have to redirect your request, to avoid this you can use Trailing_slash = True like this
router = routers.DefaultRouter(trailing_slash=False)
That way not your authorization header nor your parameters will get lost.
Hope this saves somebody some time.
I would like to to get fetch JSON from http://mycompany.com/page1...http://mycompany.com/page2... On the the webserver side, it requires initial login http://mycompany.com/login, and after that a cookie is maintained for the user. How do I get this behavior with NSURLConnection without having to ask for login every time? Here is the non-working code using NSURLCredential Storage. Do I need to get the cookie from webservice at loging and then send it along with later requests? I struggled with this for some time, So can you please clarify your answer.
- (IBAction)getJSON:(id)sender
{
NSURLCredential *credential = [NSURLCredential credentialWithUser:#"user"
password:#"pass"
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:#"myCompany.com"
port:0
protocol:#"http"
realm:nil
authenticationMethod:nil];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
forProtectionSpace:protectionSpace];
//////////GET JSON//////////////
NSError *error;
NSURL *url = [NSURL URLWithString:#"http://mycompany.com.jsonpage1"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
//I am NOT getting JSON in this delegate
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"%#",responseString);
}
Reading cookies:
refer to Managing HTTP Cookies on iPhone
Setting cookie:
... set dictionary with cookie properties, then:
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:[NSDictionary dictionaryWithObjects:object forKeys:keys]];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
but keep in mind that session cookies can expire on your server