我尝试阅读尽可能多的不同答案和帖子,但是我仍然不能完全满足自己的需求。我正在尝试找出处理用户身份验证,登录等的最佳方法(最有效,但大多数情况下更安全)。
我有一个运行在Express上的Node.js服务器;我有一个Angular.js网络应用程序;而且我有一个iOS应用。我使用Express /Node.js公开了RESTful API。
我读到的第一件事是使用cookie,并在服务器端(已哈希)和客户端(未哈希)存储会话ID
/登录令牌。客户端将随每个请求一起传输此ID,服务器将对其进行哈希处理,解析并相应地处理请求。这感觉不是RESTful(不是一个大问题),但是更重要的是,我是否必须复制我的API:一个用于用户名/密码身份验证(例如,通过curl进行)和一个用于基于cookie的身份验证(例如,我的Web应用程序)?
另一个问题是:如果一个用户有多个连接,我该怎么办,例如,他们用两个浏览器(iPhone和iPad)登录。现在,我需要将其会话ID的存储空间存储为数组吗?
下一个想法是使用HTTP基本身份验证(带有SSL),这似乎很容易,但是不建议您这样做,因为您需要在每个请求中传递用户名和密码。如果要使用HTTPBasicAuth进行操作,我是否会将用户名和密码存储在cookie(或HTML本地存储)中以允许“记住我”功能?还是我可以将两者结合起来:对实际请求使用HTTP
Basic Auth(发布新帖子等),而仅将存储在cookie中的会话ID用于序列中的初始日志/还记得我方面吗?
传输会话ID是否比仅传输用户密码更安全?怎么样?会话ID表面上将充当密码,因此对我来说,传输它与传输密码具有相同的安全性问题。
似乎所有平台都支持基本身份验证,这是理想的选择。主要的缺点似乎是每个请求都需要传输客户端身份验证数据。有没有办法减轻这个问题?
OAuth似乎对我的需求而言过于刻薄。我想我会失去执行curl命令来测试API的能力。OAuth与cookie方法相比有何改进?
您可能会说,我对可用的各种信息有些困惑,因此,如果您有一组适用于这种情况的良好链接,我希望阅读它们。我正在尝试找到适合所有平台的解决方案,但仍要尽可能地安全。另外,如果我的术语有误,请更正我,因为这会使我的搜索更加容易。
谢谢。
我一直在思考这个问题,并且已经有了一个主意。请告诉我这是否是愚蠢的/不安全的/任何反馈,因为我不确定这是否好。
当用户登录时,我们会生成一个随机的会话ID(加盐等)。这个 可选的
会话ID被发送给客户端,客户端可以选择将其存储(例如,存储在cookie中)。会话ID存储在数据库中。
然后,可以选择将该会话ID与每个请求一起作为HTTP身份验证标头或查询字符串
发送,或者如果需要,客户端可以只发送用户名和密码(这为我们提供了常规的REST
API)。在服务器端,我们首先检查会话ID参数,如果不存在,则检查用户名/密码。如果两者都不存在,那就是错误。
在服务器上,我们检查会话ID是否与正确的用户名相关联。如果是,我们将完成请求。
每次用户登录时,我们都会创建一个新的会话ID或删除当前的会话ID,并将其与响应一起发送至登录请求。
我认为这可以让我在适当的情况下使用带有Basic Auth的常规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', 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';
});
通过创建身份验证拦截器,它将随每个请求自动发送令牌:
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);
}
};
}
]);
您可以在本文中找到除AmplifyJS之外的所有内容:
http://blog.auth0.com/2014/01/07/angularjs-authentication-with-cookies-vs-
token/
如何用Apache CXF实现这一点?
问题内容: 我想使用带有身份验证的其余api。我正在尝试包括标头,但没有得到任何回应。它抛出的输出通常是在没有身份验证时抛出的。谁能建议我一些解决方案。下面是我的代码 问题答案: 该请求模块将使您的生活更轻松。现在,它包括“ 基本身份验证”作为选项,因此您不必自己构建标题。 安装请求执行
有什么主意吗?
问题内容: 我需要导入证书,以便向Spring Boot应用程序中的外部服务发出http请求。 我该如何设置Spring Boot来做到这一点? 那里有很多信息,但我发现所有这些都令人困惑。似乎我可能只需要创建类似“ truststore.jks”密钥库的内容并导入正确的证书,然后将一些条目添加到我的application.properties中即可。 问题答案: 打开您的终端或 回答所有问题。在
问题内容: 我已经通过使用nodejs + express制作了简单的nodejs应用程序。现在,我要进行用户身份验证。我想通过使用猫鼬来实现会话处理。你能举个例子吗? 问题答案: 一些有用的链接: 如何在node.js中实现登录身份验证 在node.js和mongodb中创建注册和登录表单 另外,会话管理不是由Mongoose完成,而是由connect-mongodb或connect- redi
问题内容: 解析服务器提供OAuth身份验证。如何使用Parse Server的预定义OAuth模块(例如Facebook)来注册新用户或登录“ _User”类的现有用户? Parse Server 文档提供了有关如何配置OAuth模块的示例。但是,如何在iOS项目中使用它来登录或注册用户? 问题答案: 1,创建一个从NSObject和PFUserAuthenticationDelegate扩展的