从 javascript [spotify auth] 中的弹出窗口获取访问令牌 url
getting access token url from popup in javascript [spotify auth]
我正在尝试在纯 javascript 中创建一个 spotify 身份验证流程,以便用户可以登录,然后我可以为他们的帐户添加一个新的播放列表。根据我读过的说明,我使用了一个身份验证弹出窗口,一旦他们登录,就会在 URL 中获得访问令牌。我现在有一个用户可以验证的弹出窗口,一旦他们这样做,它就会在 url 中获得访问令牌。
我需要从弹出窗口中获取 url 并将其保存为全局变量,但我在 javascript.
中无法弄清楚如何执行此操作
https://codepen.io/martin-barker/pen/YzPwXaz
我的 codepen 打开一个带有 let popup = window.open(
的弹出窗口,我可以在我的弹出窗口中 运行 一个函数来检测用户何时成功验证和 url 更改吗?在这种情况下,我想保存 url 用于解析并关闭我的弹出窗口
我的javascript代码如下:
async function spotifyAuth() {
let result = spotifyLogin()
}
//open popup
function spotifyLogin() {
console.log("inside spotifyLogin, opening popup")
let popup = window.open(`https://accounts.spotify.com/authorize?client_id=5a576333cfb1417fbffbfa3931b00478&response_type=token&redirect_uri=https://codepen.io/martin-barker/pen/YzPwXaz&show_dialog=true&scope=playlist-modify-public`, 'Login with Spotify', 'width=800,height=600')
}
//get url from popup and parse access token????
window.spotifyCallback = (payload) => {
console.log("inside window? ") //this line never appears in console
popup.close()
fetch('https://api.spotify.com/v1/me', {
headers: {
'Authorization': `Bearer ${payload}`
}
}).then(response => {
return response.json()
}).then(data => {
// do something with data
})
}
这是我在 JavaScript 中的做法。像你提到的全局变量:
var access_token = null;
在 Spotify 将用户重定向到您在仪表板上指定的 uri 后,我解析 url 以获取包含访问令牌的哈希值,如下所示:
var hash = window.location.hash.substring(1);
var accessString = hash.indexOf("&");
/* 13 because that bypasses 'access_token' string */
access_token = hash.substring(13, accessString);
console.log("Access Token: " + access_token);
输出是:
Access Token: BQAXe5JQOV_xZmAukmw6G430lreF...........rQByzZMcOIF2q2aszujN0wzV7pIxA4viMbQD6s
我将此访问令牌保存在 sessionStorage 中,以防用户离开页面并且 url 不包含 access_token。我假设这是隐式授权流程,因为您想使用纯 JavaScript。只需确保在它们过期后每小时重新获取一个访问令牌。
附录
我可以通过示例向您展示如何获取令牌并使用它。
我在 .html 页面上有一个按钮,单击该按钮后会在名为
的 JavaScript 文件中调用一个名为 implicitGrantFlow() 的函数
Test.js
function implicitGrantFlow() {
/* If access token has been assigned in the past and is not expired, no request required. */
if (sessionStorage.getItem("accessToken") !== null &&
sessionStorage.getItem("tokenTimeStamp") !== null &&
upTokenTime < tokenExpireSec) {
var timeLeft = (tokenExpireSec - upTokenTime);
console.log("Token still valid: " + Math.floor(timeLeft / 60) + " minutes left.");
/* Navigate to the home page. */
$(location).attr('href', "home.jsp");
} else {
console.log("Token expired or never found, getting new token.");
$.ajax({
url: auth_url,
type: 'GET',
contentType: 'application/json',
data: {
client_id: client_id,
redirect_uri: redirect_uri,
scope: scopes,
response_type: response_type_token,
state: state
}
}).done(function callback(response) {
/* Redirect user to home page */
console.log("COULD THIS BE A SUCCESS?");
$(location).attr('href', this.url);
}).fail(function (error) {
/* Since we cannot modify the server, we will always fail. */
console.log("ERROR HAPPENED: " + error.status);
console.log(this.url);
$(location).attr('href', this.url);
});
}
我正在做的是检查我存储在 sessionStorage 中的 access_token 信息是否为空。我使用自 Epoch 以来的时间来生成令牌的创建时间以及理想情况下应该过期的时间。如果这些参数都满足,那么我就不会再打电话了。
否则,我会调用获取访问令牌,成功后会将我重定向到我在之前的文章中提到的 uri(您会看到我在 .fail 部分中有重定向。这是因为我没有权限在我的学校服务器上设置设置以绕过与 CORS 相关的问题,从而阻止我的调用成功,即使我创建的重定向 url 没问题。)。
然后当我的白名单 uri 被加载时(重定向到我的主页)我使用我的 <body>
标签。
home.jsp
<body onload="getAccessToken()">
在我的代码中,我让它在页面加载后调用此函数。这会调用函数 getAccessTokens()。
/**
* The bread and butter to calling the API. This function will be called once the
* user is redirected to the home page on success and without rejecting the terms
* we are demanding. Once through, this function parses the url for the access token
* and then stores it to be used later or when navigating away from the home page.
*/
function getAccessToken() {
access_token = sessionStorage.getItem("accessToken");
if (access_token === null) {
if (window.location.hash) {
console.log('Getting Access Token');
var hash = window.location.hash.substring(1);
var accessString = hash.indexOf("&");
/* 13 because that bypasses 'access_token' string */
access_token = hash.substring(13, accessString);
console.log("Access Token: " + access_token);
/* If first visit or regaining token, store it in session. */
if (typeof(Storage) !== "undefined") {
/* Store the access token */
sessionStorage.setItem("accessToken", access_token); // store token.
/* To see if we need a new token later. */
sessionStorage.setItem("tokenTimeStamp", secondsSinceEpoch);
/* Token expire time */
sessionStorage.setItem("tokenExpireStamp", secondsSinceEpoch + 3600);
console.log("Access Token Time Stamp: "
+ sessionStorage.getItem("tokenTimeStamp")
+ " seconds\nOR: " + dateNowMS + "\nToken expires at: "
+ sessionStorage.getItem("tokenExpireStamp"));
} else {
alert("Your browser does not support web storage...\nPlease try another browser.");
}
} else {
console.log('URL has no hash; no access token');
}
} else if (upTokenTime >= tokenExpireSec) {
console.log("Getting a new acess token...Redirecting");
/* Remove session vars so we dont have to check in implicitGrantFlow */
sessionStorage.clear();
$(location).attr('href', 'index.html'); // Get another access token, redirect back.
} else {
var timeLeft = (tokenExpireSec - upTokenTime);
console.log("Token still valid: " + Math.floor(timeLeft / 60) + " minutes left.");
}
在这里,一旦我从 url 获得访问令牌,我就会将令牌存储在会话存储中。我使用我之前 post 中提到的过程,但这里是完整的 JavaScript。如果评论后还有不清楚的地方请告诉我。
现在我们已经获取并存储了访问令牌,我们现在可以进行 api 调用。这是我的做法(并且一直在使用 qQuery,这是获取用户热门曲目的示例)。
示例api调用
/**
* Function will get the user's top tracks depending on the limit and offset
* specified in addition to the time_range specified in JSON format.
* @param time_range short/medium/long range the specifies how long ago.
* @param offset Where the indexing of top tracks starts.
* @param limit How many tracks at a time we can fetch (50 max.)
*/
function getUserTopTracks(time_range, offset, limit) {
$.get({
url: 'https://api.spotify.com/v1/me/top/tracks',
headers: {
'Authorization': 'Bearer ' + access_token,
},
data: {
limit: limit, // This is how many tracks to show (50 max @ a time).
offset: offset, // 0 = top of list, increase to get more tracks.
time_range: time_range // short/medium/long_term time ranges.
},
success: function (response) {
/* Get the items from the response (The limit) tracks. */
res = JSON.parse(JSON.stringify(response.items));
/* Get all the track details in the json */
for (i = 0; i < res.length; i++) {
console.log("Track: " + res[i]);
}
},
fail: function () {
console.log("getUserTopTracks(): api call failed!");
}
});
参数 time_range 指定为 "long_term" 以获取用户自开始以来的热门曲目(阅读更多关于 Spotify 的文档以获取更多信息)除了偏移量为 0 以从头开始并且 limit 等于 50,因为这是每次调用的最大提取数。
成功时我有我的响应变量 'response' 然后我希望解析的根从 'items' 部分开始以使解析更容易(你不必这样做,你可以只需使用 response.xxx.items.xxx)。然后我将响应打印到控制台。
这是您可以执行的基本操作,您决定如何处理或存储数据由您决定。我不是专家,我是上学期才开始学习网络编程的,我做的很多实践可能是错误的或不正确的。
你走在正确的轨道上。
弹出窗口会将您重定向到您在 redirect_uri=...
下添加的网站。它将向 url.
添加代码和状态查询参数
所以在作为您的 redirect_uri
主机的网页上,您可以解析完整的 URL.
不可能在单个页面上完成。
我正在尝试在纯 javascript 中创建一个 spotify 身份验证流程,以便用户可以登录,然后我可以为他们的帐户添加一个新的播放列表。根据我读过的说明,我使用了一个身份验证弹出窗口,一旦他们登录,就会在 URL 中获得访问令牌。我现在有一个用户可以验证的弹出窗口,一旦他们这样做,它就会在 url 中获得访问令牌。
我需要从弹出窗口中获取 url 并将其保存为全局变量,但我在 javascript.
中无法弄清楚如何执行此操作https://codepen.io/martin-barker/pen/YzPwXaz
我的 codepen 打开一个带有 let popup = window.open(
的弹出窗口,我可以在我的弹出窗口中 运行 一个函数来检测用户何时成功验证和 url 更改吗?在这种情况下,我想保存 url 用于解析并关闭我的弹出窗口
我的javascript代码如下:
async function spotifyAuth() {
let result = spotifyLogin()
}
//open popup
function spotifyLogin() {
console.log("inside spotifyLogin, opening popup")
let popup = window.open(`https://accounts.spotify.com/authorize?client_id=5a576333cfb1417fbffbfa3931b00478&response_type=token&redirect_uri=https://codepen.io/martin-barker/pen/YzPwXaz&show_dialog=true&scope=playlist-modify-public`, 'Login with Spotify', 'width=800,height=600')
}
//get url from popup and parse access token????
window.spotifyCallback = (payload) => {
console.log("inside window? ") //this line never appears in console
popup.close()
fetch('https://api.spotify.com/v1/me', {
headers: {
'Authorization': `Bearer ${payload}`
}
}).then(response => {
return response.json()
}).then(data => {
// do something with data
})
}
这是我在 JavaScript 中的做法。像你提到的全局变量:
var access_token = null;
在 Spotify 将用户重定向到您在仪表板上指定的 uri 后,我解析 url 以获取包含访问令牌的哈希值,如下所示:
var hash = window.location.hash.substring(1);
var accessString = hash.indexOf("&");
/* 13 because that bypasses 'access_token' string */
access_token = hash.substring(13, accessString);
console.log("Access Token: " + access_token);
输出是:
Access Token: BQAXe5JQOV_xZmAukmw6G430lreF...........rQByzZMcOIF2q2aszujN0wzV7pIxA4viMbQD6s
我将此访问令牌保存在 sessionStorage 中,以防用户离开页面并且 url 不包含 access_token。我假设这是隐式授权流程,因为您想使用纯 JavaScript。只需确保在它们过期后每小时重新获取一个访问令牌。
附录
我可以通过示例向您展示如何获取令牌并使用它。
我在 .html 页面上有一个按钮,单击该按钮后会在名为
的 JavaScript 文件中调用一个名为 implicitGrantFlow() 的函数Test.js
function implicitGrantFlow() {
/* If access token has been assigned in the past and is not expired, no request required. */
if (sessionStorage.getItem("accessToken") !== null &&
sessionStorage.getItem("tokenTimeStamp") !== null &&
upTokenTime < tokenExpireSec) {
var timeLeft = (tokenExpireSec - upTokenTime);
console.log("Token still valid: " + Math.floor(timeLeft / 60) + " minutes left.");
/* Navigate to the home page. */
$(location).attr('href', "home.jsp");
} else {
console.log("Token expired or never found, getting new token.");
$.ajax({
url: auth_url,
type: 'GET',
contentType: 'application/json',
data: {
client_id: client_id,
redirect_uri: redirect_uri,
scope: scopes,
response_type: response_type_token,
state: state
}
}).done(function callback(response) {
/* Redirect user to home page */
console.log("COULD THIS BE A SUCCESS?");
$(location).attr('href', this.url);
}).fail(function (error) {
/* Since we cannot modify the server, we will always fail. */
console.log("ERROR HAPPENED: " + error.status);
console.log(this.url);
$(location).attr('href', this.url);
});
}
我正在做的是检查我存储在 sessionStorage 中的 access_token 信息是否为空。我使用自 Epoch 以来的时间来生成令牌的创建时间以及理想情况下应该过期的时间。如果这些参数都满足,那么我就不会再打电话了。
否则,我会调用获取访问令牌,成功后会将我重定向到我在之前的文章中提到的 uri(您会看到我在 .fail 部分中有重定向。这是因为我没有权限在我的学校服务器上设置设置以绕过与 CORS 相关的问题,从而阻止我的调用成功,即使我创建的重定向 url 没问题。)。
然后当我的白名单 uri 被加载时(重定向到我的主页)我使用我的 <body>
标签。
home.jsp
<body onload="getAccessToken()">
在我的代码中,我让它在页面加载后调用此函数。这会调用函数 getAccessTokens()。
/**
* The bread and butter to calling the API. This function will be called once the
* user is redirected to the home page on success and without rejecting the terms
* we are demanding. Once through, this function parses the url for the access token
* and then stores it to be used later or when navigating away from the home page.
*/
function getAccessToken() {
access_token = sessionStorage.getItem("accessToken");
if (access_token === null) {
if (window.location.hash) {
console.log('Getting Access Token');
var hash = window.location.hash.substring(1);
var accessString = hash.indexOf("&");
/* 13 because that bypasses 'access_token' string */
access_token = hash.substring(13, accessString);
console.log("Access Token: " + access_token);
/* If first visit or regaining token, store it in session. */
if (typeof(Storage) !== "undefined") {
/* Store the access token */
sessionStorage.setItem("accessToken", access_token); // store token.
/* To see if we need a new token later. */
sessionStorage.setItem("tokenTimeStamp", secondsSinceEpoch);
/* Token expire time */
sessionStorage.setItem("tokenExpireStamp", secondsSinceEpoch + 3600);
console.log("Access Token Time Stamp: "
+ sessionStorage.getItem("tokenTimeStamp")
+ " seconds\nOR: " + dateNowMS + "\nToken expires at: "
+ sessionStorage.getItem("tokenExpireStamp"));
} else {
alert("Your browser does not support web storage...\nPlease try another browser.");
}
} else {
console.log('URL has no hash; no access token');
}
} else if (upTokenTime >= tokenExpireSec) {
console.log("Getting a new acess token...Redirecting");
/* Remove session vars so we dont have to check in implicitGrantFlow */
sessionStorage.clear();
$(location).attr('href', 'index.html'); // Get another access token, redirect back.
} else {
var timeLeft = (tokenExpireSec - upTokenTime);
console.log("Token still valid: " + Math.floor(timeLeft / 60) + " minutes left.");
}
在这里,一旦我从 url 获得访问令牌,我就会将令牌存储在会话存储中。我使用我之前 post 中提到的过程,但这里是完整的 JavaScript。如果评论后还有不清楚的地方请告诉我。
现在我们已经获取并存储了访问令牌,我们现在可以进行 api 调用。这是我的做法(并且一直在使用 qQuery,这是获取用户热门曲目的示例)。
示例api调用
/**
* Function will get the user's top tracks depending on the limit and offset
* specified in addition to the time_range specified in JSON format.
* @param time_range short/medium/long range the specifies how long ago.
* @param offset Where the indexing of top tracks starts.
* @param limit How many tracks at a time we can fetch (50 max.)
*/
function getUserTopTracks(time_range, offset, limit) {
$.get({
url: 'https://api.spotify.com/v1/me/top/tracks',
headers: {
'Authorization': 'Bearer ' + access_token,
},
data: {
limit: limit, // This is how many tracks to show (50 max @ a time).
offset: offset, // 0 = top of list, increase to get more tracks.
time_range: time_range // short/medium/long_term time ranges.
},
success: function (response) {
/* Get the items from the response (The limit) tracks. */
res = JSON.parse(JSON.stringify(response.items));
/* Get all the track details in the json */
for (i = 0; i < res.length; i++) {
console.log("Track: " + res[i]);
}
},
fail: function () {
console.log("getUserTopTracks(): api call failed!");
}
});
参数 time_range 指定为 "long_term" 以获取用户自开始以来的热门曲目(阅读更多关于 Spotify 的文档以获取更多信息)除了偏移量为 0 以从头开始并且 limit 等于 50,因为这是每次调用的最大提取数。
成功时我有我的响应变量 'response' 然后我希望解析的根从 'items' 部分开始以使解析更容易(你不必这样做,你可以只需使用 response.xxx.items.xxx)。然后我将响应打印到控制台。
这是您可以执行的基本操作,您决定如何处理或存储数据由您决定。我不是专家,我是上学期才开始学习网络编程的,我做的很多实践可能是错误的或不正确的。
你走在正确的轨道上。
弹出窗口会将您重定向到您在 redirect_uri=...
下添加的网站。它将向 url.
所以在作为您的 redirect_uri
主机的网页上,您可以解析完整的 URL.
不可能在单个页面上完成。