在通过 Classroom API 访问用户资源的身份验证过程中,在将授权令牌发送到 Classroom API 并尝试访问资源后,我立即收到错误,返回状态码 404。
我已成功完成前面的步骤。也就是说,具有授予的权限和剩余参数的令牌请求,其处理最终将其发送到 Classroom API 并能够访问资源。
Ajax提交是在以下函数中完成的:
async function trySampleRequest() {
var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
console.log("Params " + JSON.stringify(params));
if (params && params['access_token']) {
// User authorized the request. Now, check which scopes were granted.
if (params['scope'].includes('https://www.googleapis.com/auth/classroom.courses')) {
// User authorized
// Calling the APIs, etc.
console.log("Include scope");
var xhr = new XMLHttpRequest();
xhr.open('GET',
'https://www.googleapis.com/classroom/v1/courses/about?fields=user&' +
'access_token=' + params['access_token'], true);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
//console.log(xhr.response);
} else if (xhr.readyState === 4 && xhr.status === 401) {
// Token invalid, so prompt for user permission.
oauth2SignIn();
}
};
xhr.setRequestHeader('Access-Control-Allow-Origin', 'http://localhost:50656');
xhr.send(null);
}
}
}
经过多次测试,我已经清楚地确定了这个错误的具体来源。当我加载作为 Classroom API 服务器响应接收者的页面时,响应标头 access-control-allow-origin 为:
access-control-allow-origin: http://localhost:50656
在这种情况下不会发生错误。
当页面是不同的页面时,因为我已从上一个页面导航到该页面,则响应标头 access-control-allow-origin 不存在。在这种情况下,浏览器不允许访问 API 资源。
解决方案可能是不需要导航到另一个不同的页面。问题是,将所有处理包含在一个页面中非常复杂。
如果可以设置 access-control-allow-origin 响应标头,以便在收到响应时浏览器能够检测到它,这将是一个更好的解决方案。根据我读过的文档, access-control-allow-origin 标头已从服务器(即 Classroom API)配置。
有人可以帮我找到解决这个问题的方法吗?
观察
由于对该问题的完整编辑,讨论中的前四条评论与所提出的具体问题无关。
对于任何可能感兴趣的人,我将详细解释我最终确认的问题的解决方案。
这就是我在问题中指出的原因。服务器在回调中返回的标头 access-control-allow-origin 可能存在,也可能不存在。如果存在,其目的是告诉浏览器是否阻止对所请求资源的访问。如果标头值允许,则在尝试在代码中使用请求的资源时不会发生错误(在我的例子中,这些文件位于 Google Drive 中,并且是使用 Google Classroom 平台生成的)。
要了解 header access-control-allow-origin 可以具有的值,您可以查阅以下 URL (https://developer.mozilla.org/en-US/docs/Web/HTTP /标题/访问控制允许来源
当标头 access-control-allow-origin 值是进行调用的源的 URL(在我的例子中 https://localhost:50656)时,不会发生错误。
如果您导航到收到授权响应的页面以外的页面,并从那里请求访问服务器资源,则标头 access-control-allow-origin 不存在于服务器响应中,并且因此,您将无法访问服务器的资源,因为浏览器会阻止它。
规范这种访问控制的整个机制是跨源资源共享(CORS)。可以在以下 URL 找到帮助 (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
对于我的问题,解决方案是从收到响应的同一页面进行调用以访问资源。虽然看起来简单且合乎逻辑,但对我来说找到解决方案并不容易,因为我的网站(ASP.NET)在收到服务器响应时的行为对我来说是意料之外的。
我发现响应总是定向到 Default.aspx 页面,即使请求是从另一个页面发出的。知道这一点后,我将响应处理代码放置在 Default.aspx 页面上。后来,我注意到,如果我导航到另一个页面并将授权令牌从那里发送到服务器,则会出现状态代码 404 的错误,因为缺少从服务器接收响应的 access-control-allow-origin。下一步是应用我上面描述的解决方案。