I am building an app, which has login page connected with my AWS server using PHP and MySQL, everything is working fine except that I have no idea how to save the PHP session within the app so the user can stay authenticated.
Part of my PHP code:
<?php
$session_start();
...
...
if($verify){
echo "Verfied";
$_SESSION["Authenticated"] = 1;
} else {
echo "Unverified";
$_SESSION["Authenticated"] = 0;
}
...
...
?>
Part of Swift code:
let url = URL(string: "http://localhost/login.php")!
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let postString = "username=\(username)&password=\(password)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)!
print("responseString = \(String(describing: responseString))")
DispatchQueue.main.async() {
if (responseString == "Vaild!") {
self.performSegue(withIdentifier: "MainPageSegue", sender: self)
} else {
self.errorLabel.text = "Invalid username or password."
}
}
}
task.resume()
How can I save the session within my app so the user stay authenticated?
Related
The code I've posted here is a shortened versions with just the essentials to the issue. When put through rigorous error testing, it appears that there are no issues either within the request, within the server, or within the return code, except for the fact that the response from the server says "Function": null instead of "Function": "addUser" as it should. Is there something I'm doing wrong on either end? It just seems to not be recognizing the posted variables, but I've used this code numerous times in other apps and servers and it seems to be failing here for some reason I cannot see. Thank you for any assistance.
Here is my PHP on the server:
<?php
$t = $_POST["function"];
$do = array("Success"=>true, "Function"=> $t);
echo json_encode($do);
?>
Here is the swift I'm using to make the request:
let params = ["function": "addUser"] as [String: AnyObject]?
fetchData("https://pdt.pitchprogress.net/SamplePHP.php", token: nil, parameters: params, method: "POST", onCompletion: { (success, data) -> Void in
if success {
do {
let json = try JSON(data: data!)
if json["Success"].boolValue == true {
print("success!")
print(json.description)
print(json["Function"].stringValue)
}
}
}
})
func fetchData(_ feed:String,token:String? = nil,parameters:[String:AnyObject]? = nil,method:String? = nil, onCompletion:#escaping (_ success:Bool,_ data:Data?)->Void){
DispatchQueue.main.async {
if let unwrapped_url = URL(string: feed){
let request = NSMutableURLRequest(url: unwrapped_url)
if let parm = parameters {
if let data = (try? JSONSerialization.data(withJSONObject: parm, options:[])) as Data? {
request.httpBody = data
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("\(data.count)", forHTTPHeaderField: "Content-Length")
}
}
if let unwrapped_method = method {
request.httpMethod = unwrapped_method
}
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.timeoutIntervalForRequest = 15.0
let session = URLSession(configuration: sessionConfiguration)
let taskGetCategories = session.dataTask(with: request as URLRequest, completionHandler: { (responseData, response, error) -> Void in
let statusCode = (response as! HTTPURLResponse?)?.statusCode
//println("Status Code: \(statusCode), error: \(error)")
if error != nil || (statusCode != 200 && statusCode != 201 && statusCode != 202){
onCompletion(false, nil)
} else {
onCompletion(true, responseData)
}
})
taskGetCategories.resume()
}
}
}
This is because you are sending the params as JSON while your API requires params as form data.
This code sends the params as simple form post and this retrieved successful response.
var request = URLRequest(url: URL(string: "http://app123.freeiz.com/Apis/samples/api4.php")!)
request.httpMethod = "POST"
var postString = ""
postString.append("function=value") // replace 'function' with your paramname and 'value' with your value'
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
// check for fundamental networking error
print("error=\(String(describing: error))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
// check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
let responseString = String(data: data, encoding: .utf8)
if let unWrappedResponseString = responseString{
print(unWrappedResponseString)
}
}
task.resume()
I had once made a small wrapper for sending simple form data, If i find it I will update the answer with that. Till then you can try with this. Let me know how it goes..
Looks like your key is different use "function" instead of using "Function"
I am creating an application that uses a login and register page. After a user registers their account it is in my mySQL database. So when I go to test the login, I will press login, then nothing happens, however I am receiving a message from my php saying "success" but the application will not segue until I click on the Login button again. I thought that maybe my if statement was in the wrong location, but I can't figure out where to move it because my task.resume is locked to where it is, and the if statement needs to execute with a button press. I feel like this will be an easy problem to fix, but for the life of me I cannot figure it out. All help is appreciated, this is my loginViewController.swift file.(I removed my POST website on purpose)
import UIKit
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
class loginViewController: UIViewController {
struct globalVariable {
static var response = String()
}
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBAction func loginButtonTap(_ sender: Any) {
do {
let request = try NSMutableURLRequest(url: NSURL(string: "")! as URL)
request.httpMethod = "POST"
//Getting the values from the text fields and creating the post parameter
let postString = "email=\(emailTextField.text!)&password=\(passwordTextField.text!)"
//Adding the parameters to request body
request.httpBody = postString.data(using: String.Encoding.utf8)
//Creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error is=\(error)")
return;
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
globalVariable.response = responseString as! String
}
task.resume()
if globalVariable.response.range(of: "true") != nil{
var loginSwitch = self.storyboard?.instantiateViewController(withIdentifier: "tabBarController") as! UITabBarController
var appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = loginSwitch
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You need to handle the response from webservice inside the completion handler, as it stands, its trying to handle the response from the webservice before the webservice has returned.
//Creating a task to send the post request
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error is=\(error)")
return;
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(responseString)")
if responseString.range(of: "true") != nil{
DispatchQueue.main.async {
var loginSwitch = self.storyboard?.instantiateViewController(withIdentifier: "tabBarController") as! UITabBarController
var appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.window?.rootViewController = loginSwitch
}
}
}
task.resume()
I am new to Swift and I am trying to create secure login with PHP in backend. But somewhere I am going wrong, my viewcontroller is segue to next view controller even though i Don't give login credential and getting following error in console:
Please help !!
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set
my code:
#IBAction func loginAuthentication(sender: UIButton) {
//declare parameter as a dictionary which contains string as key and value combination. considering inputs are valid
let myUrl = NSURL(string: "my url");
var request = NSMutableURLRequest(URL:myUrl!)
request.HTTPMethod = "POST"// Compose a query string
let postString = "username = \( NameTextField.text!) & password = \( passwortTextField.text!) ";
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data , response , error in
if error != nil
{
let alert = UIAlertView()
alert.title = "Login Failed!"
alert.message = "Error: \(error)"
alert.delegate = self
alert.addButtonWithTitle("OK")
alert.show()
return
}
// You can print out response object
print("*****response = \(response)")
let responseString = NSString(data: data! , encoding: NSUTF8StringEncoding )
if ((responseString?.containsString("")) != nil) {
print("incorrect - try again")
let alert = UIAlertController(title: "Try Again", message: "Username or Password Incorrect", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Nochmalversuchen", style: .Default) { (action) -> Void in
}
// Add Actions
alert.addAction(yesAction)
// Present Alert Controller
self.presentViewController(alert, animated: true, completion: nil)
}
else {
print("correct good")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("toPflegerProfile")
self.presentViewController(controller, animated: true, completion: nil)
}
print("*****response data = \(responseString)")
do {
//create json object from data
if let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? [String: Any] {
if let email = json["UserName"] as? String,
let password = json["passowrd"] as? String {
print ("Found User id: called \(email)")
}
}
} catch let error {
print(error)
}
}
task.resume()
}
php code :
<?php
require_once 'db.php';
$conn = connect();
if($conn)
{
if (isset($_GET['loginuser']))
{
//Getting post values
require_once 'getuserdata.php';
//1.Check if user is looged in
$loggedin = checkuserloggedin($username, $conn);
if ($loggedin)
{
$response['error']=true;
$response['message']='User is already logged in!';
}
else
{
//2.If not, insert pfleger
//Inserting log in values
if (insertuserdata($name,$username, $password, $gps, $logintime, $conn))
{
$response['error']=false;
$response['message']='Log Data added successfully';
}
else
{
$response['error']=true;
$response['message']='Could not add log in data';
}
}
}
else
{
$response['error']=true;
$response['message']='You are not authorized';
}
echo json_encode($response);
?>
use this
var request = URLRequest(url: URL(string: “url”)!)
request.httpMethod = "POST"
let userName = self.emailTextField.text!
let password = self.passtextField.text!
let postString = NSString(format: "emailId=%#&password=%action=%#",userName, password,”action name”)
request.httpBody = postString.data(using: String.Encoding.utf8.rawValue)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
do {
let jsonResults : NSDictionary = try JSONSerialization.jsonObject(with: data, options: [])as! NSDictionary
print("login json is ---%#",jsonResults)
let str = jsonResults.object(forKey: "status")as! String
if (str == "Success")
{
let newdic:NSDictionary = jsonResults.object(forKey: "response") as! NSDictionary
} catch {
// failure
print("Fetch failed: \((error as NSError).localizedDescription)")
}
}
task.resume()
Hello I'm writing an ios swift 3 application to communicate with a website, the app after doing a number of things should return a type value of false or true, but it does not happen you can tell me where I'm wrong and how to correct the mistake!
VALUE RETURN at swift:
....response = Optional( { URL: "http://....myurl.php"}.....
SWIFT CODE:
let myUrl = URL(string: "http://....myurl.php");
var request = URLRequest(url:myUrl!)
request.httpMethod = "POST"// Compose a query string
let postString = "username=James&password=Bond";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
if error != nil
{
print("error=\(error)");
// return false
}
print("response = \(response)")
}
task.resume()
return 0;
PHP CODE:
include 'user.php';
$user = new User();
$username= $_REQUEST["username"];
$password = $_REQUEST["password"];
if($user->login($username,$password)==true){
echo json_encode("true");
}
else{
echo json_encode("false");
}
ERROR IMAGE:
You need to look into data and not response.
And maybe you should encapsulate your return value in your PHP code, like this for example:
if($user->login($username,$password)==true){
echo '{"success":true}';
}else{
echo '{"success":false}';
}
And then get the result in swift:
func login(request_completed:#escaping (_ succeded:Bool) -> ()) {
let myUrl=URL(string: "http://....myurl.php");
var request=URLRequest(url:myUrl!)
request.httpMethod="POST"
let postString = "username=James&password=Bond";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task=URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
guard data != nil else {
print("no data found")
request_completed(false)
return
}
do{
if let jsonData=try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary{
print(jsonData)
let success=jsonData.value(forKey: "success") as! Bool
if success{
print("login succeded")
request_completed(true)
return
}else{
print("login failed")
request_completed(false)
return
}
}else{
print("could not parse json")
request_completed(false)
}
}catch{
print("request failed")
request_completed(false)
}
})
task.resume()
}
So I've got a few lines that will "login" to the web page, and they fetch the contents and print them to the console, but I can't figure out how to get the results out of the "task" and use them later on in the code.
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/mobilelogin.php")!)
request.HTTPMethod = "POST"
let username = email_input.text;
let password = password_input.text;
var postString = "username="
postString += username!
postString += "&password="
postString += password!
print(postString);
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
print(request.HTTPBody);
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in guard error == nil && data != nil
else {
// check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
// check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
return
}
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
print("responseString = \(responseString)");
return
}
print("This is the task string")
task.resume()
You can't return from a closure, you need to use a "callback".
We make a function for your code:
func getData(username username: String, password: String)
but instead of adding a return type, we add a callback, here named "completion":
func getData(username username: String, password: String, completion: (response: String)->()) {
}
And inside the function, we use this callback at the location where the data will be available:
func getData(username username: String, password: String, completion: (response: String)->()) {
let request = NSMutableURLRequest(URL: NSURL(string: "http://localhost:8888/mobilelogin.php")!)
request.HTTPMethod = "POST"
var postString = "username="
postString += username
postString += "&password="
postString += password
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard let data = data where error == nil else {
fatalError(error!.debugDescription)
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {
print("response = \(response)")
fatalError("statusCode should be 200, but is \(httpStatus.statusCode)")
}
guard let str = String(data: data, encoding: NSUTF8StringEncoding) else {
fatalError("impossible to get string from data")
}
completion(response: str)
}
task.resume()
}
And you will use it like this:
getData(username: email_input.text!, password: password_input.text!) { (response) in
print(response)
}