使用Angular.js和iOS客户端对Node.js应用进行身份验证
我试图尽可能多地阅读不同的答案和帖子,但是我仍然不能完全满足我的需求。我正在努力解决用户身份验证,登录等方面最好的(最有效率,但更安全)的方式。
我有一个Node.js服务器,在Express上运行;我有一个Angular.js网络应用程序我有一个iOS应用程序。我用Express / Node.js公开了一个RESTful API。 饼干 我读过的第一件事就是使用cookies,并在服务器端(散列)和客户端(未分配)上存储会话ID /登录令牌。客户端将会传送每个请求的id,服务器会将其哈希,解析并相应地处理该请求。这不是RESTful(不是一个巨大的问题),但更重要的是,我必须复制我的API:一个用于用户名/密码认证(例如通过curl完成),一个用于基于cookie的身份验证(例如我的网络应用程序)? 另一个问题是:如果我有一个用户的多个连接,我会做什么,例如他们登录在两个浏览器,一个iPhone和一个iPad。我的存储的会话ids需要现在是一个数组? HTTP基本认证 接下来的想法是使用HTTP Basic Auth(使用SSL),这似乎很简单,但不推荐,因为您需要在每个请求中传输用户名和密码。如果我使用HTTP Basic Auth进行操作,那么我会将用户名和密码存储在cookie(或HTML本地存储)中,以允许“记住我”功能吗?或者我可以组合这两个:使用HTTP Basic Auth进行实际请求(发布新的帖子等),并且只使用存储在cookie中的会话ID来初始化日志/记住我的方面? 正在传送会话ID比只传送用户密码更安全吗?怎么样? 基本认证似乎在所有平台上得到支持,这是理想的。主要的缺点似乎是需要每个请求传输客户端认证数据。有办法缓解这个问题吗? OAuth的 OAuth似乎对我的需要是过分的。我想我将失去卷曲命令测试我的API的能力。如何将OAuth作为Cookie方法的改进? 你可能会告诉我,我有点混淆了不同的信息,所以如果你有一套良好的链接 – 适用于这种情况 – 我很想读它们。我试图找到一个适合所有平台的解决方案,但仍然尽可能安全。此外,如果我的任何术语错误,请纠正我,因为它会使我的搜索变得更容易。 谢谢。 更新: 我一直在想这个问题,我有一个想法。请告诉我,如果这是愚蠢/不安全/任何反馈,因为我不知道这是否好。 当用户登录时,我们生成一个随机会话ID(盐渍等)。该可选会话ID被发送到客户端,客户端可以存储(例如,在Cookie中)如果他们选择;会话ID存储在数据库中。 然后,可以将此会话ID作为HTTP身份验证头或查询字符串作为每个请求发送,或者客户端可以根据需要发送用户名和密码(这给我们提供了常规的REST API)。在服务器端,我们首先检查一个session id参数,如果不存在,我们检查用户名/密码。如果没有 – 错误。 在服务器上,我们检查会话ID是否与正确的用户名相关联。如果是,我们完成请求。 每次用户登录时,我们创建一个新的会话ID或删除当前的会话ID,并将其发送给响应请求。 我认为这可以让我在适当的时候使用常规REST API和基本身份验证,并维护会话/记住我的功能。它不解决多个登录问题,但否则我认为这样应该会。请告诉我。
我将使用基于令牌的身份验证,您可以在每个请求中自动发送令牌(自动)。您必须登录一次,服务器将为您提供一个令牌,然后您可以使用每个请求发送。该标记将被添加到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()); 如果要进行身份验证,您可以在快速服务器中创建此功能: 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',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,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'; }); 并通过创建一个身份验证拦截器,它将自动发送令牌与每个请求: 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'); }); 如果您必须支持不支持本地存储的旧浏览器。您可以使用像AmplifyJS(http://amplifyjs.com/)这样的库来交换$ window.sessionStorage。扩大例如使用任何本地存储可用。这将会像这样翻译: 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'; }); 和我们交换的authinterpter: angular.module('myApp.authInterceptor',['myApp.localStorage']).factory('authInterceptor',[ '$rootScope','$q','localStorage',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); } }; } ]); 您可以在本文中找到除AmplifyJS之外的所有内容: http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-token/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |