shaunpersad/api-foundation

这是一个为 Laravel 4 提供创建 API 基础的包。特别是,它允许使用任何应用程序需要的授权类型实现 OAuth 2.0,包括自定义授权类型。此外,它还将所有 API 响应标准化为易于定义的格式。

0.1.6 2014-08-24 04:07 UTC

This package is not auto-updated.

Last update: 2024-09-24 02:08:36 UTC


README

版本 0.1.6 增加了通过 Google+ 登录的支持。请注意,您不需要成为实际的 Google+ 用户即可使用 Google+ 登录。您只需要任何类型的 Google 账户。在您的应用程序中实现此功能有两种支持的方式:推荐的混合服务器端流程使用服务器代码:https://developers.google.com/+/web/signin/server-side-flow 和纯服务器端流程:https://developers.google.com/+/web/signin/redirect-uri-flow

混合服务器端流程在 Api Foundation 中通过 gplus_server_code 授权类型支持,您必须传递一个 gplus_server_code 参数,这是 Google 文档中指定的“一次性授权代码”。

纯服务器端流程对应于 gplus_access_token 授权类型,您必须传递一个 gplus_access_token 参数,这是一个通过任何其他方式从 Google 获得的访问令牌。

此版本还通过添加新的配置选项来指定特定于您的应用程序的数据库字段名称,增加了进一步的灵活性。

注意:如果您是从此包的先前版本升级,请向您的用户表中添加一个字段,该字段将用作 Google+ 用户 ID。如果您使用我们的原始迁移,只需运行 >php artisan migrate --package="shaunpersad/api-foundation" 即可自动添加该字段。

简介

这是一个为 Laravel 4 提供创建 API 基础的包。特别是,它允许使用任何授权类型实现 OAuth 2.0,包括自定义授权类型。

此外,它还将所有 API 响应标准化为易于定义的格式。

关键概念

  • 授权:用户必须允许应用程序访问资源服务器上的资源。例如,当通过 Facebook 登录到应用程序时,您是在允许该应用程序访问 Facebook 上的资源。
  • 授权码:在授权过程成功后,会返回一个授权码。然后可以使用此代码交换访问令牌。
  • 访问令牌:在访问受保护资源时提供的令牌。通常,此访问令牌代表系统中的特定用户(但这不一定是这种情况)。
  • 认证:请求访问令牌。此请求的结构和需求基于应用程序实现的授权类型。
  • 授权类型:使用的认证方法。ApiFoundation 实现了多种授权类型,并允许创建自定义授权类型。
  • 客户端:使用您的 API 的应用程序。它可以是任何东西:网站、移动应用程序或服务器。“客户端”和“应用程序”在此文档中将交替使用。
  • 客户端 ID:用于标识应用程序。
  • 客户端密钥:用于验证客户端的密码。可选的,根据OAuth 2.0规范,如果此密钥有公开的风险,则必须排除。

ApiFoundation中的OAuth 2.0

OAuth 2.0支持建立在bshaffer的Oauth2 Server Library for PHP之上:http://bshaffer.github.io/oauth2-server-php-docs/

有关OAuth 2.0及其实现的详细描述,请查看他的文档。

作为ApiFoundation中OAuth 2.0如何使用的高级介绍,本质上有一个“令牌”端点,在该端点,给定特定的参数(例如用户的用户名和密码),返回一个访问令牌,该访问令牌(通常)直接映射到用户,然后可以用于验证未来的API请求。

这些特定的参数取决于你选择在API中使用哪种授权类型。有多种授权类型可供选择

  • 授权码:这是标准的OAuth 2.0实现。如果你曾经使用过Facebook的Graph API OAuth 2.0实现,这基本上是那个流程,用户会被引导到登录页面,在那里他们可以以某种方式登录到你的系统并授权一个应用程序。这样做会返回一个授权码(记住,这不同于访问令牌!)然后可以将此授权码发送到API的令牌端点以接收一个访问令牌。

  • 密码(用户凭证):更简单的实现,用户名和密码直接发送到令牌端点以接收访问令牌。这是验证用户最方便的方式。

  • 客户端凭证:将应用程序的客户端ID和客户端密钥发送到令牌端点以接收访问令牌。然而,此访问令牌不映射到用户。从本质上讲,这是应用程序本身使用API,只能访问应用程序控制下的资源(而不是用户可访问的资源)。

  • 刷新令牌:当用户通过授权码或密码授权类型进行认证时,会返回一个“刷新令牌”与访问令牌一起。然后可以将此刷新令牌发送回令牌端点以获取新的访问令牌。

  • 隐式:这与授权码授权类型相同,只是在用户登录到你的系统时,返回的是访问令牌而不是授权码。当在客户端JavaScript中使用API时,这通常是一种首选的方法。

  • Facebook访问令牌(自定义授权类型):你可以创建自己的授权类型。一种这样的自定义授权类型是“Facebook访问令牌”授权类型,它允许你向令牌端点发送Facebook访问令牌以接收访问令牌。换句话说,它用一个Facebook访问令牌(用于标识一个FACEBOOK用户)交换你的资源服务器的一个访问令牌(用于标识你的一个用户)。因此,如果你的应用程序有“使用Facebook登录”的功能,那么Facebook认证流程结束时Facebook返回的访问令牌可以用来在你的系统中创建和/或识别用户。

