vfork-imsglobal / lti-1p3-tool
LTI 1.3 工具分支
Requires
- phpseclib/phpseclib: ^2.0
- vfork-fproject/php-jwt: ^4.0
This package is not auto-updated.
Last update: 2024-09-25 20:35:26 UTC
README
LTI 1.3 优势库
此代码包括用于在 PHP 中创建 LTI 工具提供者的库。
库文档
导入库
使用 Composer
将以下内容添加到您的 composer.json
文件中
"repositories": [ { "type": "vcs", "url": "https://github.com/IMSGlobal/lti-1-3-php-library" } ], "require": { "imsglobal/lti-1p3-tool": "dev-master" }
运行 composer install
或 composer update
。在您的代码中,您现在可以使用 \IMSGlobal\LTI
命名空间中的类来访问库。
手动导入
要导入库,将 src
中的 lti
文件夹复制到您的项目中,并在执行开始时使用以下代码
require_once('lti/lti.php'); use \IMSGlobal\LTI;
访问注册数据
为了允许进行验证并允许工具知道它需要在何处进行调用,必须存储注册数据。库而不是指定如何存储,它提供了一个必须实现的接口,以便它可以访问注册数据。必须完全实现 LTI\Database
接口才能使其工作。
class Example_Database implements LTI\Database { public function find_registration_by_issuer($iss) { ... } public function find_deployment($iss, $deployment_id) { ... } }
必须返回一个 LTI\LTI_Registration
。
return LTI\LTI_Registration::new() ->set_auth_login_url($auth_login_url) ->set_auth_token_url($auth_token_url) ->set_client_id($client_id) ->set_key_set_url($key_set_url) ->set_kid($kid) ->set_issuer($issuer) ->set_tool_private_key($private_key);
如果存在于数据库中,则必须返回一个 LTI\LTI_Deployment
。
return LTI\LTI_Deployment::new() ->set_deployment_id($deployment_id);
调用库需要传入一个 LTI\Database
实例。
创建 JWKS 端点
可以为单个注册或从 KID
和私有密钥的数组生成 JWKS(JSON Web Key Set)端点。
// From issuer LTI\JWKS_Endpoint::from_issuer(new Example_Database(), 'http://example.com')->output_jwks(); // From registration LTI\JWKS_Endpoint::from_registration($registration)->output_jwks(); // From array LTI\JWKS_Endpoint::new(['a_unique_KID' => file_get_contents('/path/to/private/key.pem')])->output_jwks();
处理请求
Open Id Connect 登录请求
LTI 1.3 使用 OpenId Connect 第三方发起的登录流的修改版本。这意味着要进行 LTI 1.3 启动,您必须首先接收登录初始化请求并返回到平台。
为了处理此请求,您必须首先创建一个新的 LTI\LTI_OIDC_Login
对象。
$login = LTI_OIDC_Login::new(new Example_Database());
现在您必须配置您的登录请求,并带有返回 URL(此 URL 必须预先配置并在工具中白名单)。如果没有给出重定向 URL 或注册不存在,则将抛出 LTI\OIDC_Exception
。
try { $redirect = $login->do_oidc_login_redirect("https://my.tool/launch"); } catch (LTI\OIDC_Exception $e) { echo 'Error doing OIDC login'; }
有了重定向,我们现在可以将用户重定向回工具。有三种方法可以做到这一点
这将添加一个 302 位置头并退出。
$redirect->do_redirect();
这将输出一些 JavaScript 以执行重定向而不是使用 302。
$redirect->do_js_redirect();
您还可以获取您需要重定向到的 URL,其中包含所有必要的查询参数,如果您希望以自定义方式重定向。
$redirect_url = $redirect->get_redirect_url();
重定向完成,我们可以进行启动。
LTI 消息启动
现在我们已经完成了 OIDC 登录,平台将返回到工具。为了处理此请求,首先我们需要创建一个新的 LTI\LTI_Message_Launch
对象。
$launch = LTI\LTI_Message_Launch::new(new Example_Database());
一旦我们有了消息启动,我们就可以对其进行验证。这将检查签名、部署的存在以及任何必需的参数。如果验证失败,则将抛出异常。
try { $launch->validate(); } catch (Exception $e) { echo 'Launch validation failed'; }
现在我们知道启动是有效的,我们可以了解更多关于启动的信息。
检查我们是否有资源启动或深度链接启动。
if ($launch->is_resource_launch()) { echo 'Resource Launch!'; } else if ($launch->is_deep_link_launch()) { echo 'Deep Linking Launch!'; } else { echo 'Unknown launch type'; }
检查我们可以访问哪些服务。
if ($launch->has_ags()) { echo 'Has Assignments and Grades Service'; } if ($launch->has_nrps()) { echo 'Has Names and Roles Service'; }
访问缓存的启动请求
您可能会希望稍后在后续请求中回过头来引用启动。这是使用启动 ID 来标识缓存的请求完成的。启动 ID 可以使用以下方法找到
$launch_id = $launch->get_launch_id().
一旦您获得启动ID,就可以将其与您的会话链接,并将其作为查询参数传递。
请确保您将启动ID与用户会话进行核对,以防止有人对另一个人的启动进行操作。
使用启动ID检索启动可以通过以下方式完成:
$launch = LTI_Message_Launch::from_cache($launch_id, new Example_Database());
检索后,您可以像平常一样调用启动对象上的任何方法,例如:
if ($launch->has_ags()) { echo 'Has Assignments and Grades Service'; }
深度链接响应
如果您收到深度链接启动,您很可能希望使用平台资源来响应深度链接请求。
要创建深度链接响应,您需要获取当前启动的深度链接。
$dl = $launch->get_deep_link();
现在我们需要创建 LTI\LTI_Deep_Link_Resource
来返回。
$resource = LTI\LTI_Deep_Link_Resource::new() ->set_url("https://my.tool/launch") ->set_custom_params(['my_param' => $my_param]) ->set_title('My Resource');
一切设置都是为了将资源返回到平台。有两种方式可以实现。
以下方法将为您输出一个自动发布表单的html。
$dl->output_response_form([$resource]);
或者,您可以直接调用以获取需要发送回平台的已签名JWT。
$dl->get_response_jwt([$resource]);
调用服务
名称和角色服务
在开始使用名称和角色之前,您应该检查您是否有权限访问它。
if (!$launch->has_nrps()) { throw new Exception("Don't have names and roles!"); }
一旦我们知道我们可以访问它,我们可以从启动中获取该服务的实例。
$nrps = $launch->get_nrps();
从服务中,我们可以通过调用来获取所有成员的数组
$members = $nrps->get_members();
作业和成绩服务
在开始使用作业和成绩之前,您应该检查您是否有权限访问它。
if (!$launch->has_ags()) { throw new Exception("Don't have assignments and grades!"); }
一旦我们知道我们可以访问它,我们可以从启动中获取该服务的实例。
$ags = $launch->get_ags();
要将成绩发送回平台,您需要创建一个 LTI\LTI_Grade
对象,并用必要的信息填充它。
$grade = LTI\LTI_Grade::new() ->set_score_given($grade) ->set_score_maximum(100) ->set_timestamp(date(DateTime::ISO8601)) ->set_activity_progress('Completed') ->set_grading_progress('FullyGraded') ->set_user_id($external_user_id);
要将成绩发送到平台,我们可以调用
$ags->put_grade($grade);
这会将成绩放入默认提供的lineitem。如果没有默认lineitem,则会创建一个。
如果您想发送多种类型的成绩,可以通过指定一个 LTI\LTI_Lineitem
来实现。
$lineitem = LTI\LTI_Lineitem::new() ->set_tag('grade') ->set_score_maximum(100) ->set_label('Grade'); $ags->put_grade($grade, $lineitem);
如果存在具有相同 tag
的lineitem,将使用该lineitem,否则将创建一个新的lineitem。
贡献
如果您有改进、建议或错误修复,请随意发起pull请求或issue,有人会查看它。
您不需要成为IMS成员即可使用或为此库做出贡献,但是为了更好地获取支持资源并获得认证,建议您这样做。
此库最初由@MartinLenord从Turnitin创建,以帮助验证LTI 1.3规范并加速工具开发。
注意: 此库仅适用于基于IMS LTI 1.3的规范。请求包含自定义、非规范或供应商特定更改的请求将被拒绝。
不喜欢PHP?
如果您不喜欢PHP,并且有一个您想要为其制作库的喜欢的语言,我们很乐意听到您的意见!