Good day everyone . I'm currently facing a problem where in I don't have any idea how to store the session that the web API will give me and use that to get the data and put it on webview
Here's what i've got so far
let URL_USER_LOGIN = "https://xxxx.xxx.xxx/xxx/xxx"
let parameters: Parameters=[
"username" : usernameTextField.text!,
"password" : passwordTextField.text!
]
Alamofire.request(URL_USER_LOGIN, method: .post, parameters: parameters).responseString
{
response in
//WEBVIEW
//if success
let url = NSURL(string:"https://xxx.xxx.xxx/xxx/dashboard")
let requestObj = URLRequest(url: url! as URL) self.WebView_Dashboard.LoadRequest(requesObj)
}
I'm using Alamofire framework for the post request
As I understood. From one my old project: (Sorry for Objective C. It's easy to convert into Swift)
-(void)saveCookies:(NSString*)user_id{
NSMutableArray *theCookies = [NSMutableArray new];
for(NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
[theCookies addObject:cookie];
}
if (theCookies.count>0){
NSData *cd = [NSKeyedArchiver archivedDataWithRootObject:theCookies];
NSString *cookiesFilesPath = [appDelegate cookPathForUser:user_id]; // Here your path to file (or you can store it anywhere)
[[NSFileManager defaultManager] createFileAtPath:cookiesFilesPath contents:[NSData data] attributes:nil];
[cd writeToFile:cookiesFilesPath atomically:YES];
}
}
-(NSArray*)cookiesForUser:(NSString*)user_id{
NSData *cookiesData = [NSData dataWithContentsOfFile:[appDelegate cookPathForUser:user_id]];
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];
return cookies;
}
-(void)resetCookies {
[[NSURLCache sharedURLCache] removeAllCachedResponses];
for(NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
}
- (void)applyCookies:(NSArray*)cookies {
for (int i = 0; i<cookies.count; i++){
NSHTTPCookie *cookie = [cookies objectAtIndex:i];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
}
- (void)addCookies:(NSArray *)cookies forRequest:(NSMutableURLRequest *)request
{
if ([cookies count] > 0)
{
NSHTTPCookie *cookie;
NSString *cookieHeader = nil;
for (cookie in cookies)
{
if (!cookieHeader)
{
cookieHeader = [NSString stringWithFormat: #"%#=%#",[cookie name],[cookie value]];
}
else
{
cookieHeader = [NSString stringWithFormat: #"%#; %#=%#",cookieHeader,[cookie name],[cookie value]];
}
}
if (cookieHeader)
{
[request setValue:cookieHeader forHTTPHeaderField:#"Cookie"];
}
}
}
Related
However, because I am loading the web page in UIWebView by calling UIWebView's loadRequest, those techniques are not really applicable.
Any ideas how I can save the login content in web page so that on again app launch to save my login content in UIWebView page,
This url save login content:- http://aubonpain.mloyalconnect.com/microsite/
document.querySelectorAll("input[type='password']")
For all textField use: document.querySelectorAll("input[type='text']")
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *userName = #"xyz";
NSString *password = #"abc";
if (userName.length != 0 && password.length != 0) {
NSString *jsPassword = [NSString stringWithFormat:#"document.querySelectorAll(\"input[type='password']\").value ='%#'", password];
NSString *jsUsername = [NSString stringWithFormat:#"var inputFields = document.querySelectorAll(\"input[type='text']\"); \
for (var i = inputFields.length >>> 0; i--;) { inputFields[i].value = '%#';}", userName];
[self.mywebView stringByEvaluatingJavaScriptFromString: jsUsername];
[self.mywebView stringByEvaluatingJavaScriptFromString: jsPassword];
}
}
I am using the following in couple of my live apps and they work quite well.
Save cookies when you get response :
- (void)saveCookiesToDefaults
{
NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject:[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
[[NSUserDefaults standardUserDefaults] setObject:cookiesData forKey:#"SAVED_COOKIES"];
}
Load cookies :
- (void)loadCookies
{
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: #"SAVED_COOKIES"]];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in cookies)
{
NSMutableDictionary *newProperties = [[NSMutableDictionary alloc]initWithDictionary:cookie.properties];
NSDate *date = [newProperties objectForKey:NSHTTPCookieExpires];
if(date == nil)
[newProperties setObject:[[NSDate date] dateByAddingTimeInterval:100*12*30*60*60] forKey:NSHTTPCookieExpires];
else
[newProperties setObject:[[NSDate date] dateByAddingTimeInterval:100*12*30*60*60] forKey:NSHTTPCookieExpires];
NSHTTPCookie *newCookie = [NSHTTPCookie cookieWithProperties:newProperties];
[cookieStorage setCookie: newCookie];
NSLog(#"%#",newCookie);
}
}
Clear cookies from session :
- (void)clearCookies
{
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies])
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
[[NSURLCache sharedURLCache] removeAllCachedResponses];
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:#"SAVED_COOKIES"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Check if session exists :
- (BOOL)hasExistingSession
{
NSData *savedCookiesData = [[NSUserDefaults standardUserDefaults] objectForKey:#"SAVED_COOKIES"];
if(savedCookiesData == nil)
return 0;
else
{
NSArray *savedCookies = [NSKeyedUnarchiver unarchiveObjectWithData:savedCookiesData];
for (NSHTTPCookie *cookie in savedCookies)
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
NSLog(#"HAS EXISTING SESSION: %#", savedCookies.count ? #"YES" : #"NO");
return savedCookies.count;
}
}
How can i URLEncode a NSDictionary so i can send it across AFNetworking.
The code is as follows:
NSMutableDictionary *rus = [[NSMutableDictionary alloc] init];
[rus setValue:#"1211" forKey:#"id"];
[rus setValue:#"33" forKey:#"man"];
How can i Encode this NSDictionary so i can send it across AFNetworking ?
Depends how you wish to send your data:
1) #"application/json" in which case you would use [NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]
2) #"application/x-www-form-urlencoded" in which case you basically want to create the string: ?id=1211&man=33 from your dictionary rus.
Here's some code, may not be the most efficient by you get the idea:
NSString *temp;
int i=0;
for(NSString *key in options.params.allKeys)
{
NSString *value = [options.params objectForKey:key];
[parameters setObject:value forKey:key];
if(i==0)
{
temp = [NSString stringWithFormat:#"?%#=%#", key,value];
}
else
{
temp = [NSString stringWithFormat:#"%#&%#=%#", temp, key, value];
}
}
Note: may or may not be relevant to you, but my two cents:
I use AFHTTPSessionManager which handles all the details for me including url encoding, so I just pass in the desired dictionary:
NSMutableDictionary *rus = [[NSMutableDictionary alloc] init];
[rus setValue:#"1211" forKey:#"id"];
[rus setValue:#"33" forKey:#"man"];
[self POST:#"/api/place/nearbysearch" parameters:rus success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(#"nearbyPlaces: success");
[self fetchedPlacesData:responseObject block:block];
if(task != nil && task.originalRequest != nil)
{
NSString *url = [task.originalRequest.URL absoluteString];
[self saveNearbySearchEvent:url params:params];
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"nearbyPlaces: error: %#", error);
block(self, nil, error);
}];
AFHTTPSessionManager encapsulates a lot of functionality included serializing the data: AFURLRequestSerialization either as JSON or HTTP Request. In case you interested on what AFHTTPSessionManager actually does here's some detail:
A) HTTP Request
Here's the code from AFURLRequestSerialization.m:
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSParameterAssert(request);
NSMutableURLRequest *mutableRequest = [request mutableCopy];
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
if (![request valueForHTTPHeaderField:field]) {
[mutableRequest setValue:value forHTTPHeaderField:field];
}
}];
if (parameters) {
NSString *query = nil;
if (self.queryStringSerialization) {
NSError *serializationError;
query = self.queryStringSerialization(request, parameters, &serializationError);
if (serializationError) {
if (error) {
*error = serializationError;
}
return nil;
}
} else {
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding);
break;
}
}
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? #"&%#" : #"?%#", query]];
} else {
if (![mutableRequest valueForHTTPHeaderField:#"Content-Type"]) {
[mutableRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
}
[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
}
}
return mutableRequest;
}
B) JSON
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
{
NSParameterAssert(request);
if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
return [super requestBySerializingRequest:request withParameters:parameters error:error];
}
NSMutableURLRequest *mutableRequest = [request mutableCopy];
[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
if (![request valueForHTTPHeaderField:field]) {
[mutableRequest setValue:value forHTTPHeaderField:field];
}
}];
if (parameters) {
if (![mutableRequest valueForHTTPHeaderField:#"Content-Type"]) {
[mutableRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
}
[mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
}
return mutableRequest;
}
NSMutableDictionary *rus = [[NSMutableDictionary alloc] init];
[rus setValue:#"1211" forKey:#"id"];
[rus setValue:#"33" forKey:#"man"];
If you are exchanging JSON data with your server:
NSError *error = nil;
NSData *aRequestData = [NSJSONSerialization dataWithJSONObject:rus options:NSJSONWritingPrettyPrinted error:&error];
if (!error) {
[urlRequest setHTTPBody:aRequestData];
}
If you are exchanging PLIST data with your server:
[self stringByAppendingQueryParameters:rus appendQuestionMark:NO];
- (NSString *)stringByAppendingQueryParameters:(NSDictionary *)iParameters appendQuestionMark:(BOOL)iAppendQuestionMark {
BOOL aAppendAmpersand = YES;
NSMutableString *aWorking = [NSMutableString stringWithString:self];
if (iAppendQuestionMark) {
NSRange aQueryBeginning = [self rangeOfString:#"?"];
if (aQueryBeginning.location == NSNotFound) {
[aWorking appendString:#"?"];
aAppendAmpersand = NO;
}
} else {
aAppendAmpersand = NO;
}
for (id aKey in iParameters) {
id aValue = [iParameters valueForKey:aKey];
NSString *aKeyStr = [self convertObjectToURLEncodedValue:aKey];
if (aAppendAmpersand) {
[aWorking appendString:#"&"];
} else {
aAppendAmpersand = YES;
}
if ([aValue isKindOfClass:[NSArray class]]) {
NSArray *aSubParamaters = (NSArray *)aValue;
BOOL aFirstTime = YES;
for (id aSubValue in aSubParamaters) {
NSString *aValueString = [self convertObjectToURLEncodedValue:aSubValue];
if (!aFirstTime) {
[aWorking appendString:#"&"];
}
[aWorking appendString:aKeyStr];
[aWorking appendString:#"="];
[aWorking appendString:aValueString];
aFirstTime = NO;
}
} else {
NSString *aValueString = [self convertObjectToURLEncodedValue:aValue];
[aWorking appendString:aKeyStr];
[aWorking appendString:#"="];
[aWorking appendString:aValueString];
}
}
return [NSString stringWithString:aWorking];
}
- (NSString *)convertObjectToURLEncodedValue:(id)iObject {
NSString *anIntermediate = nil;
if ([iObject isKindOfClass:[NSString class]]) {
anIntermediate = iObject;
} else if ([iObject respondsToSelector:#selector(stringValue)]) {
anIntermediate = [iObject stringValue];
} else {
anIntermediate = [iObject description];
}
NSString *anEncodingString = (__bridge_transfer NSString *)(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef)anIntermediate,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 ));
return anEncodingString;
}
I am doing a project in login screen am posting email password in response i need to store the cookies and delete the cookies when user logged out so how can i handle this i tried with NSUrlSession and NSURLConnection but i don't know how to store the cookie and delete the cookie
NSString *noteDataString = [NSString stringWithFormat:#"user[email]=%#&user[password]=%#", userNameTF.text, passWordTF.text];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.HTTPShouldSetCookies = YES;
sessionConfiguration.HTTPAdditionalHeaders = #{
#"Accept": #"application/json"
};
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSURL *url = [NSURL URLWithString:#"http://URL/login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = [noteDataString dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod = #"POST";
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary * dd = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString * role = [dd objectForKey:#"role"];
if ([role isEqualToString:#"user"]) {
UIStoryboard * storyBD = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UITabBarController * obj = [storyBD instantiateViewControllerWithIdentifier:#"tab"];
[self.navigationController pushViewController:obj animated:YES];
}
NSLog(#"%#",dd);
}];
[postDataTask resume];
You can also user NSUserDefaults for saving the cookies data
- (void)saveCookies{
NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject: cookiesData forKey: #"sessionCookies"];
[defaults synchronize];
}
- (void)loadCookies{
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: #"sessionCookies"]];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in cookies){
[cookieStorage setCookie: cookie];
}
}
Delete the cookies data at logout
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"sessionCookies"]
//When we saved the data, the key was "sessionCookies" so it must be sessionCookies for this specific saved data. You can name it as you like but then it must be same for saving, retrieving and deleting that specific data.
Please read out the Apple's documentation for NSUserDefaults.
I am using a web service with simple header authentication
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSString *userName = [_usernameTextField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];;
NSString *passWord = [_passwordTextfield.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([challenge previousFailureCount] == 0) {
//Creating new credintial
NSURLCredential *newCredential = [NSURLCredential credentialWithUser:userName
password:passWord
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
else {
CommonCode*objCommon=[[CommonCode alloc]init];
[_activityIndicator stopAnimating];
[objCommon showAlert:#"Invalid Password, or no user found with this Email Address"];
}
}
On the logout I am clearing the cokies with
- (void)resetCredintialCache {
NSDictionary *credentialsDict = [[NSURLCredentialStorage sharedCredentialStorage] allCredentials];
if ([credentialsDict count] > 0) {
// the credentialsDict has NSURLProtectionSpace objs as keys and dicts of userName => NSURLCredential
NSEnumerator *protectionSpaceEnumerator = [credentialsDict keyEnumerator];
id urlProtectionSpace;
// iterate over all NSURLProtectionSpaces
while (urlProtectionSpace = [protectionSpaceEnumerator nextObject]) {
NSEnumerator *userNameEnumerator = [credentialsDict[urlProtectionSpace] keyEnumerator];
id userName;
// iterate over all usernames for this protectionspace, which are the keys for the actual NSURLCredentials
while (userName = [userNameEnumerator nextObject]) {
NSURLCredential *cred = credentialsDict[urlProtectionSpace][userName];
[[NSURLCredentialStorage sharedCredentialStorage] removeCredential:cred forProtectionSpace:urlProtectionSpace];
}
}
NSURLCache *sharedCache = [NSURLCache sharedURLCache];
[sharedCache removeAllCachedResponses];
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *cookies = [cookieStorage cookies];
for (NSHTTPCookie *cookie in cookies) {
[cookieStorage deleteCookie:cookie];
}
}
}
But after logout if I enter the wrong password I am logged in as theprevious user. How do I delete the cookies from the header of the HTTP request?
NSURLRequest has a cachePolicy property, which specifies the caching behaviour of the request.
Set the following cache policy NSURLRequestReloadIgnoringLocalCacheData when making the request like the example bellow will load the data from the url and not from the cache.
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
NSURLRequestReloadIgnoringLocalCacheData
Specifies that the data for the URL load should be loaded from the
originating source. No existing cache data should be used to satisfy a
URL load request.
https://developer.apple.com/library/prerelease/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/index.html#//apple_ref/c/tdef/NSURLRequestCachePolicy
I am trying to access a specific URL that requires cookies through UIWebView but I can not access it because cookies are disabled. So I did the following:
Enabled cookies:
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
Created NSURLConnection and extracted cookies from response:
NSArray *cookies = [ NSHTTPCookie cookiesWithResponseHeaderFields: [ httpResponse allHeaderFields ] forURL:response.URL];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies: cookies forURL: response.URL mainDocumentURL:nil];
But neither of this didn't help. However if I launch the URL in safari it loads successfully and after that I can load the same URL in UIWebView too. Could you help me with this, how can I enable cookies for UIWebView?
Thanks in advance
After create a NSURLRequest, copy all cookies in sharedHTTPCookieStorage to NSURLRequest:
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPShouldHandleCookies:YES];
[self addCookies:cookies forRequest:request];
[_webView loadRequest:request];
And add addCookies:forRequest method
- (void)addCookies:(NSArray *)cookies forRequest:(NSMutableURLRequest *)request
{
if ([cookies count] > 0)
{
NSHTTPCookie *cookie;
NSString *cookieHeader = nil;
for (cookie in cookies)
{
if (!cookieHeader)
{
cookieHeader = [NSString stringWithFormat: #"%#=%#",[cookie name],[cookie value]];
}
else
{
cookieHeader = [NSString stringWithFormat: #"%#; %#=%#",cookieHeader,[cookie name],[cookie value]];
}
}
if (cookieHeader)
{
[request setValue:cookieHeader forHTTPHeaderField:#"Cookie"];
}
}
}