如何使用适用于 iOS 的 swift 3 连接到 MEAN 堆栈 REST api
Posted
技术标签:
【中文标题】如何使用适用于 iOS 的 swift 3 连接到 MEAN 堆栈 REST api【英文标题】:How to connect to MEAN stack REST api using swift 3 for iOS 【发布时间】:2017-05-22 07:11:59 【问题描述】:我正在尝试使用 ios 创建一个简单的登录应用程序,它使用一个 MEAN 堆栈服务器公开一个 REST API 供 iOS 端连接。
我一直在服务器端工作,并且有一个 API,它允许使用电子邮件和密码创建用户。按照本教程,我还创建了 DELETE 和 GET 请求: https://codeforgeek.com/2015/08/restful-api-node-mongodb/
但是,我不确定现在如何在 iOS 端使用此信息登录。 我有几个问题是:
我需要创建一个令牌让 iOS 端接受吗? 我需要验证方法吗?我在下面包含了用于服务器和 iOS 端的代码。
我对这两种语言都很陌生,因此我们将不胜感激。 先感谢您。
app.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
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
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
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 该文件当前要求提供服务器 IP,并允许发出后解锁和锁定请求,我将在未来添加数据。
我想让这个视图只能通过以有效用户身份登录到服务器并呈现给它来访问。
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()
【问题讨论】:
【参考方案1】:我想知道完全相同的事情。我从 IFTTT 的 API 教程开始,并参加了 Udemy Node.js 课程,因此我首先开始为我想要开发的 iOS 应用程序创建服务器端。
我会关注这篇文章,希望有人能帮助我们。
我确实通过搜索找到了本教程,因此我将对此进行调查
https://www.raywenderlich.com/61264/write-ios-app-uses-node-jsmongodb-web-service
【讨论】:
我已经看过了,如果我没记错的话,它会使用objective-c来实现。另外,我可以发送 POST 请求。我主要关心的是是否需要某种令牌? 我决定使用令牌系统并实现了一个返回 JWT 令牌的身份验证方法,我现在需要实现一个方法来检查令牌是否有效。以上是关于如何使用适用于 iOS 的 swift 3 连接到 MEAN 堆栈 REST api的主要内容,如果未能解决你的问题,请参考以下文章
expo ios 模拟器“无法连接到开发服务器”错误(适用于浏览器)
Swift iOS - 如何将 UIPopoverBackgroundView 类中的方法连接到不同类中的 PopoverController?
Swift iOS 应用程序不使用 Socket.IO 连接到服务器