网站与自有API之间的认证

2024-02-09

以前可能有人问过这个问题,所以我先致歉。

我建立了一个网站并建立了一个 API。该 API 将来也将被移动应用程序使用。我两者都拥有,所以我很确定两条腿和三条腿的 OAuth 不适合我。 API 的部分内容可供全世界访问,而其他部分则受到保护并需要用户帐户。为了简单起见,我刚刚使用了 https + Basic Auth 解决方案(目前)。当手动测试 API 请求时,一切都很好(我没有编写测试,因为我是一个坏人),一切按预期工作,基本身份验证也很好。

我正在尝试解决用户使用明文用户名和密码登录的流程,将其发送到 API 进行身份验证,API 只需要说是或否,但来自站点的所有请求(代表用户)当他们想要 POST/GET/PUT/DEL 受保护资源之一时,应使用其凭据以某种方式对 API 进行签名。

在我读过的所有身份验证资源中,我仍然对使用什么方案感到困惑。将明文密码存储在站点端,以便我可以对其进行 Base 64 编码并通过网络发送,这似乎很糟糕,但看起来这就是我必须做的。我读过摘要验证,但我不确定我是否明白。欢迎任何和所有建议。


这就是我处理这个案子的方式;

  1. 当然,使用 HTTPS 将用户名和密码以纯文本形式发布到您的 api。
  2. 然后将其验证到您的数据库,当今用于对密码加盐的最佳算法是bcrypt.
  3. 如果用户无效返回 401 或其他。
  4. 如果用户有效,则返回 JWT 令牌及其使用公钥算法签名的个人资料。
  5. 您的前端知道公钥,因此可以解码 JWT,但无法生成新的公钥。
  6. 对于每个需要身份验证的请求,您都附加一个Authentication标头,带有Bearer [JWT]
  7. 后端的中间件读取此标头并使用私钥对其进行验证。

不要害怕 JWT,每种语言和框架都有大量的实现,并且比您想象的要容易。许多应用程序甚至 Google 都已经在使用 JWT。

Auth0 https://www.auth0.com是一个身份验证代理,可以针对任何身份提供商或自定义数据库进行验证,并返回 JWT。它提供了一个可用于在前端解码配置文件的 clientID 和一个用于在后端验证令牌的密钥以及客户端库 https://github.com/auth0/auth0.js去做这个。

免责声明:我为 auth0 工作。

Update:既然你在评论中提到了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: '[email protected] /cdn-cgi/l/email-protection',
    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 令牌,有效期为 5 小时。

然后我们有一个示例端点/api/something但因为我有一个express-jwt中间件来处理所有事情/api它需要一个 Authorization: Bearer 标头和一个有效的令牌。中间件不仅验证令牌,还解析配置文件并将其放在 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 中的配置文件以获取用户配置文件,并且我还保存令牌以便稍后在每个请求中使用。

ajaxSetup/beforeSend 技巧为每个调用添加标头。那么,我就可以向 /api/something 发出请求。

正如您可以想象的那样,这种方法不使用 cookie 和会话,因此它在 CORS 场景中开箱即用。

我是 Passport.js 的忠实粉丝,我为其他一些适配器贡献了很多适配器和修复程序,但对于这种特殊情况,我不会使用它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网站与自有API之间的认证 的相关文章