支持多种授权类型意味着你的API可以在多种情况下使用,同时仍然提供安全的访问方法,包括在移动应用程序中、在前端JavaScript中,甚至在完全服务器端。

安装

你可以将ApiFoundation用于新项目或现有项目,但是现有项目将需要进行一些修改。我们首先介绍新项目的步骤。

新项目安装

通过composer安装。

require: "shaunpersad/api-foundation": "0.1.6"

将服务提供程序添加到你的app/config/app.php中的提供程序列表中

‘Shaunpersad\ApiFoundation\ApiFoundationServiceProvider’

发布包含的配置文件,以便您可以对项目进行修改

php artisan config:publish shaunpersad/api-foundation

这会将配置文件复制到 app/config/packages/shaunpersad/api-foundation

运行包含的迁移(注意:这将创建一个“users”表)

php artisan migrate --package="shaunpersad/api-foundation"

这是一个包含的数据库种子器,您可能希望将其作为您自己的种子器的基础:shaunpersad/api-foundation/src/Shaunpersad/ApiFoundation/Database/OAuthSeeder.php

配置文件和创建的表设计为直接协同工作,但如果您选择修改用户表,请检查配置文件以确保更改了适当的值。

此外,如果您计划利用Facebook集成,请在配置文件中设置Facebook App ID和Facebook App Secret。

找到包含的sample-routes.php文件:shaunpersad/api-foundation/src/Shaunpersad/ApiFoundation/sample-routes.php

在其中,您将找到您可能希望实施的各个路由,这些路由将在“端点”部分中详细描述。将这些路由复制到您的项目中。

现有项目安装

通过composer安装。

require: "shaunpersad/api-foundation": "0.1.6"

将服务提供程序添加到你的app/config/app.php中的提供程序列表中

‘Shaunpersad\ApiFoundation\ApiFoundationServiceProvider’

发布包含的配置文件,以便您可以对项目进行修改

php artisan config:publish shaunpersad/api-foundation

如果您已经有了自己的“users”表,请不要运行包含的迁移。相反,创建自己的迁移,然后找到包含的创建OAuth表迁移文件(shaunpersad/api-foundation/src/migrations/),并将其代码复制到您的迁移文件中,然后运行此迁移。

这是一个包含的数据库种子器,您可能希望将其作为您自己的种子器的基础:shaunpersad/api-foundation/src/Shaunpersad/ApiFoundation/Database/OAuthSeeder.php

如果您正在使用自己的“users”表,那么您可能需要修改配置文件,以便ApiFoundation指向您用户表中的正确字段。注意:您需要一个与“username”对应的字段,例如电子邮件地址或实际的用户名。您还需要一个密码字段。

此外,如果您计划利用Facebook集成,请在配置文件中设置Facebook App ID和Facebook App Secret。

接下来,您可能需要扩展控制ApiFoundation如何与您的数据库交互的类:ModelStorage。虽然技术上您可以覆盖所有方法,但通常只需覆盖少数几个以适应您的需求

  • checkUserCredentials ($username, $password):bool

    此函数接受用户的用户名和原始密码,然后检查密码是否有效。

  • getUserInfoByUsername ($username):array

    给定用户的用户名,获取用户的信息(通常是一个数据库行),作为一个包含强制性的user_id键的关联数组。

  • checkPassword ($username, $password):bool

    默认情况下,此函数由checkUserCredentials方法使用。如果您使用自定义Auth方法,可以覆盖此函数。

  • getUserInfoByFacebookId ($facebook_id):array

    给定用户的facebook ID,获取用户的信息(通常是一个数据库行),作为一个包含强制性的user_id键的关联数组。

  • createFacebookUser (GraphUser $facebook_user):void

    根据他们的Facebook信息在您的系统中创建一个新的用户。

如果您使用Facebook集成,您还可能需要扩展FacebookAccessToken授权类型,如果您希望精确控制Facebook访问令牌如何交换为您的访问令牌之一。例如,如果您不想使用Facebook用户的电子邮件地址作为他们的用户名。

为了使用您扩展的ModelStorage和/或FacebookAccessToken类,您还必须覆盖相关的IoC绑定,这可能包括oauth2oauth2_grant_types和/或oauth2_storage(请参阅“IoC绑定”部分)。

