我正在执行oauth2的授权代码流程,在这里我做错了什么,但我无法真正检测到。
这是我的代码
在app.js中
myService.setup().then(function(){...
在service.js中
var service = {
setup(options) {
this.processData();
return this.getToken(options);
},
processData(data) {
let response = this._extractURLParams(window.location.href)
if (response.hasOwnProperty("code")) {
return this.handleAuthorizationCode(responseResult);
},
handleAuthorization(codeObject) {
var service= this;
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("POST", /token, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
var params = 'grant_type=authorization_code&code=' + codeObject.code + '&client_id=client_id&client_secret=secret&redirect_uri=' + codeObject.redirectURi;
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var responseData = JSON.parse(this.response);
resolve(service.storeToken(responseData));
}
};
xhr.send(params);
});
},
getToken(options) {
let service = this;
return new Promise(function (resolve, reject) {
if(// localStorage has a token) {
resolve(localStorage.getToken()) //dummy text, real code here
} else {
resolve(service.handleRedirectionsFlow(options));
})
},
发生的情况如下
1)当我访问我的应用程序时,我调用myService.setup()
2)setup()方法将调用processData(),并且由于url为空,因此if条件不会通过,因此我们将调用getToken()
3)getToken()将调用一个方法,该方法将构建一个url并更改其位置,以便我们通过授权服务器上的表单进行身份验证,然后在使用代码进行身份验证后将重定向到应用程序!
4)身份验证后,我们将使用类似以下内容重定向到应用程序
'url?code = abcasdasdsfdasifsfsfs
5)现在,processData()将检测到url具有code属性,我们将调用handleAuthorizationCode
6)handleAuthorizationCode将仅执行发布请求以获取令牌,而onReadyStateChange我们将调用另一个方法来存储令牌。
7)现在,当我们从setup()调用getToken()时,此时尚未从先前的方法触发onreadystatechange,这导致我们重做重定向以再次进行身份验证,然后令牌请求被取消,并且我们从不存储它..
有人可以帮我知道我应该在哪里准确地做出一个额外的承诺并解决它,以便在onreadystatechange被触发并存储令牌以避免无限循环之后调用getToken()?
谢谢
最佳答案
无法运行它很难知道,但是呢?
var service = {
setup(options) {
return this.processData()
.then(token => token || this.getToken(options));
},
processData(data) {
const response = this._extractURLParams(window.location.href);
return response.hasOwnProperty("code")
? this.handleAuthorizationCode(responseResult)
: Promise.resolve();
},
handleAuthorization(codeObject) {
var service = this;
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("POST", /token, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
var params = 'grant_type=authorization_code&code=' + codeObject.code + '&client_id=client_id&client_secret=secret&redirect_uri=' + codeObject.redirectURi;
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var responseData = JSON.parse(this.response);
resolve(service.storeToken(responseData));
}
};
xhr.send(params);
});
},
getToken(options) {
let service = this;
return new Promise(function(resolve, reject) {
if (localStorageHasToken) {
resolve(localStorage.getToken()) //dummy text, real code here
} else {
resolve(service.handleRedirectionsFlow(options));
}
});
}
};
本质上,即使它是立即解决的承诺,我们也使
processData
始终返回承诺,并且在setup
中,我们在调用processData()
之前等待getToken
承诺解决。我不确定
service.storeToken(responseData)
返回什么,但是如果已经存储了令牌,则可以使用它完全跳过对getToken
的调用。