How to do authentication in UIWebView properly?
Try to use sharedCredentialStorage for all domains you need to authenticate.
Here is working sample for UIWebView it was tested against Windows IIS having only BasicAuthentication enabled
This is how to add your site credentials:
NSString* login = @"MYDOMAIN\\myname";
NSURLCredential *credential = [NSURLCredential credentialWithUser:login
password:@"mypassword"
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"myhost"
port:80
protocol:@"http"
realm:@"myhost" // check your web site settigns or log messages of didReceiveAuthenticationChallenge
authenticationMethod:NSURLAuthenticationMethodDefault];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential
forProtectionSpace:protectionSpace];
[protectionSpace release];
Edit: same code in Swift 4
let login = "MYDOMAIN\\myname"
let credential = URLCredential(user:login, password:"mypassword", persistence:.forSession)
let protectionSpace = URLProtectionSpace(host:"myhost", port:80, protocol:"http", realm:"myhost", authenticationMethod:NSURLAuthenticationMethodDefault)
URLCredentialStorage.shared.setDefaultCredential(credential, for:protectionSpace)
Your webView is supposed to work now, if it does not work use next code to debug, especially check log messages of didReceiveAuthenticationChallenge.
#import "TheSplitAppDelegate.h"
#import "RootViewController.h"
@implementation TheSplitAppDelegate
@synthesize window = _window;
@synthesize splitViewController = _splitViewController;
@synthesize rootViewController = _rootViewController;
@synthesize detailViewController = _detailViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the split view controller's view to the window and display.
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];
NSLog(@"CONNECTION: Add credentials");
NSString* login = @"MYDOMAIN\\myname";
NSURLCredential *credential = [NSURLCredential credentialWithUser:login
password:@"mypassword"
persistence:NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:@"myhost"
port:80
protocol:@"http"
realm:@"myhost" // check your web site settigns or log messages of didReceiveAuthenticationChallenge
authenticationMethod:NSURLAuthenticationMethodDefault];
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
[protectionSpace release];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://myhost/index.html"]
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:12
];
NSLog(@"CONNECTION: Run request");
[[NSURLConnection alloc] initWithRequest:request delegate:self];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
- (void)dealloc
{
[_window release];
[_splitViewController release];
[_rootViewController release];
[_detailViewController release];
[super dealloc];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(@"CONNECTION: got auth challange");
NSString* message = [NSString stringWithFormat:@"CONNECTION: cred cout = %i", [[[NSURLCredentialStorage sharedCredentialStorage] allCredentials] count]];
NSLog(message);
NSLog([connection description]);
NSLog([NSString stringWithFormat:@"CONNECTION: host = %@", [[challenge protectionSpace] host]]);
NSLog([NSString stringWithFormat:@"CONNECTION: port = %i", [[challenge protectionSpace] port]]);
NSLog([NSString stringWithFormat:@"CONNECTION: protocol = %@", [[challenge protectionSpace] protocol]]);
NSLog([NSString stringWithFormat:@"CONNECTION: realm = %@", [[challenge protectionSpace] realm]]);
NSLog([NSString stringWithFormat:@"CONNECTION: authenticationMethod = %@", [[challenge protectionSpace] authenticationMethod]]);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
// release the connection, and the data object
[connection release];
// inform the user
NSLog(@"CONNECTION: failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(@"CONNECTION: received response via nsurlconnection");
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
{
NSLog(@"CONNECTION: USE!");
return YES;
}
@end
The final solution for WebView authentication was based on custom protocol implementation. All protocols registered as a stack, so if you redefine HTTP protocol it would intercept all requests coming from webView, so you have to check attributes assotiated with incoming request and repack it into new request and send it again via your own connection. Since you are in stack, your request immidiatly comes to you again and you have to ignore it. So it goes down protocol stack to real HTTP protocol implementation, since your request is not athenticated you'll get authenticaiton request. And after authenticaiton you'll get a real response from server, so you repack response and reply to original request received from webView and that's it.
Don;t try to create new requests or responses bodies, you have to just resend them. The final code would be aproximetly 30-40 lines of code and it is quite simple, but requires a lot of debuging and tetsing.
Unfortunatlly I cannot provide code here, since I am assigned to different project already, I just wanted to say that my post is wrong way, it stucks when user changes password.
Passing Login credentials into UIWebView
Presumably you're displaying a website (e.g., www.foo.com) in the UIWebView
and want to pass the SID to the UIWebView
to login to www.foo.com.
You'll want to set up an NSMutableURLRequest
with HTMLBody
and HTTPMethod
set properly to achieve this. The way to pass the SID to login is via a query parameter.
var url = NSURL(string: "http://www.foo.com")
var request = NSMutableURLRequest(URL: url!)
// usually to login you send a POST with the user's credentials
request.HTTPMethod = "POST"
// this is where you would assign the SID (from a UITextView, etc.)
var sid = "1234" // getSid()
var bodyData = "SID=\(sid)"
// encode the query params as UTF8
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding)
// this will load the UIWebView by sending the POST with the query string:
// http://www.foo.com/?SID=1234
webView.loadRequest(request)
How do I detect an authentication challenge from a UIWebView?
Apple now has sample code that solves this problem. It also looks like the most complete documentation of how to implement an NSURLProtocol properly.
WKWebView and authentication
The solved it in beta 3 using the function didReceiveAuthenticationChallenge in WKNavigationDelegate. I've tried it and it works perfectly
How to authenticate in UIWebView using RestKit and WSSE?
I don't see how RestKit will help if your download content is HTML. UIWebView
has a loadRequest:
method so you should just create an NSURLRequest
and set the auth headers then pass it straight to the web view.
Clear the credentials from UIWebView
Try Code for Clear cookie of Request
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
{
NSString* domainName = [cookie domain];
NSRange domainRange = [domainName rangeOfString:@"twitter"];
if(domainRange.length > 0)
{
[storage deleteCookie:cookie];
}
}
Swift - WebView HTTP Auth - Cleanest solution
I'm not entirely sure this fulfils your demands in the best way, but if you can use a WKWebView
, maybe you can simply rely on the authentication challenge delegate method? See my answer here as well, the relevant code snippet would be:
func webView(webView: WKWebView, didReceiveAuthenticationChallenge
challenge: NSURLAuthenticationChallenge,
completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
let creds = NSURLCredential(user:"username", password:"password", persistence: NSURLCredentialPersistence.ForSession)
completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, creds)
}
I haven't tried it yet myself, but the documentation says the credentials should be used for the session, so additional requests resulting from links should work. Even if not, that just results for the method to be called again and you can provide the credentials once more.
This is just a rump, you'd have to get name and password from an alert or the like (also you can store the credentials more elegantly to make subsequent calls to the delegate method more elegant).
You also wrote you're using SSL, so I take it you're familiar with the App Transport Security flags (since the question title just has "HTTP" in it and not "HTTPS", which you probably want for it to work smoothly, otherwise see the question I linked).
Swift - UIWebView baseURL resulting in blank screen
Your code isn't working because the base URL isn't https://dev-moss.stpaulscatholiccollege.co.uk/
, it's https://dev-moss.stpaulscatholiccollege.co.uk/sites/Students/default.aspx
. Try that and it should work.
Edit:
It looks like it's not working because https://dev-moss.stpaulscatholiccollege.co.uk/sites/Students/default.aspx
uses HTTP Basic Authentication, which you have not provided credentials for (the UIWebView makes a separate requests for resources from your one made via Alamofire, which doesn't include your credentials.) See How to do authentication in UIWebView properly?
Related Topics
iOS Builds/Ipa Creation No Longer Works from the Command Line
Dismissing Uialertviews When Entering Background State
Navigation Pop View When Swipe Right Like Instagram iPhone App.How I Achieve This
iOS Horizontal Slideview with Vertical Menu
Allow Unverified Ssl Certificate in Uiwebview
Local and Push Notifications in iOS Version Compatible
Xcode Error on Simulator: Mgisdeviceoneoftype Is Not Supported on This Platform
Code Signing Is Required for Product Type Unit Test Bundle in Sdk iOS 8.0
iOS 7 and Later: Set Status Bar Style Per View Controller
Save and Retrieve Value via Keychain
Atos and Dwarfdump Won't Symbolicate My Address
Ios: Add Imageview in a Scrollview to Have Zoom
How Shouldchangecharactersinrange Works in Swift
Error: Uicollectionview Must Be Initialized with a Non-Nil Layout Parameter
Running Xcodebuild from a Forked Terminal
Create and Perform Segue Without Storyboards
Want to Create a Cool Static UI But:"Static Table Views Are Only Valid..."