找到包含的sample-routes.php文件:shaunpersad/api-foundation/src/Shaunpersad/ApiFoundation/sample-routes.php

在其中,您将找到您可能希望实施的各个路由,这些路由将在“使用”部分中详细描述。请在实现每个路由时阅读注释。

端点

sample-routes.php文件包含几个路由,这些路由可以识别为以下类型的API端点

授权端点

sample-routes.php 文件 中,这是 /authorize 路由。此端点用于授权码授予类型。对该端点的 GET 请求应显示一个表单或其他登录方法供用户登录您的系统。对该端点的 POST 请求应处理登录并将用户重定向到指定的 "redirect_uri" 或带有错误信息的表单。如果用户被重定向到 "redirect_uri",则该 URI 应包含授权码 ("code" 查询参数),或者如果授予类型是 "Implicit",则包含访问令牌在 URL 片段中。

令牌端点

sample-routes.php 文件中,这是 /api/v1/get-token 路由。这是基于您使用的授权类型,发送特定参数并接收访问令牌的端点。

#####必需参数

  • client_id - 必须存在于请求体中或在授权 HTTP 标头(Http Basic)中。

  • grant_type - 必须存在于请求体中,并设置为您的授权类型之一。

    此参数的值通过 ApiFoundationServiceProvider 中的 oauth2_grant_types IoC 绑定映射到描述的授权类型之一。默认映射如下,其中键是您用作 grant_type 值的内容

            return array(
                'authorization_code' => '\OAuth2\GrantType\AuthorizationCode',
                'password' => '\OAuth2\GrantType\UserCredentials',
                'client_credentials' => '\OAuth2\GrantType\ClientCredentials',
                'refresh_token' => '\OAuth2\GrantType\RefreshToken',
                'fb_access_token' => '\Shaunpersad\ApiFoundation\OAuth2\GrantType\FacebookAccessToken',
                'gplus_access_token' => '\Shaunpersad\ApiFoundation\OAuth2\GrantType\GPlusAccessToken',
                'gplus_server_code' => '\Shaunpersad\ApiFoundation\OAuth2\GrantType\GPlusServerCode',
            );
    

    在此列表中,您希望支持的授权类型可以在配置文件中定义。要添加额外的授权类型,您需要通过定义具有相同键的自定义绑定来覆盖 oauth2_grant_types 绑定。

  • client_secret - 如果您的应用程序使用它,则必须存在。应用程序不应使用公开可用的客户端机密。如果使用客户端机密,则必须存在,并且必须在请求体中或在授权 HTTP 标头(Http Basic)中。

重定向端点

sample-routes.php 文件中,这是 /login-redirect 路由。这是在通过授权端点授权后希望用户重定向到的 URI。

资源端点

sample-routes.php 文件中,这是 /api/v1/me 路由。这是一个 API 资源的示例。将有效的访问令牌传递到此路由将返回该已认证用户("我")作为资源。

Facebook 路由

包括两个额外路由以演示 Facebook 访问令牌授予类型。在配置文件中提供 Facebook 应用 ID 和机密后,/get-facebook-login 路由将重定向您到 Facebook 以登录并授权您的应用程序。授权后,Facebook 将重定向您到 /facebook-login-redirect 路由,并显示您的 Facebook 访问令牌。然后,可以将此 Facebook 访问令牌发送到令牌端点以交换为您的应用程序的访问令牌之一。

Google+ 路由

包括三个额外路由以演示与 Google+ 相关的两个授权类型,对应于两种可能的 Google+ 登录流程。在配置文件中提供 Google 客户端 ID 和机密后,/get-gplus-login 路由将重定向您到 Google 以登录并授权您的应用程序。授权后,Google 将重定向您到 /gplus-login-redirect 路由,并显示您的 Google+ 访问令牌。然后,可以将此 Google+ 访问令牌发送到令牌端点以交换为您的应用程序的访问令牌之一。

