简体   繁体   English

如何使用适用于 iOS 的 swift 3 连接到 MEAN 堆栈 REST api

[英]How to connect to MEAN stack REST api using swift 3 for iOS

I'm trying to create a simple login application with iOS, which uses a MEAN stack server exposing a REST API for the iOS side to connect to.我正在尝试使用 iOS 创建一个简单的登录应用程序,它使用一个 MEAN 堆栈服务器公开一个 REST API 供 iOS 端连接。

I've been working on the server side and have an API which allows one to create a user with an Email and Password.我一直在服务器端工作,并且有一个 API,它允许创建一个带有电子邮件和密码的用户。 I've also created DELETE and GET requests, following this tutorial: https://codeforgeek.com/2015/08/restful-api-node-mongodb/我还按照本教程创建了 DELETE 和 GET 请求: https : //codeforgeek.com/2015/08/restful-api-node-mongodb/

However, I'm unsure of how to now log in with this information on the iOS side.但是,我不确定现在如何在 iOS 端使用此信息登录。 a few questions I have are:我有几个问题是:

  • Do I need to create a token for the iOS side to accept?我是否需要为 iOS 端创建一个令牌才能接受?
  • Do I need an Authenticate method?我需要一个 Authenticate 方法吗?

I've included the code I have for the server and my iOS side below.我在下面包含了服务器和我的 iOS 端的代码。

I'm quite new to both languages so any help would be greatly appreciated.我对这两种语言都很陌生,所以任何帮助将不胜感激。 Thank you in advance.先感谢您。

app.js应用程序.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');
var app = express();

app.use( bodyParser.json() );       // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true
})); 
// view engine setup
// all views passed through views 
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');


app.get('/javascript/jquery.min.js', function (req, res) {
        res.sendFile( __dirname + "/javascript" + "/jquery.min.js" );

});
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

app.post('/', function(req, res) {
  console.log(req.body);
  res.send(200);

  });

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

 //app.use('/',router);


module.exports = app;

index.js索引.js

var express = require('express');
var router = express.Router();
var exec = require('child_process').exec;
var util = require('util')
var bodyParser = require('body-parser');
var app = express();

//needed to be able to run child_proccess
app.get('/javascript/jquery.min.js', function (req, res) {
        res.sendFile( __dirname + "/javascript" + "/jquery.min.js" );

});

router.get('/', function(req, res){
  res.render('index', {
    title: 'Home'
  });
});


/** bodyParser.urlencoded(options)
 * Parses the text as URL encoded data (which is how browsers tend to send form data from regular forms set to POST)
 * and exposes the resulting object (containing the keys and values) on req.body
 */
router.use(bodyParser.urlencoded({
    extended: true
}));

/**bodyParser.json(options)
 * Parses the text as JSON and exposes the resulting object on req.body.
 */
router.use(bodyParser.json());

router.post('/unLock', function(req, res){
    console.log("unlocking");  //print to console when the lock is being operated
    // console.log(req.body.paramString); //this doesnt work, trying to get the app to print to console
exec('ssh pi@192.168.2.2 sudo python /home/pi/unlock.py', (e, stdout, stderr)=> { 
    if (e instanceof Error) {
        console.error(e);
        throw e;
    }
})
});

router.post('/Lock', function(req, res){
    console.log("locking"); //print to console when the lock is being operated  
exec('ssh pi@192.168.2.2 sudo python /home/pi/lock.py', (e, stdout, stderr)=> { 
    if (e instanceof Error) {
        console.error(e);
        throw e;
    }
})
});


module.exports = router;

users.js用户.js

var express = require('express');
var router = express.Router();
var mongoOp = require("../model/mongo");

router.route("/")
.get(function(req,res){
        var response = {};
        mongoOp.find({},function(err,data){
        // Mongo command to fetch all data from collection.
            if(err) {
                response = {"error" : true,"message" : "Error fetching data"};
            } else {
                response = {"error" : false,"message" : data};
            }
            res.json(response);
        });
    })
//create new user
      .post(function(req,res){
        var db = new mongoOp();
        var response = {};
        // fetch email and password from REST request.
        // Add strict validation when you use this in Production.
        db.userEmail = req.body.email; 
        // Hash the password using SHA1 algorithm.
        db.userPassword =  require('crypto')
                          .createHash('sha1')
                          .update(req.body.password)
                          .digest('base64');
        db.save(function(err){
        // save() will run insert() command of MongoDB.
        // it will add new data in collection.
            if(err) {
                response = {"error" : true,"message" : "Error adding data"};
            } else {
                response = {"error" : false,"message" : "Data added"};
            }
            res.json(response);
        });
    });
