QTIWorks LTI请求参数为空

时间:2015-04-23 13:09:14

标签: java lti

我试图在我们的教育平台中实施LTI,以便与Java中的QTIWoks建立联系。

我有一个简单的工具使用者,可以生成以下HTML表单:

<html>
<head> </head>
<body>
<form action="http://192.168.0.114:8080/qtiworks-engine/lti/domainlaunch" name="ltiLaunchForm" id="ltiLaunchForm" method="post" target="basicltiLaunchFrame" enctype="application/x-www-form-urlencoded" style="display: block;">
<input type="hidden" name="context_id" value="cid-00113">
<input type="hidden" name="context_label" value="SI106">
<input type="hidden" name="context_title" value="Design of Personal Environments 1">
<input type="hidden" name="ext_note" value="Instructor from first course">
<input type="hidden" name="launch_presentation_locale" value="en_us">
<input type="hidden" name="lis_person_contact_email_primary" value="sian@imscert.org">
<input type="hidden" name="lis_person_name_family" value="Instructor">
<input type="hidden" name="lis_person_name_given" value="Siân">
<input type="hidden" name="lis_person_sourcedid" value="school.edu:user">
<input type="hidden" name="resource_link_description" value="This learning space is private">
<input type="hidden" name="resource_link_id" value="res-0012612">
<input type="hidden" name="resource_link_title" value="My Weekly Wiki">
<input type="hidden" name="roles" value="Instructor">
<input type="hidden" name="tool_consumer_info_product_family_code" value="sakai-unit">
<input type="hidden" name="tool_consumer_info_version" value="0.9">
<input type="hidden" name="tool_consumer_instance_description" value="University of School (LMSng)">
<input type="hidden" name="tool_consumer_instance_guid" value="lmsng.school.edu">
<input type="hidden" name="user_id" value="user-0016">
<input type="hidden" name="oauth_callback" value="about:blank">
<input type="hidden" name="custom_simple_key" value="custom_simple_value">
<input type="hidden" name="custom_complex____________key" value="Complex!@#$^*(){}[]½Value">
<input type="hidden" name="lti_version" value="LTI-1p0">
<input type="hidden" name="lti_message_type" value="basic-lti-launch-request">
<input type="hidden" name="oauth_version" value="1.0">
<input type="hidden" name="oauth_nonce" value="Z2WVNEPUZkzsolOe4hRvKbkXtOSmYiyw">
<input type="hidden" name="oauth_timestamp" value="1429793062">
<input type="hidden" name="oauth_consumer_key" value="feras">
<input type="hidden" name="oauth_signature_method" value="HMAC-SHA1">
<input type="hidden" name="oauth_signature" value="g908qTtVGh8MsOgVUdarVlSBmC0=">
<input type="hidden" name="ext_submit" value="Finish Launch">
</form><iframe name="basicltiLaunchFrame" id="basicltiLaunchFrame" src="" width="100%" height="900" scrolling="auto" frameborder="1" transparency="">
</iframe>
<script type="text/javascript">
   document.getElementById("ltiLaunchForm").style.display = "none";
   nei = document.createElement('input');
   nei.setAttribute('type', 'hidden');
   nei.setAttribute('name', 'ext_submit');
   nei.setAttribute('value', 'FinishLaunch');
   document.getElementById("ltiLaunchForm").appendChild(nei);
   document.ltiLaunchForm.submit();
</script>
</body>
</html>

然后它从qtiworks调用dominlaunch

@RequestMapping(value="/domainlaunch", method=RequestMethod.POST)
    public String ltiDomainLevelLaunch(final HttpSession httpSession, final HttpServletRequest request,
            final HttpServletResponse response)
            throws IOException {
        /* Decode LTI launch request, and bail out on error */
        final DecodedLtiLaunch decodedLtiLaunch = ltiLaunchService.decodeLtiLaunchData(request, LtiLaunchType.DOMAIN);
        if (decodedLtiLaunch.isError()) {
            response.sendError(decodedLtiLaunch.getErrorCode(), decodedLtiLaunch.getErrorMessage());
            return null;
        }
        final LtiLaunchData ltiLaunchData = decodedLtiLaunch.getLtiLaunchData();

        /* Make sure this is a domain launch */
        final LtiUser ltiUser = decodedLtiLaunch.getLtiUser();
        final LtiDomain ltiDomain = ltiUser.getLtiDomain();
        if (ltiDomain==null) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "The tool consumer has attempted a domain-level launch using a link-level key");
            return null;
        }

        /* Extract/create the corresponding LtiResource for this launch */
        final LtiResource ltiResource = ltiLaunchService.provideLtiResource(decodedLtiLaunch); /* (May be null for candidates) */
        final UserRole userRole = ltiUser.getUserRole();

        if (userRole==UserRole.INSTRUCTOR) {
            /* If user is an instructor, we'll forward to the LTI instructor MVC after
             * "authenticating" the user by creating and storing an LtiDomainTicket
             * in the session */
            final LtiAuthenticationTicket ltiDomainTicket = new LtiAuthenticationTicket(ltiUser.getId(), ltiResource.getId(),ltiLaunchData.getLaunchPresentationReturnUrl());
            LtiResourceAuthenticationFilter.authenticateUserForResource(httpSession, ltiDomainTicket);
            return "redirect:/lti/resource/" + ltiResource.getId();
        }
        else if (userRole==UserRole.CANDIDATE) {
            /* If user is a candidate, then we'll launch/reuse a candidate session */
            if (ltiResource==null) {
                return "candidateLaunchError";
            }

            /* Extract relevant data */
            final String returnUrl = ltiLaunchData.getLaunchPresentationReturnUrl();
            final String lisOutcomeServiceUrl = ltiLaunchData.getLisOutcomeServiceUrl();
            final String lisResultSourcedid = ltiLaunchData.getLisResultSourcedid();

            /* Launch and redirect to session */
            try {
                final CandidateSessionTicket candidateSessionTicket = candidateSessionLaunchService.launchDomainLevelLtiCandidateSession(httpSession,
                        ltiUser, ltiResource, returnUrl, lisOutcomeServiceUrl, lisResultSourcedid);
                return GlobalRouter.buildSessionStartRedirect(candidateSessionTicket);
            }
            catch (final CandidateException e) {
                return "candidateLaunchError";
            }
        }
        else {
            throw new QtiWorksLogicException("Unexpected LTI userRole " + userRole);
        }
    }

问题是decodedLtiLaunch.isError()返回true而我的请求没有执行。

我调试了问题,发现HttpServletRequest request在parameterMap中没有项目

然而,当请求来自moodle时,它运行良好(请求的参数Map已经传递了参数)

我该如何解决这个问题?

提前感谢。

1 个答案:

答案 0 :(得分:0)

在不知道您所看到的确切错误代码的情况下,我会强烈猜测您的签名是否错误

由于您使用的是JAVA,我建议您使用IMSGlobal提供的basiclti-util库来生成签名

添加以下依赖项

<dependency>
  <groupId>org.imsglobal</groupId>
  <artifactId>basiclti-util</artifactId>
  <version>1.1.2</version>
</dependency>

然后使用以下代码生成签名

Map<String, String> signedParameters = new LtiOauthSigner()
   .signParameters(parameters, key, secret, url, "POST");

然后获取signedParameters映射中的所有键值对,并使用它来构建示例中的表单输入标记。