ct-imsglobal / lti-1p3-tool
Requires
- firebase/php-jwt: ^4.0 || >=4.0
- phpseclib/phpseclib: ^2.0
This package is not auto-updated.
Last update: 2024-09-26 09:09:58 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) { ... } }
find_registration_by_issuer
方法必须返回一个 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);
find_deployment
方法必须返回一个 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 或注册不存在,则将抛出 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,该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);
这将成绩放入默认提供的行项。如果没有默认行项,它将创建一个。
如果您想发送多种类型的成绩,可以通过指定一个 LTI\LTI_Lineitem
来完成。
$lineitem = LTI\LTI_Lineitem::new() ->set_tag('grade') ->set_score_maximum(100) ->set_label('Grade'); $ags->put_grade($grade, $lineitem);
如果存在具有相同 tag
的行项,则将使用该行项;否则,将创建一个新的行项。
贡献
如果您有改进、建议或错误修复,请随时提交一个pull请求或问题,有人会查看它。
您不需要是IMS成员即可使用或为此库做出贡献,但是为了更好地访问支持资源和认证,建议您这样做。
该库最初由Turnitin的@MartinLenord创建,以帮助验证LTI 1.3规范并加速工具开发。
注意:此库仅适用于基于IMS LTI 1.3的规范。将包括自定义、不符合规范或供应商特定的更改的请求将被拒绝。
不喜欢PHP?
如果您不喜欢PHP并且有一个您想为其创建库的 favorite 语言,我们很乐意听到您的想法!