之前可能已经问过这个问题,所以我先发制人地道歉。
我建立了一个网站,并建立了一个 API。该 API 将来也将被移动应用程序使用。我拥有两者,所以我很确定两条腿和三条腿的 OAuth 不适合我。 API 具有可供全世界访问的部分以及 protected 且需要用户帐户的其他部分。为了简单起见,我刚刚使用了 https + 基本身份验证解决方案(目前)。手动测试 API 的请求时一切正常(我没有编写测试,因为我是一个坏人),事情按预期工作,基本身份验证很好。
我正在尝试解决用户使用纯文本用户和密码登录的流程,将其发送到 API 进行身份验证,API 只需要说是或否,但来自站点的所有请求(代表用户)当他们想要 POST/GET/PUT/DEL protected 资源之一时,应使用他们的凭据以某种方式对 API 进行签名。
在我读过的所有身份验证资源中,我仍然对使用什么方案感到困惑。在站点端存储明文密码以便我可以对它进行 base 64 编码并通过网络发送它似乎很糟糕,但看起来这就是我必须做的。我读过摘要认证,但我不确定我是否明白。欢迎任何和所有建议。
最佳答案
这就是我处理这个案子的方式;
Authentication
标题,带有 Bearer [JWT]
不要害怕 JWT,每种语言和框架都有很多实现,而且比您想象的要容易。许多应用程序已经在使用 JWT,甚至谷歌。
Auth0是一个身份验证代理,可以针对任何身份提供者或自定义数据库进行验证,并返回 JWT。它提供可用于解码前端配置文件的客户端 ID 和用于验证后端 token 的 key 以及 client side library去做这个。
免责声明:我为 auth0 工作。
更新:既然你提到 node.js 并在评论中表达,我将在这项技术中举一个例子。
var http = require('http');
var express = require('express');
var jwt = require('jsonwebtoken'); //https://npmjs.org/package/node-jsonwebtoken
var expressJwt = require('express-jwt'); //https://npmjs.org/package/express-jwt
var secret = "this is the secret secret secret 12356";
var app = express();
app.configure(function () {
this.use(express.urlencoded());
this.use(express.json());
this.use('/api', expressJwt({secret: secret}));
});
//authentication endpoint
app.post('/authenticate', function (req, res) {
//validate req.body.username and req.body.password
//if is invalid, return 401
var profile = {
first_name: 'John',
last_name: 'Foo',
email: 'foo@bar.com',
id: 123
};
var token = jwt.sign(profile, secret, {
expiresInMinutes: 60*5
});
res.json({
token: token
});
});
//protected api
app.get('/api/something', function (req, res) {
console.log('user ' + req.user.email + ' is calling /something');
res.json({
name: 'foo'
});
});
//sample page
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
http.createServer(app).listen(8080, function () {
console.log('listening on http://localhost:8080');
});
这是一个带有一个端点的快速应用程序,用于验证用户名和密码。如果凭据有效,它将返回具有完整配置文件的 JWT token ,有效期为 5 小时。
然后我们在
/api/something
中有一个示例端点但是因为我在 /api
上有一个用于所有内容的 express-jwt 中间件它需要一个带有有效 token 的 Authorization: Bearer header 。中间件不仅会验证 token ,还会解析配置文件并将其放在 req.user 上。如何使用这个客户端?这是一个 jquery 的例子:
//this is used to parse the profile
function url_base64_decode(str) {
var output = str.replace("-", "+").replace("_", "/");
switch (output.length % 4) {
case 0:
break;
case 2:
output += "==";
break;
case 3:
output += "=";
break;
default:
throw "Illegal base64url string!";
}
return window.atob(output); //polifyll https://github.com/davidchambers/Base64.js
}
var token;
//authenticate at some point in your page
$(function () {
$.ajax({
url: '/authenticate',
type: 'POST',
data: {
username: 'john',
password: 'foo'
}
}).done(function (authResult) {
token = authResult.token;
var encoded = token.split('.')[1];
var profile = JSON.parse(url_base64_decode(encoded));
alert('Hello ' + profile.first_name + ' ' + profile.last_name);
});
});
//send the authorization header with token on every call to the api
$.ajaxSetup({
beforeSend: function(xhr) {
if (!token) return;
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
}
});
//api call
setTimeout(function () {
$.ajax({
url: '/api/something',
}).done(function (res) {
console.log(rest);
});
}, 5000);
首先,我使用用户名和密码进行身份验证调用,我可以解码 JWT 中的配置文件以获取用户配置文件,并且我还保存 token 以供以后在每个请求中使用。
ajaxSetup/beforeSend 技巧为每次调用添加 header 。所以,然后我可以向/api/something 发出请求。
可以想象,这种方法不使用 cookie 和 session ,因此它在 CORS 场景中开箱即用。
我是passport.js 的忠实粉丝,我为其他一些适配器贡献了很多适配器和修复程序,但对于这种特殊情况,我不会使用它。
关于authentication - 网站和自有API之间的身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20793902/