IoC 绑定

  • oauth2 - 一个 单例,是 bshaffer 的 Oauth2 服务器库创建的基础 OAuth 2.0 服务器对象:[http://bshaffer.github.io/oauth2-server-php-docs/](http://bshaffer.github.io/oauth2-server-php-docs/)。这在 ApiFoundationServiceProvider 内部使用,所以您通常不需要与它交互。

  • oauth2_grant_types - 一个 单例,创建一个将 grant_type 映射到实现该授予类型的类的关联数组。如果您想使用自己的自定义授权类型,则必须用您自己的自定义绑定覆盖此绑定。

  • oauth2_storage - 一个 单例,用于创建一个对象以处理与数据库的交互。如果您想使用自己的自定义存储,则必须用您自己的绑定来覆盖此绑定。

  • requires_oauth_token - 一个 过滤器,用于限制路由需要有效的访问令牌(作为“access_token”参数)。请参见 sample-routes.php 文件中的用法。

  • authorize_request - 一个 绑定,用于创建对授权端点的请求。在创建时,您应该传递一个 "validate_error_callback" 和一个 "validate_success_callback"。这个绑定可能只使用一次。请参见 sample-routes.php 文件中的用法。

  • authorize_response - 一个 绑定,用于为对授权端点的请求创建响应。您应该传递 "is_authorized" 参数来指示用户是否授权了您的应用程序,以及 "user_id" 参数来指示哪个用户(如果有)执行了此操作。这个绑定可能只使用一次。请参见 sample-routes.php 文件中的用法。

  • token_response - 一个 绑定,用于为令牌端点创建响应。此响应将包括访问令牌或错误信息。这个绑定可能只使用一次。请参见 sample-routes.php 文件中的用法。

  • api_response_array - 一个 绑定,用于创建每个API响应的结构。可以通过简单地扩展我们的服务提供程序并重写 makeAPIResponseArray 方法来更改此结构。

  • access_token_data - 一个 实例,在通过 requires_oauth_token 过滤器成功认证后可用。包含访问令牌数据。您通常不需要使用此实例。

  • oauth2_storage - 一个 单例,用于创建 Google_Client 实例,该实例是处理底层 Google+ 认证所必需的。

辅助类

  • SuccessResponse - 使用 SuccessResponse::make($object) 创建成功的API请求的JSON响应。$object 可以是 Laravel 常规可序列化的任何内容,例如 Eloquent 模型。
  • ErrorResponse - 使用 ErrorResponse::make($message, $status, $headers) 创建API错误的JSON响应。
  • OAuthRequest - 用于在 bshaffer 的 Oauth2 服务器库的 Request 对象和 Laravel 之间建立桥梁。
  • OAuthResponse - 用于在 bshaffer 的 Oauth2 服务器库的 Response 对象和 Laravel 之间建立桥梁。

所有响应对象都利用 api_response_array 绑定定义的结构。

示例

为了可重复性,所有示例都有以下假设:

  • 在全新的项目中安装此包
  • 您已使用包含的 seeder 向数据库填充了数据
  • 您已将 sample-routes.php 中的所有路由复制到您的路由中
  • 基本 URL 是 http://apitest.local
  • 令牌端点是 POST
  • 未使用客户端密钥
  • 客户端 ID 通过请求体传递(尽管通过头信息传递更佳)

使用授权码授权类型

在您的浏览器中,导航到 http://apitest.local/authorize。您应该得到一个错误,因为 sample-routes.php 文件中的注释指出:

您还必须在 URL 查询中设置 response_typeclient_idstateredirect_uri,其中 response_type = "code"(如果不是隐式 token),client_id = 您的客户端 ID,state = 任何随机值,redirect_uri = 数据库中的有效 redirect_uri

使用包含的 seeder 中的数据,client_id = "testclient",redirect_uri = "http://apitest.local/login-redirect" 将这些值包含在 URL 查询中将正确显示登录表单。

例如:http://apitest.local/authorize?client_id=testclient&response_type=code&redirect_uri=http://apitest.local/login-redirect&state=sdjf

为了错误检查,请尝试移除参数。

通过点击“是”按钮并使用有效的凭据授权应用。如果使用包含的seeder,应使用admin@local.compassword。随后,您应被重定向到提供的redirect_uri,URL中包含您的授权码(code),或者如果response_type参数设置为token,则URL片段中的access_token参数为您的访问令牌。

如果您收到了授权码,您可以将其(连同其他必需参数)POST到令牌端点以接收访问令牌

例如:(使用CocoaRestClient)https://www.dropbox.com/s/c4m86xgu94fpr1r/Screenshot%202014-06-23%2017.14.41.png

使用密码授权类型

POST所需的凭据和其他参数:https://www.dropbox.com/s/h7xmd9qlz7ft9vz/Screenshot%202014-06-23%2017.18.06.png

使用Facebook访问令牌授权类型

在浏览器中,导航到http://apitest.local/get-facebook-login

您应被重定向到Facebook进行登录并授权应用。一旦授权或如果您之前已授权该应用,您将被重定向回http://apitest.local/facebook-login-redirect,并且您的Facebook访问令牌将显示出来。

然后,您可以将其(连同其他必需参数)POST到令牌端点:https://www.dropbox.com/s/dzaxzva56tdcc92/Screenshot%202014-06-23%2017.23.40.png

使用访问令牌访问资源

使用有效的访问令牌POST到“me”端点

  1. 种子用户:https://www.dropbox.com/s/dr48oanlpq2k9ju/Screenshot%202014-06-23%2017.27.06.png
  2. Facebook用户:https://www.dropbox.com/s/h0t0f1e482llbu9/Screenshot%202014-06-23%2017.25.33.png