添加了一个修改
This commit is contained in:
168
HASH_MODE_SPOTIFY_SOLUTION.md
Normal file
168
HASH_MODE_SPOTIFY_SOLUTION.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# ✅ Hash 模式下的 Spotify OAuth 完美解决方案
|
||||
|
||||
## 🎯 最终方案
|
||||
|
||||
### 1. Spotify Dashboard 配置
|
||||
|
||||
**Redirect URIs:**
|
||||
```
|
||||
https://sports.rucky.cn/ (生产环境)
|
||||
http://localhost:5173/ (开发环境)
|
||||
```
|
||||
|
||||
⚠️ **重要:不要使用 hash 格式!**
|
||||
- ❌ `https://sports.rucky.cn/#/callback`
|
||||
- ✅ `https://sports.rucky.cn/`
|
||||
|
||||
### 2. 工作流程
|
||||
|
||||
```
|
||||
用户点击"连接 Spotify 账号"
|
||||
↓
|
||||
跳转到 Spotify (redirect_uri=https://sports.rucky.cn/)
|
||||
↓
|
||||
用户授权
|
||||
↓
|
||||
Spotify 返回: https://sports.rucky.cn/?code=xxx&state=xxx
|
||||
↓
|
||||
Home.vue 检测到 code 参数
|
||||
↓
|
||||
保存参数到 sessionStorage
|
||||
↓
|
||||
跳转到 #/callback 路由
|
||||
↓
|
||||
SpotifyCallback.vue 处理授权
|
||||
↓
|
||||
授权成功,跳转到音乐律动页面
|
||||
```
|
||||
|
||||
### 3. 关键代码
|
||||
|
||||
**MusicRhythm.vue:**
|
||||
```typescript
|
||||
// 使用根路径作为 redirect_uri
|
||||
const REDIRECT_URI = window.location.origin + '/'
|
||||
```
|
||||
|
||||
**Home.vue:**
|
||||
```typescript
|
||||
onMounted(() => {
|
||||
// 检测 Spotify 回调
|
||||
const urlParams = new URLSearchParams(window.location.search)
|
||||
|
||||
if (urlParams.has('code') && urlParams.has('state')) {
|
||||
// 保存参数并跳转到 callback 路由
|
||||
sessionStorage.setItem('spotify_callback_params', window.location.search)
|
||||
router.replace('/callback')
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**SpotifyCallback.vue:**
|
||||
```typescript
|
||||
onMounted(async () => {
|
||||
// 从 sessionStorage 恢复参数
|
||||
const savedParams = sessionStorage.getItem('spotify_callback_params')
|
||||
|
||||
if (savedParams) {
|
||||
// 恢复 URL 参数供 spotifyService 处理
|
||||
const currentUrl = new URL(window.location.href)
|
||||
currentUrl.search = savedParams
|
||||
window.history.replaceState({}, '', currentUrl.toString())
|
||||
|
||||
// 清理
|
||||
sessionStorage.removeItem('spotify_callback_params')
|
||||
}
|
||||
|
||||
// 处理授权
|
||||
if (window.location.search.includes('code=')) {
|
||||
await spotifyService.handleCallback()
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## ✅ 优势
|
||||
|
||||
1. **兼容性好**
|
||||
- 支持 Hash 模式路由
|
||||
- 不需要服务器配置 SPA 支持
|
||||
|
||||
2. **用户体验流畅**
|
||||
- 自动检测和处理回调
|
||||
- 清晰的加载和成功提示
|
||||
- 自动跳转回原页面
|
||||
|
||||
3. **安全可靠**
|
||||
- State 参数验证(CSRF 保护)
|
||||
- 参数临时存储,用后即删
|
||||
- URL 清理,不暴露敏感信息
|
||||
|
||||
## 📋 部署步骤
|
||||
|
||||
1. **修改 Spotify Dashboard**
|
||||
- 删除 `https://sports.rucky.cn/#/callback`
|
||||
- 添加 `https://sports.rucky.cn/`
|
||||
- 保存设置
|
||||
|
||||
2. **部署新代码**
|
||||
```bash
|
||||
# 代码已构建完成
|
||||
rsync -avz --delete dist/ user@sports.rucky.cn:/var/www/sports.rucky.cn/
|
||||
```
|
||||
|
||||
3. **清除缓存测试**
|
||||
```javascript
|
||||
localStorage.clear()
|
||||
sessionStorage.clear()
|
||||
```
|
||||
|
||||
## 🧪 测试流程
|
||||
|
||||
1. 访问 https://sports.rucky.cn/
|
||||
2. 进入音乐律动页面 (#/music-rhythm)
|
||||
3. 点击 Spotify 标签
|
||||
4. 点击"连接 Spotify 账号"
|
||||
5. 在 Spotify 页面授权
|
||||
6. 应该看到:
|
||||
- ✅ 返回到首页(带 code 参数)
|
||||
- ✅ 自动跳转到 #/callback
|
||||
- ✅ 显示"正在处理授权..."
|
||||
- ✅ 显示"授权成功!"
|
||||
- ✅ 自动跳转回音乐律动页面
|
||||
- ✅ Spotify 功能正常使用
|
||||
|
||||
## 🔍 调试
|
||||
|
||||
如果有问题,检查浏览器控制台:
|
||||
|
||||
```javascript
|
||||
// 应该看到以下日志:
|
||||
"✅ Spotify OAuth callback detected!"
|
||||
"Code: AQBTrOWWZ8883ozZ1RD..."
|
||||
"State: RxEHF89uqI2Y0YFR"
|
||||
"✅ Processing Spotify OAuth callback from sessionStorage"
|
||||
```
|
||||
|
||||
## 📝 注意事项
|
||||
|
||||
1. **必须使用根路径**
|
||||
- Spotify 不支持 hash 格式的 redirect_uri
|
||||
- 只能使用 `https://sports.rucky.cn/`
|
||||
|
||||
2. **Hash 模式的限制**
|
||||
- URL 会短暂显示 code 参数
|
||||
- 需要额外的跳转步骤
|
||||
|
||||
3. **sessionStorage 的作用**
|
||||
- 临时保存参数
|
||||
- 跨路由传递数据
|
||||
- 用后自动清理
|
||||
|
||||
## ✅ 问题已解决
|
||||
|
||||
- ✅ 支持 Hash 模式路由
|
||||
- ✅ 正确处理 Spotify 回调
|
||||
- ✅ 完整的授权流程
|
||||
- ✅ 良好的用户体验
|
||||
|
||||
现在部署新代码,就能完美使用了!🎉
|
||||
Reference in New Issue
Block a user