eskater/lti-1p3-tool

此软件包最新版本(dev-master)没有可用的许可信息。

dev-master 2020-12-10 00:34 UTC

This package is auto-updated.

Last update: 2024-09-10 08:46: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 installcomposer 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或注册不存在,将抛出 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';
}

访问缓存的启动请求

在后续请求中,您可能会希望回溯到某个启动(launch)。这可以通过使用启动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)。如果没有默认行项目存在,它将创建一个。

如果您想发送多种类型的成绩,可以通过指定一个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 request或issue,有人会查看。

您不需要是IMS成员即可使用或为此库做出贡献,但是为了更好地访问支持资源和认证,我们建议这样做。

此库最初由Turnitin的@MartinLenord创建,以帮助验证LTI 1.3规范并加速工具开发。

注意:此库仅适用于基于IMS LTI 1.3的规范。包含自定义、非规范或供应商特定的更改的请求将被拒绝。

不喜欢PHP?

如果您不喜欢PHP,并且有一个您希望为其创建库的喜欢的语言,我们非常愿意听取您的意见!