首页
话题
消息
手册
我的

Node-openid 基于 Node.js 实现的 OpenID 协议

发布于 2019-09-07 字数 6861 浏览 771 评论 0

OpenID 的创建基于这样一个概念:我们可以通过 URI (又叫 URL 或网站地址)来认证一个网站的唯一身份,同理我们也可以通过这种方式来作为用户的身份认证。由于 URI 是整个网络世界的核心,它为基于 URI 的用户身份认证提供了广泛的、坚实的基础。

Node-openid 是一个基于 Node.js 实现的 OpenID 协议。

特点

  • 全面支持 OpenID 1.1/OpenID 2.0 协议的第三方扩展库
  • 非常简单的 API 接口
  • 易于扩展和使用

安装

如果你使用 npm 你可以运行下面的代码安装 Node-openid

npm install openid

如果你喜欢自己动手安装,你可以访问 Node-openid 的 Github 地址,然后下载到您的本地项目目录中,解压下载的 Node-openid 源文件,将 lib 文件夹和 openid.js 文件移动到你的项目目录中,使用 require(‘openid’) 语句引入插件并使用,记得在你的目录把文件做 require.paths.unshift 除非它已经在你的 require.paths。

简单示例

这是使用 Node.js 认证 OpenID 的一个非常简单的服务器端示例:

var relyingParty = new openid.RelyingParty(
    'http://example.com/verify', // Verification URL (yours)
    null, // Realm (optional, specifies realm for OpenID authentication)
    false, // Use stateless verification
    false, // Strict mode
    []); // Optional list of extensions to enable and include


var server = require('http').createServer(
    function(req, res){
        var parsedUrl = url.parse(req.url);
        if(parsedUrl.pathname == '/authenticate'){ 
          // User supplied identifier
          var query = querystring.parse(parsedUrl.query);
          var identifier = query.openid_identifier;

          // Resolve identifier, associate, and build authentication URL
          relyingParty.authenticate(identifier, false, function(error, authUrl){
            if(error){
              res.writeHead(200, { 'Content-Type' : 'text/plain; charset=utf-8' });
              res.end('Authentication failed: ' + error.message);
            }else if (!authUrl){
              res.writeHead(200, { 'Content-Type' : 'text/plain; charset=utf-8' });
              res.end('Authentication failed');
            }else{
              res.writeHead(302, { Location: authUrl });
              res.end();
            }
          });
        }else if(parsedUrl.pathname == '/verify'){
          // Verify identity assertion
          // NOTE: Passing just the URL is also possible
          relyingParty.verifyAssertion(req, function(error, result){
            res.writeHead(200, { 'Content-Type' : 'text/plain; charset=utf-8' });

            if(error){
              res.end('Authentication failed: ' + error.message);
            }else{
              res.end((result.authenticated ? 'Success :)' : 'Failure :(') +
                '\n\n' + JSON.stringify(result));
            }
          });
        }else{
            // Deliver an OpenID form on all other URLs
            res.writeHead(200, { 'Content-Type' : 'text/html; charset=utf-8' });
            res.end('<!DOCTYPE html><html><body>'
                + '<form method="get" action="/authenticate">'
                + '<p>Login using OpenID</p>'
                + '<input name="openid_identifier" />'
                + '<input type="submit" value="Login" />'
                + '</form></body></html>');
        }
    });
server.listen(80);

一个更复杂的例子包括扩展可以在 GitHub 库 sample.js 发现。

支持扩展

这个库是为下面的内置支持 OpenID 的扩展:

  • The Simple Registration (SREG) 1.1 extension is implemented as openid.SimpleRegistration.
  • The Attribute Exchange (AX) 1.0 extension is implemented as openid.AttributeExchange.
  • The OAuth 1.0 extension is implemented as openid.OAuthHybrid.
  • The User Interface 1.0 extension is implemented as openid.UserInterface.
  • The Provider Authentication Policy Extension 1.0 (PAPE) is implemented as openid.pape.

存储关联状态

为保存/加载关联状态提供了一种方法,你需要混合在 OpenID 的模块功能:

  • saveAssociation(provider, type, handle, secret, expiry_time_in_seconds, callback) is called when a new association is established during authentication. The callback should be called with any error as its first argument (or null if no error occured).
  • loadAssociation(handle, callback) is used to retrieve the association identified by handle when verification happens. The callback should be called with any error as its first argument (and null as the second argument), or an object with the keys provider, type, secret if the association was loaded successfully.

OpenID 模块包括默认实现这些函数使用一个简单的对象存储在内存中的关联。

缓存信息

验证的一个积极的断言(即一个身份验证的用户),可以加快速度显着,避免需要额外的供应商发现时,可能。为了达到这个速度,节点,OpenID 需要缓存的发现者。可以用2个函数组合来重写默认的缓存,这是一个在内存中使用一个简单对象存储的缓存:

  • saveDiscoveredInformation(key, provider, callback) is used when saving a discovered provider. The following behavior is required:
    • The key parameter should be uses as a key for storing the provider – it will be used as the lookup key when loading the provider. (Currently, the key is either a claimed identifier or an OP-local identifier, depending on the OpenID context.)
    • When saving fails for some reason, callback(error) is called with error being an error object specifying what failed.
    • When saving succeeds, callback(null) is called.
  • loadDiscoveredInformation(key, callback) is used to load any previously discovered information about the provider for an identifier. The following behavior is required:
    • When no provider is found for the identifier, callback(null, null) is called (i.e. it is not an error to not have any data to return).
    • When loading fails for some reason, callback(error, null) is called with error being an error string specifying why loading failed.
    • When loading succeeds, callback(null, provider) is called with the exact provider object that was previously stored using saveDiscoveredInformation.

相关链接

如果你对这篇文章有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助。

扫码二维码加入Web技术交流群

您暂时不能评论!

管理员开启了需要登录才能够评论,你可以免费注册一个本站的账号。

还没有评论!

目前还没有任何评论,快来抢沙发吧!