使用Angular.js和iOS客户端对Node.js应用程序进行身份validation

我试图尽可能多地阅读不同的答案和post,但是我仍然无法完全满足我的需求。 我正在努力制定出最好的(最有效的,但更加安全)的方式来处理用户身份validation,login等。

我有一个运行在Express上的Node.js服务器; 我有一个Angular.js的Web应用程序; 我有一个iOS应用程序。 我用Express / Node.js公开了一个RESTful API。

cookies

我读到的第一件事就是使用cookie,并在服务器端(哈希)和客户端(非哈希)存储会话ID /login令牌。 客户端会传输这个ID与每个请求,服务器将散列它,parsing它,并相应地处理请求。 这不感觉RESTful(不是一个大问题),但更重要的是,我将不得不复制我的API:一个用户名/密码authentication(例如通过curl完成)和一个基于cookie的authentication(如我的networking应用程序)?

另一个问题:如果我有一个用户的多个连接,我会做什么,例如,他们在两个浏览器,一个iPhone和一个iPadlogin。 我的存储他们的会议ids现在需要一个数组?

HTTP基本身份validation

下一个想法是使用HTTP基本身份validation(使用SSL),这似乎很容易,但不推荐,因为您需要传输用户名和密码与每个请求。 如果我使用HTTP Basic Auth进行操作,那么我会将用户名和密码存储在Cookie(或HTML本地存储)中以允许“记住我”function吗? 或者我可以将两者结合起来:使用HTTP基本身份validation来实际请求(发布新post等),并使用存储在cookie中的会话标识来logging初始日志/记住我的方面?

传输会话ID比传输用户密码更安全吗? 怎么样? 会话ID将会表面上看起来像是一个密码,所以对我来说,传输密码会有和传输密码一样的安全问题。

基本身份validation似乎在所有平台上得到支持,这是理想的。 主要的缺点似乎是需要传输客户端身份validation数据与每个请求。 有没有办法来缓解这个问题?

OAuth的

OAuth似乎是为了我的需要矫枉过正。 我想我会失去执行curl命令来testing我的API的能力。 OAuth如何改进cookie方法?

正如你可能知道的那样,我对可用的各种信息有点困惑,所以如果你有一套适用于这种情况的好链接,我很乐意阅读它们。 我试图find适合所有平台的解决scheme,但仍尽可能安全。 此外,如果我有任何我的术语错误,请纠正我,因为它会使我更容易search。

谢谢。

更新:

我一直在想这个问题,而且我有一个想法。 请告诉我,如果这是愚蠢的/不安全的/任何反馈,因为我不知道这是否是好的。

当用户login时,我们生成一个随机的会话ID(盐渍等)。 这个可选的会话ID被发送到客户端,如果他们select,客户端可以存储(例如在cookie中); 会话ID存储在数据库中。

然后,可以select将此会话标识作为HTTPvalidation标头或查询string与每个请求一起发送,也可以根据需要发送用户名和密码(这给了我们常规的REST API)。 在服务器端,我们首先检查会话ID参数,如果不存在,我们检查用户名/密码。 如果两者都没有错误。

在服务器上,我们检查会话ID是否与正确的用户名关联。 如果是,我们完成请求。

每次用户login时,我们都会创build一个新的会话ID或者删除当前的会话ID,并将这个响应发送给login请求。

我想这可以让我在适当的时候使用常规的REST API和基本身份validation,并保持会话/记住我的function。 它不能解决多个login问题,但否则我认为这种方式应该会。 请告诉我。

我将使用基于令牌的身份validation,您可以在每个请求中自动发送令牌。 您必须login一次,服务器将为您提供一个令牌,然后您可以使用该令牌随每个请求一起发送。 这个令牌将被添加到HTML标头,所以你不必修改每个请求到浏览器。

您可以在API中设置特定的调用,以便始终需要令牌,而其他调用可能不受令牌保护。

对于Express,可以使用express-jwt( https://www.npmjs.org/package/express-jwt

var expressJwt = require('express-jwt'); // Protect the /api routes with JWT app.use('/api', expressJwt({secret: secret})); app.use(express.json()); app.use(express.urlencoded()); 

如果你想authentication你可以在你的快递服务器上创build这个function:

 app.post('/authenticate', function (req, res) { //if is invalid, return 401 if (!(req.body.username === 'john.doe' && req.body.password === 'foobar')) { res.send(401, 'Wrong user or password'); return; } var profile = { first_name: 'John', last_name: 'Doe', email: 'john@doe.com', id: 123 }; // We are sending the profile inside the token var token = jwt.sign(profile, secret, { expiresInMinutes: 60*5 }); res.json({ token: token }); }); 

对于以/ api开头的保护性调用:

 app.get('/api/restricted', function (req, res) { console.log('user ' + req.user.email + ' is calling /api/restricted'); res.json({ name: 'foo' }); }); 

在你的Angular应用程序中,你可以用

 $http .post('/authenticate', $scope.user) .success(function (data, status, headers, config) { $window.sessionStorage.token = data.token; $scope.message = 'Welcome'; }) .error(function (data, status, headers, config) { // Erase the token if the user fails to log in delete $window.sessionStorage.token; // Handle login errors here $scope.message = 'Error: Invalid user or password'; }); 

通过创build一个authentication拦截器,它会自动发送每个请求的令牌:

 myApp.factory('authInterceptor', function ($rootScope, $q, $window) { return { request: function (config) { config.headers = config.headers || {}; if ($window.sessionStorage.token) { config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token; } return config; }, response: function (response) { if (response.status === 401) { // handle the case where the user is not authenticated } return response || $q.when(response); } }; }); myApp.config(function ($httpProvider) { $httpProvider.interceptors.push('authInterceptor'); }); 

如果您必须支持不支持本地存储的旧浏览器。 您可以将$window.sessionStorage与像AmplifyJS( http://amplifyjs.com/ )这样的库交换。 放大例如使用任何本地存储可用。 这会翻译成这样的东西:

  if (data.status === 'OK') { //Save the data using Amplify.js localStorage.save('sessionToken', data.token); //This doesn't work on the file protocol or on some older browsers //$window.sessionStorage.token = data.token; $location.path('/pep'); } }).error(function (error) { // Erase the token if the user fails to log in localStorage.save('sessionToken', null); // Handle login errors here $scope.message = 'Error: Invalid user or password'; }); 

我们交换的authintercepter:

 angular.module('myApp.authInterceptor', ['myApp.localStorage']).factory('authInterceptor', [ '$rootScope', '$q', 'localStorage', function ($rootScope, $q, localStorage) { return { request: function (config) { config.headers = config.headers || {}; config.headers.Authorization = 'Bearer ' + localStorage.retrieve('sessionToken'); return config; }, response: function (response) { if (response.status === 401) { } return response || $q.when(response); } }; } ]); 

你可以在这篇文章中findAmplifyJS以外的所有东西:

http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/

看看yeoman发电机的angular度和节点? 发生器 – angular – 满堆使用护照进行用户authentication的结构非常好。

你可以在这里看到一个例子:

代码: https : //github.com/DaftMonk/fullstack-demo

结果: http : //fullstack-demo.herokuapp.com/

希望能帮助到你!

我使用generator-angular-fullstack,/ api服务不安全,从/ api / users / me取得你的_id,注销,并进入/ api / users / your_id_here,你会发现/ api没有安全。