Reputation: 22956
I'm nearly embarrassed to ask, but I'm trying to build a little app for myself and I'm stumbling with the intricacies of web technologies.
It's not the Swift I need help with, more so the methodology...
I'm trying to sign in here programatically https://account.tfl.gov.uk/oyster
It's just UK website that lets you check you balance on a travel card.
I suck with web stuff, but I believe the POST URL I need to hit is: https://oyster.tfl.gov.uk/oyster/security_check (from inspecting the page)
However the below code just keeps returning a 200 OK, but an error from the web server saying the page is unavailable. Surely the site is just a simple log in via POST?
Any insights would be great - even just a pointer in the right direction! - thanks a lot... current method below:
func login() {
var user = "myUsername"
var pass = "myPassword"
var config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.allowsCellularAccess = true
var connection = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
var request = NSMutableURLRequest(URL: NSURL(string: "https://oyster.tfl.gov.uk/oyster/security_check")!)
request.HTTPMethod = "POST"
var params = "username=\(user)&password=\(pass)"
var err: NSError?
request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
connection.dataTaskWithRequest(request, completionHandler: {
(data : NSData!, response : NSURLResponse!, error : NSError!) in
var dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
println(response)
println(dataString)
}).resume()
}
Upvotes: 2
Views: 308
Reputation: 8014
On that web page, the POST requires a couple of extra params: these are hidden in the HTML. I think you will need to supply all of the required params to get it to work.
The list seems to be:
ReturnUrl="https://oyster.tfl.gov.uk/oyster/security_check"
AppId="8ead5cf4-4624-4389-b90c-b1fd1937bf1f"
UserName=""
Password=""
NB UserName and Password have capitals in name.
Try using all 4 and see how you get on. Not spent a lot of time on this, so might have missed something.
var params = "ReturnUrl=https://oyster.tfl.gov.uk/oyster/security_check&AppId=8ead5cf4-4624-4389-b90c-b1fd1937bf1f&UserName=\(user)&Password=\(pass)"
You might find it simpler to use a UIWebView and to use javascript to fill in the forms and execute the login button. When the login finishes you can then use javascript to scrape off any data you want. That way you are simply automating the user interaction on their standard web page. With this you can also watch what is happening if you show the WebView. You also benefit from the WebView dealing with all the redirects, scripts etc that need to run to make things work.
e.g. To set the username and password and log in all you need to run in javascript in the WebView is:
username=document.getElementById("UserName");
username.value="<put in your username>";
password=document.getElementById("Password");
password.value="<put in your password>";
signinbutton=document.getElementsByName("Sign in")[0];
signinbutton.click();
This will then handle all the page loading for the login in the WebView.
You can try all this out using the Safari inspector window.
Upvotes: 1
Reputation: 438212
Looking at the HTML for the login page, a couple of observations:
You might want to confirm the capitalization of the username
and password
field names. Sometimes web services are case sensitive.
If you look at the form in the HTML, there are other fields on the form. You will probably want to send all the fields that are present in that login form (even if they're not visible in the web browser).
While it doesn't appear to be the case here, sometimes these fields are dynamically generated and you actually have to request the login html page first, parse out these fields, and include them in your request.
You may want to watch the interaction of the web browser using a tool like Charles. You might want to reproduce the requests as faithfully as possible.
Be careful about building the body of the request. Often values will have to be percent escaped. For example, if the password contained reserved characters such as +
or &
, this code would not work. It's probably not the case in your testing, but its something to be wary of.
You might want to review the terms of service for this service, as they sometimes prohibit programmatic interaction with their web servers. You don't want to run afoul of their terms and conditions. More to the point, you don't want users to violate the terms of service by using your app.
You might also want to contact the web server provider to see if they have an approved API for performing the tasks that you are attempting to perform.
Upvotes: 1