While trying to link the woo-commerce api's generated on xcode8 I am getting error 401 (on googleing a bit found its authentication error) however the same api link and the keys seem to work fine on browser.
Adding the code snip of xcode for reference.
let urlString = "https://serverUrl.com"
func downloadJsonWithURl(){
let url = NSURL(string: urlString)
let request = NSMutableURLRequest(url: url as! URL)
//keys for authentication
request.addValue("A KEY", forHTTPHeaderField: "Consumer-key")
request.addValue("A SECRET", forHTTPHeaderField: "Secret-key")
URLSession.shared.dataTask(with: (url as? URL)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
print (jsonObj as Any)
}
}) .resume()
}
after a bit poking . i got fix this.
just modify the .plist file
add App Transport Security Settings and within that Allow Arbitrary Loads in Web Content and Allow Arbitrary Loads to YES.
info.plist
Related
I am having trouble getting a simple Json object from my php page into my ios app. I am using Swift 3 in xcode 8. I have tried multiple tutorials with no avail. I keep getting the error "Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." I have checked my php page with a Json validator and it seems to be fine. Any help in the right direction will be greatly appreciated. Here is my Json data that is echoed to my php page.
{"SSID":"TESTSSID","PASS":"TESTPASS"}
As you can see, all I am trying to do is be able to get SSID and PASS into a variable in Swift so that I can output the data to the app. Here is what I have so far for the swift code. (sorry if it is terrible, I am a newbie and just hacked it together)
This is in my ViewDidLoad()..
let urlString = "http://192.168.51.1/mytestPHP.php"
let url = URL(string: urlString)
URLSession.shared.dataTask(with:url!) { (data, response, error) in
if error != nil {
print(error)
} else {
do {
let parsedData = try JSONSerialization.jsonObject(with: data!, options: []) as! [String:Any]
let SSID = parsedData["SSID"] as! [String:Any]
print(SSID)
} catch let error as NSError {
print(error)
}
}
}.resume()
In your JSON response both SSID and PASS keys having String as value not Dictionary.
do {
let parsedData = try JSONSerialization.jsonObject(with: data!, options: []) as! [String:Any]
if let ssid = parsedData["SSID"] as? String,
let pass = parsedData["PASS"] as? String {
print(ssid, pass)
}
} catch let error as NSError {
print(error)
}
Note: As error suggesting your response is not valid so try once converting data to string and check what you are getting in response. Add below line before calling JSONSerialization and the response of it here.
print(String(data: data!, encoding: .utf8))
You are basically getting an invalid JSON error, so either your PHP script is not returning the JSON you think it's returning or it's not returning anything at all.
So this may be a little broad, but I will be as specific as possible with what I am working on.
Currently I am developing an iPhone app using swift 3. This app performs a post request to a php file located on a lamp server that is on a different network. The server is primarily being used to simply take the data sent from the app and store it into some mysql tables.
Currently, I am doing this.
func sendToServer(firstEntry: String, secondEntry: String, serverAddr: String){
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
let uid = firstEntry
let gender = secondEntry
let request = NSMutableURLRequest(url: NSURL(string: serverAddr)! as URL)
request.httpMethod = "POST"
let postString = "UID=\(uid)&Gender=\(gender)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error)")
return
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
}
task.resume()
}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: #escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
This sends the data over like it should. But I would like to see if anyone can answer these couple questions.
Is there a way to get a trusted certificate without having a domain name?
If I do it this way will there be issues with the app getting rejected for this?
Thanks
This is the acceptable POST request that server(using codeigniter) accepts.
As it is shown, it doesn't take keys, but only values.
The first value starts with "/", and "/" is used between values.
http://example.com/index.php/api/signup/value01/value02/value03
I have this code, written in Swift3.
let serverUrl = "http://example.com/index.php/api/signup"
let parameterString = "/value01/value02/value03"
let url: URL = URL(string: serverUrl)!
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "POST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
request.httpBody = parameterString.data(using: String.Encoding.utf8)
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
}) task.resume()
It gets an error, and the server responds that it didn't receive any parameter.
But, if I copy paste the below code to Browser, it works perfect.
http://example.com/index.php/api/signup/value01/value02/value03
The swift3 code worked for another server, which accepted POST requests written this way.
http://example.com/api?key=value&key=value
Thank you #Tj3n #Leo Dabus #GoodSp33d !
I was able to solve the problem, using your suggestions.
The server php also used "URL-encode RFC 1738 (e.g. "%E6%84%9B" for "愛")" for certain string values.
So, I added
let newString = oldString.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)!
to encode some string values and the problem solved.
So, this is the solution in a simplified version.
let serverUrl = "http://example.com/index.php/api/signup/value01/value02/value03"
let url: URL = URL(string: serverUrl)!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
}) task.resume()
This is the real POST request url that my code sent.
http://example.com/index.php/api/signup/1282283772/none/0204291/%E6%84%9B/0/70/null
I am using Swift's NSURL function to connect to a PHP script that I can use to interact with a MySQL database. Everything is running smoothly except for the insecurity of the variables passed in the URL via POST. If someone were to intercept these variables it would pose an enormous security risk to my application. I have researched the subject extensively however I have hit a wall. Is an SSL certificate enough to secure the URL? I am not passing the variables through the literal URL but a POST method. As far as I know, the SSL certificate provides security for the data passed AFTER the initial connection (meaning that the data originally passed via POST and the URL are not secure). So essentially, how do I go about passing variables to a web server securely?Here is the code I am using to establish the connection:
let myUrl = NSURL(string: "http://testsite.com/login.php”)
let request = NSMutableURLRequest(URL: myUrl!)
request.HTTPMethod = "POST"
let postString = “username=bob&password=123"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
if let responseData = data {
let responseString = NSString(data: responseData, encoding: NSUTF8StringEncoding)
if error != nil {
print("Error: \(error)")
}
dispatch_async(dispatch_get_main_queue()) {
}
}
} else {
self.sendAlert("Error", message: "Unable to establish connection")
}
}
You can refer to raywenderlich tutorials for setting up the iOS part of it. This tutorial is for connection between ruby rails and swift. It has sign in, sign up and token system, it also includes encryption.
The tutorial uses httpBody to pass the information, you can stick with that or modify to header instead to personalise your codes as required.
request.addValue("bob", forHTTPHeaderField: "username")
request.addValue("123", forHTTPHeaderField: "password") // add AES Encryption.
Also, you can implement a token system instead of passing your username and password. You would however have to pass it initially to get the token.
I am writing this question because I am in a big difficulty in understanding how to implement a simple basic authentication login with Swift.
The first screen of my app is a simple form with text fields (username and password) and a Sign In button. In my LoginViewController.swift file I linked the button to this:
#IBAction func doLogin(sender : AnyObject) {
}
The probem now is that I don't know how to go on. I have a local server in MAMP where there is this file.php querying a database and which works perfectly:
<?php
$deep="";
require_once($deep."class/config.php");
$sistema = new config($deep);
if( isset($_GET["username"]) && isset($_GET["password"]) ) {
$username=mysqli_real_escape_string($sistema->dbConn,$_GET["username"]);
$password=mysqli_real_escape_string($sistema->dbConn,$_GET["password"]);
$userL=$sistema->user->allAdmin("WHERE username='".$username."' AND password='".$password."' ");
echo json_encode($userL);
}
?>
So how can I perform a GET request to this file? I suppose I need to create a URL with user data like this form:
http://localhost:8888/excogitoweb/loginM.php?username=lorenzo&password=lorenzo
but then I don't know how to go on. How can I perform this request to retrieve that JSON content? And how can I check that JSON content in order to understand if the sign in procedure has succeeded or has not?
I have watched many tutorials in youtube, overall this but even if I copy the code they show I always get compilation errors...
for a "normal" GET request you need a NSURLRequest with your url... Its just like this:
if let requestURL: NSURL = NSURL(string: "http://localhost:8888/excogitoweb/loginM.php?username=lorenzo&password=lorenzo") as NSURL? {
let urlRequest: NSURLRequest = NSURLRequest(URL: requestURL)
let urlSession = NSURLSession.sharedSession().dataTaskWithRequest(urlRequest, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if let responseJSON: [String: String] = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as? [String: String] {
///Here you can handle the responded JSON
}
})
urlSession.resume()
}
Don't forget, you are on a background Task when you handle the responded JSON... If you want to do some UI Stuff there you will need to dispatch it to the mein queue
Also a would recommend you doing HTTP POST instead of HTTP GET for such things
UPDATE
if let responseJSON: [[String: String]] = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as? [[String: String]] {
///Here you can handle the responded JSON
}