使用 Lua 完成 OAuth2 的身份验证

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 本文讲的是使用 Lua 完成 OAuth2 的身份验证,在此说明该教程将不提供详细的技术指导,教您如何使用 OpenResty + Lua 构建自己的认证层,而是讲解一下解决方案背后的处理过程。
本文讲的是使用 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日

本文来自云栖社区合作伙伴掘金,了解相关信息可以关注掘金网站。
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
API PHP
PHP使用jwt生成token,做api的用户认证firebase/php-jwt
PHP使用jwt生成token,做api的用户认证firebase/php-jwt
431 0
|
4月前
|
安全 Java API
深度解析 Spring Security:身份验证、授权、OAuth2 和 JWT 身份验证的完整指南
Spring Security 是一个用于保护基于 Java 的应用程序的框架。它是一个功能强大且高度可定制的身份验证和访问控制框架,可以轻松地集成到各种应用程序中,包括 Web 应用程序和 RESTful Web 服务。 Spring Security 提供了全面的安全解决方案,用于身份验证和授权,并且可以用于在 Web 和方法级别上保护应用程序。
256 0
|
5月前
|
存储 安全 前端开发
深入探讨安全验证:OAuth2.0、Cookie与Session、JWT令牌、SSO与开放授权平台设计
这篇文章讨论了认证和授权的概念,并探讨了设计权限认证框架的原则。它还比较了Cookie和Session的区别,并探讨了处理分布式部署时的Session保存问题。此外,文章还介绍了CSRF攻击及其防范方法,以及OAuth2.0、JWT令牌和SSO的概念。最后,文章提出了设计开放授权平台时需要考虑的因素。
深入探讨安全验证:OAuth2.0、Cookie与Session、JWT令牌、SSO与开放授权平台设计
|
7月前
|
存储 JSON 安全
JWT验证用户信息功能与OAuth2协议
JWT验证用户信息功能与OAuth2协议
72 0
|
9月前
|
存储 JSON 安全
Oauth2.0 + JWT 做权限认证
做过权限认证的朋友都清楚,SpringSecurity 的功能很强大,但是我们也都知道,它配置起来也着实让人头疼。N多个配置类还有N多个需要实现的接口,总是记不住和不知道为什么会有这么多,最近在学习这方面的东西,正好能够把学习到的东西分享出来给大家参考一下。
|
12月前
|
存储 安全 算法
OAuth2.0实战!使用JWT令牌认证!
OAuth2.0实战!使用JWT令牌认证!
Jasny SSO是否支持OAuth认证?底层原理是什么?
Jasny SSO是否支持OAuth认证?底层原理是什么?
|
XML 安全 数据格式
Jasny SSO是否支持SAML认证?底层原理是什么?
Jasny SSO是否支持SAML认证?底层原理是什么?
jira学习案例22-jwt原理-auth-provider
jira学习案例22-jwt原理-auth-provider
48 0
jira学习案例22-jwt原理-auth-provider
|
存储 JSON NoSQL
浅析单点登录(重点讲解OAuth2+JWT)
浅析单点登录(重点讲解OAuth2+JWT)
509 0
浅析单点登录(重点讲解OAuth2+JWT)