//get by id using GET http://localhost:3000/users/id
      router.route("/:id")
    .get(function(req,res){
        var response = {};
        mongoOp.findById(req.params.id,function(err,data){
        // This will run Mongo Query to fetch data based on ID.
            if(err) {
                response = {"error" : true,"message" : "Error fetching data"};
            } else {
                response = {"error" : false,"message" : data};
            }
            res.json(response);
        });
    })
    //update data of a user
    .put(function(req,res){
        var response = {};
        // first find out record exists or not
        // if it does then update the record
        mongoOp.findById(req.params.id,function(err,data){
            if(err) {
                response = {"error" : true,"message" : "Error fetching data"};
            } else {
            // we got data from Mongo.
            // change it accordingly.
                if(req.body.userEmail !== undefined) {
                    // case where email needs to be updated.
                    data.userEmail = req.body.userEmail;
                }
                if(req.body.userPassword !== undefined) {
                    // case where password needs to be updated
                    data.userPassword = req.body.userPassword;
                }
                // save the data
                data.save(function(err){
                    if(err) {
                        response = {"error" : true,"message" : "Error updating data"};
                    } else {
                        response = {"error" : false,"message" : "Data is updated for "+req.params.id};
                    }
                    res.json(response);
                })
            }
        });
    })
    //DELETE http://localhost:3000/users/id
    //delete data 
    .delete(function(req,res){
        var response = {};
        // find the data
        mongoOp.findById(req.params.id,function(err,data){
            if(err) {
                response = {"error" : true,"message" : "Error fetching data"};
            } else {
                // data exists, remove it.
                mongoOp.remove({_id : req.params.id},function(err){
                    if(err) {
                        response = {"error" : true,"message" : "Error deleting data"};
                    } else {
                        response = {"error" : true,"message" : "Data associated with "+req.params.id+"is deleted"};
                    }
                    res.json(response);
                });
            }
        });
    })


module.exports = router;

mongo.js mongo.js

var mongoose    =   require("mongoose");
mongoose.connect('mongodb://localhost:27017/lock');
// create instance of Schema
var mongoSchema =   mongoose.Schema;
// create schema
var userSchema  = {
    "userEmail" : String,
    "userPassword" : String
};
// create model if not exists.
module.exports = mongoose.model('userLogin',userSchema);

ViewController.swift This file currently asks for the server IP and allows one to make post Unlock and Lock requests, which I will be adding data to in the future. ViewController.swift 该文件目前要求提供服务器 IP 并允许发布解锁和锁定请求,我将在未来向其中添加数据。

I'm wanting to make this view only accessible via logging into to the server as a valid user and being presented with it.我想让这个视图只能通过以有效用户身份登录到服务器并显示出来才能访问。

import UIKit

class ViewController: UIViewController {

    func presentAlert() {
        let alertController = UIAlertController(title: "IP?", message: "Please input your unique key:", preferredStyle: .alert)

        let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (_) in
            if let field = alertController.textFields?[0] {
                //this could be lock unique key name etc in future
                UserDefaults.standard.set(field.text, forKey: "userIP")
                UserDefaults.standard.synchronize()
            } else {
                // user did not fill field - doesnt currently work
                print("no input given")
            }
        }

        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }


        alertController.addTextField { (textField) in
            textField.placeholder = "IP"
        }

        alertController.addAction(confirmAction)
        alertController.addAction(cancelAction)

        self.present(alertController, animated: true, completion: nil)
    }

    //view did appear for the alert
    override func viewDidAppear(_ animated: Bool) {
        presentAlert()
    }


    override func viewDidLoad() {
        super.viewDidLoad()

    }
    var Timestamp: String {
        return "\(NSDate().timeIntervalSince1970 * 1000)"
    }
    func un_lock()
    {
        let u = UserDefaults.standard.value(forKey: "userIP")!
        let url_to_unlock:String = "http://\(u):3000/unLock"
        print(url_to_unlock)
        let url:URL = URL(string: url_to_unlock)!
        let session = URLSession.shared

        let request = NSMutableURLRequest(url: url)
        request.httpMethod = "POST"
        request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData

        //make this work
        let paramString = "data=unLocking at \(Timestamp)"
        request.httpBody = paramString.data(using: String.Encoding.utf8)

        let task = session.dataTask(with: request as URLRequest, completionHandler: {
            (
            data, response, error) in

            guard let _:Data = data, let _:URLResponse = response  , error == nil else {
                print("Error comunicating with server, Check IP")
                return
            }
            //for errors
            let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            print(dataString! )

        })

        task.resume()
    }

    func lock()
    {

        let u = UserDefaults.standard.value(forKey: "userIP")!
        let url_to_lock:String = "http://\(u):3000/Lock"

        let url:URL = URL(string: url_to_lock)!
        let session = URLSession.shared

        let request = NSMutableURLRequest(url: url)
        request.httpMethod = "POST"
        request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData

        //make this work
        let paramString = "data=Locking at \(Timestamp)"
        request.httpBody = paramString.data(using: String.Encoding.utf8)

        let task = session.dataTask(with: request as URLRequest, completionHandler: {
            (
            data, response, error) in

            guard let _:Data = data, let _:URLResponse = response  , error == nil else {
                print("Error comunicating with server, Check IP")
                return
            }
            //for errors
            let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            print(dataString! )

        })

        task.resume()

    }

    //button actions 

    @IBAction func Submit(_ sender: UIButton) {

    }

    @IBAction func lock(_ sender: UIButton) {
        lock()
    }

    @IBAction func unLock(_ sender: Any) {
        un_lock()

    }

I want to know exactly the same thing.我想知道完全相同的事情。 I started with an API tutorial from IFTTT and took a Udemy Node.js course so I started creating the server side first for an iOS app I want to develop.我从 IFTTT 的 API 教程开始,并参加了 Udemy Node.js 课程,所以我首先开始为我想要开发的 iOS 应用程序创建服务器端。

I will be following this post and hopefully someone will be kind enough to help us out.我会关注这篇文章,希望有人能帮助我们。

I did find this tutorial by doing a search so I will be investigating this我确实通过搜索找到了本教程,因此我将对此进行调查

https://www.raywenderlich.com/61264/write-ios-app-uses-node-jsmongodb-web-service https://www.raywenderlich.com/61264/write-ios-app-uses-node-jsmongodb-web-service

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM