使用 Lua 完成 OAuth2 的身份验证

本文讲的是使用 Lua 完成 OAuth2 的身份验证,


在此说明该教程将不提供详细的技术指导,教您如何使用 OpenResty + Lua 构建自己的认证层,而是讲解一下解决方案背后的处理过程。

这是一个真实的案例:moltin's API 如何依赖 OpenResty + Lua 来为所有的用户处理 oauth2 身份认证

用于验证用户的方法最初是被在运用在 PHP 框架 Laravel 所搭建的 moltin 相关的 API 当中。这就意味着在认证身份、驳回请求或验证消息从而导致高度延时的用户请求之前需启动大量的代码。

我不会详细地去介绍一个PHP框架需要花多长时间才能给出一个基本响应,但如果我们将它和其他语言/框架进行比较,也许你就可以理解相关的差异。

以下是它所呈现的大致情景:

...
public function filter($route, $request) {
    try {
        // Initiate the Request handler
        $this->request = new OAuthRequest;
        // Initiate the auth server with the models
        $this->server  = new OAuthResource(new OAuthSession);
        // Is it a valid token?
        if ($this->accessTokenValid() == false) {
            throw new InvalidAccessTokenException('Unable to validate access token');
        }
...

那么,我们决定将所有逻辑提升一层至 OpenResty + Lua ,便能实现如下几点:

  • 解除与Monolitic API之间的耦合关系。
  • 改进认证次数和生成的访问/刷新令牌。
  • 改进拒绝非法访问令牌和身份验证证书的次数。
  • 改进身份验证访问令牌时的次数和重定向后再次向API发送请求的次数。

我们希望并需要在请求 API 之前更好地控制每个请求,因此我们决定采用速度足够快的工具,使我们能对每个请求进行预处理,并可以十分灵活地将它们集成到我们的实际系统中。最终,我们选择了 OpenResty(一个 Nginx 的修改版本),这使得我们可以使用 Lua 来预先处理这些请求。因为 Lua 强大并且速度快,足以解决这些问题,并且 Lua 是许多大公司每天都在使用的一种受到高度认可的脚本语言。

我们跟随Kong背后的思想使用 OpenResty + Lua 脚本,Kong 提供了一些可插入到你的API项目中的微服务。然而,我们发现Kong仍处于一个非常初期的阶段,实际上kong正在试图提供更多我们需要的东西。因此,我们决定实现自己的验证层,使我们对它有更多的控制权。

基础架构

moltin 当前的基础架构

  • OpenResty (Nginx)
  • Lua scripts
  • Caching Layer (Redis)

OpenResty

这是一些配置的规则

我们设置了一些路由来处理不同用户的请求,你可以看到如下情况:

nginx.conf

location ~/oauth/access_token {
    ...
}
location /v1 {
    ...
}

So for each of those endpoints we have to:

  • check the authentication access token
  • get the authentication access token

    ... location ~/oauth/access_token { content_by_lua_file "/opt/openresty/nginx/conf/oauth/get_oauth_access.lua"; ... }

    location /v1 { access_by_lua_file "/opt/openresty/nginx/conf/oauth/check_oauth_access.lua"; ... } ...

我们利用OpenResty的这两条指令 content_by_lua_file 和access_by_lua_file

Lua 脚本

这是个不可思议的环节。我们需要编写两个lua脚本来做到这一点:

get_oauth_access.lua

...
ngx.req.read_body()
args, err = ngx.req.get_post_args()

-- If we don't get any post data fail with a bad request
if not args then
    return api:respondBadRequest()
end

-- Check the grant type and pass off to the correct function
-- Or fail with a bad request
for key, val in pairs(args) do
    if key == "grant_type" then
        if val == "client_credentials" then
            ClientCredentials.new(args)
        elseif val == "password" then
            Password.new(args)
        elseif val == "implicit" then
            Implicit.new(args)
        elseif val == "refresh_token" then
            RefreshToken.new(args)
        else
            return api:respondForbidden()
        end
    end
end

return api:respondOk()
...

check_oauth_access.lua

...
local authorization, err = ngx.req.get_headers()["authorization"]

-- If we have no access token forbid the beasts
if not authorization then
    return api:respondUnauthorized()
end

-- Check for the access token
local result = oauth2.getStoredAccessToken(token)

if result == false then
    return api:respondUnauthorized()
end
...

缓存层

在这创建并且存储访问的令牌。我们可以按照自己的意愿对其进行删除、终止或刷新。我们将Redis作为存储层,使用openresty/lua-resty-redis 把Lua连接到Redis上。

资源

以下是我们在创建验证层时所用到的一些与Lua相关的有趣资源。





原文发布时间为:2016年01月07日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2024-10-15 18:31:15

使用 Lua 完成 OAuth2 的身份验证的相关文章

窃取 OAuth 令牌绕过 Airbnb 身份验证

本文讲的是窃取 OAuth 令牌绕过 Airbnb 身份验证,登录过程中的CSRF与Airbnb的OAuth登录流程中的基于HTTP Referer头的开放重定向跳转漏洞相结合,可能会被用来窃取所有的Airbnb身份提供商的OAuth访问令牌,并最终确定Airbnb网站和移动应用程序的受害者.这种攻击并不依赖于特定的OAuth身份提供程序的应用程序配置缺陷(例如白名单redirect_uri 的URL中的通配符),这对所有的Airbnb的身份提供者(包括Facebook和Google)都是通用的

如何通过SQL Server2000使用Forms 身份验证

  摘要 ASP.NET Forms 身份验证允许用户将凭据(用户名和密码)输入到 Web Form 来标识其身份.在收到这些凭据时,Web 应用程序可以根据数据源来检查这些凭据,从而对用户进行身份验证. 本模块描述如何使用密码哈希安全地将用户凭据存储在 SQL Server 中,以及如何根据包含在 SQL Server 中的帐户数据库对用户进行身份验证. 预备知识 安全地存储用户凭据包含两个关键概念: • 存储密码摘要.出于安全性考虑,请不要将密码明文存储在数据库中.本模块描述如何创建和存储用

ASP.NET七大身份验证方式及解决方案

在B/S系统开发中,经常需要使用"身份验证".因为web应用程序非常特殊,和传统的C/S程序不同,默认情况下(不采用任何身份验证方式和权限控制手段),当你的程序在互联网/局域网上公开后,任何人都能够访问你的web应用程序的资源,这样很难保障应用程序安全性.通俗点来说:对于大多数的内部系统.业务支撑平台等而言,用户必须登录,否则无法访问和操作任何页面.而对于互联网(网站)而言,又有些差异,因为通常网站的大部分页面和信息都是对外公开的,只有涉及到注册用户个人信息的操作,或者网站的后台管理等

asp.net里面的身份验证和授权

今天闲着无聊.想起来了ASP.NET身份验证.感觉良好.贴出下列代码:login.aspx HTML代码 <%@ Page language="c#" Codebehind="02Login.aspx.cs" AutoEventWireup="false" Inherits="身份验证._02Login" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 T

[收藏]使用Reporting Services中的窗体身份验证

services 使用 Reporting Services 中的窗体身份验证发布日期: 8/18/2004 | 更新日期: 8/18/2004Microsoft Corporation 适用范围:Microsoft SQL Server 2000 Reporting Services 摘要:了解有关 Reporting Services 安全扩展方面的知识,着重学习窗体身份验证.此外,下载和部署 Reporting Services 的窗体身份验证扩展示例. 要安装示例代码,请下载 Forms

ASP.Net:基于Windows的身份验证

asp.net|window 如果将 ASP.NET 配置为使用 Windows 身份验证,则 IIS 使用配置的 IIS 身份验证机制执行用户身份验证.启用Windows身份验证的步骤如下:     (1) 配置 Web.config文件.     <authentication mode="Windows" />     (2) 首先启动系统的Internet 信息服务(IIS),右击网站本目录的节点,选择[属性]命令.如图12.3所示. 图12.3 启动IIS (3)

浅谈PHP+MYSQL身份验证的方法

mysql 近日在为学校制做校友录时,需要身份验证,在对比之后决定采用PHP+MYSQL进行身份验证. 之前也曾考虑过用cookies或session.但是用cookies,在用户离线再上线后,只要cookies不过期,不用登录仍然可以保持在线,这对于网吧来说是个隐患.而且用户可以关闭cookies,这样身份验证就不成功.也考虑过用session,session在浏览过程中不断的将访问信息加入到session中,如果用户在网站内时间很长,浏览的页面很多,就用导致session越来越大,浏览速度降

调用SQL SERVER数据库存储过程实现ASP用户身份验证

server|存储过程|数据|数据库 在我们编写用户身份验证程序中,很容易用ASP调用SQL语句来检索数据表中是否有条件相符的记录,然后再用ASP进行相关处理. 条条道路通罗马!当然,我们也可以用SQL SERVER数据库的存储过程来轻松实现这个功能.虽然相对而言较复杂,但其效率的提升是很明显的,因为存储过程是在数据库中已经编译好的一段程序,我们只需用ASP将其所用的各种参数正确传递就行了. 本文也主要是想通过一个简单的事例,向大家介绍一下如何在ASP中调用带参数的存储过程.希望大家能从中得到更

asp.net中的身份验证

asp.net asp.net中的身份验证 我用的是基于窗体的验证,这也是最常用的,我只写一下摘要,源代码太长,但应该不影响理解代码. web.config的修改:<authentication mode="Forms" /> 用户的登陆验证方法,:这里有两个输入控件的,一个是user_tb,用来输入用户,一个是psw_tb,用来输入密码private void Button1_Click(object sender, System.EventArgs e){//用户登陆验