随机推荐

  • 如何停止正在运行的线程?

    from pyautogui import moveTo click rightClick write keyDown keyUp hotkey scroll import pyautogui import pyperclip import
  • 寻找 IPFW 以外的替代解决方案来减慢互联网连接速度

    我需要减慢 模拟坏的 互联网连接 我发现了一些文档 其中它是通过 ipfw pipeline 命令实现的 问题是在最新的 MAC OS 版本中 ipfw 已被弃用 并删除 我想知道 ipfw API 是否有其他替代方案 有谁知道最新的网络链
  • java 中什么样的全局变量是不好的做法?

    对于我的许多java项目 我广泛使用数据库 我通常做的是有一个property xml文件来保存我所有的字符串和设置 然后我就去上课CNST保存与 xml 文件中的静态常量相对应的所有静态常量 这些常量在程序启动时由 xml 文件初始化一次
  • 如何设置 Rake 任务进行播种

    这确实是一个关于 Rake Rails 以及一般依赖关系的新手问题 尝试让我的头脑了解所有这些如何组合在一起 基本上 我想要一个像 Seed rb 一样但单独调用的 Rake 任务 它添加了开发环境的测试数据 而我的seed rb则提供了所
  • getsockopt IPPROTO_SCTP、SCTP_STATUS 的“无效参数”

    设想 我创建了 SCTP 一对多套接字 以大写字母开头的函数调用相应的标准函数 检查错误并将 errno 打印到 stderr int sock fd msg flags char readbuf BUFFSIZE struct socka
  • DataGridComboBoxColumn 数据绑定

    我正在尝试数据绑定DataGridComboBoxColumn
  • 在 Java 中查找不可序列化字段的好方法

    我有一个相当复杂的 Java 对象需要序列化 几周前运行良好 在同时实现了很多之后 序列化现在失败并抛出以下异常 java io NotSerializableException sun java2d SunGraphics2D 我检查了所
  • 在自然断点处分割字符串

    在渲染标题时 使用 reportlab 如果标题长度超过 45 个字符 我想将其拆分为两行 到目前为止我有这个 if len Title lt 45 drawString 200 695 Title else drawString 200
  • UIManagedDocument 中核心数据对象的状态保存和恢复策略

    我开始尝试向我的 iOS 应用程序添加对状态保存和恢复的支持 该应用程序有一个核心数据组件 我可以通过 UIManagedDocument 访问该组件 我开始将恢复标识符添加到我的视图控制器中 并在我的 AppDelegate 和控制器中连
  • 完成处理程序 swift 3 从函数返回一个变量

    我对 swift 3 中完成处理程序的语法感到困惑 在下面的函数中 解析后xml来自 Web 服务调用的文件 它应该返回一个变量 array String String 我的尝试如下 但显然这是不正确的 enum HistoryKey ca
  • header("Location: ...) 之后的代码是否执行?

    SESSION some value 4 header Location another file php SESSION some value 5 有什么价值 SESSION some value 值为 5 您可以输出更多的标头 而不仅仅
  • 从 python 中的 for 循环返回值

    我试图找出在 for 循环语法中将参数从一个列表或字典传递到另一个列表或字典的语法 我正在寻找的期望结果是这样的 for bean in beans if bean type coffee print bean 只是 我不想打印到标准输出
  • 在java中将图像作为文本发送

    是否可以将图像读取为文本并通过网络发送 是的 那么我们该怎么做呢 您可以对图像进行 Base64 编码以生成 文本 字符串 Apache Commons Codec 有 Base64 实现 http commons apache org c
  • 更新到23.3.0后Android支持库错误

    我一直在使用 android support v4 23 1 1 最近尝试将其更新到 23 3 0 被问及时的最新版本 但出现以下错误 错误 与依赖项 com android support support annotations 冲突 应
  • 在后台检测 python 中的按键

    我正在尝试找到一种方法来检测按键 然后根据按键运行一个方法 我已经可以使用 Tkinter 做到这一点 但我不能做的是在窗口处于后台时检测按键 当我玩游戏时 我将在后台运行这个程序 我需要它能够在我玩游戏时检测输入 有什么办法可以用 Tki
  • QtDbus 无法在 Windows 7 上的 Qt5.4.1 中工作

    当我运行 Qt Creator dbus 示例时 它们无法运行 是否有任何用于工作 QtDbus 模块的设置或内容或任何先决条件 例如在chat项目 if QDBusConnection sessionBus isConnected qWa
  • 使用实体框架连接多个表

    我正在尝试使用 EF 连接 3 个表 但它会抛出错误 consider swaping conditions on either side of equals 请有人帮忙吗 var billdata from billtotal in co
  • 如何将 favicon 与 ember-cli 一起使用?

    我的索引模板上有一个图标工作了一段时间 但没有任何其他模板 现在甚至我的索引模板也不会显示它 我刚刚处于开发阶段 所以我正在使用ember server 索引 html 只需四处看看我的图标 看看它是否出现在任何地方 我现在将它放在以下位置
  • 传递 kwargs 列表?

    为了简洁起见 我可以将 kwargs 列表传递给方法吗 这就是我正在尝试做的事情 def method kwargs do something keywords keyword1 foo keyword2 bar method keywor
  • 网站与自有API之间的认证

    以前可能有人问过这个问题 所以我先致歉 我建立了一个网站并建立了一个 API 该 API 将来也将被移动应用程序使用 我两者都拥有 所以我很确定两条腿和三条腿的 OAuth 不适合我 API 的部分内容可供全世界访问 而其他部分则受到保护并