-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathcsp.js
More file actions
206 lines (179 loc) · 5.62 KB
/
csp.js
File metadata and controls
206 lines (179 loc) · 5.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
/**
* CSP (Content Security Policy) 工具函数
* 用于处理视频播放时的CSP策略和防盗链绕过
*/
/**
* Referrer 策略选项
*/
export const REFERRER_POLICIES = {
NO_REFERRER: 'no-referrer',
NO_REFERRER_WHEN_DOWNGRADE: 'no-referrer-when-downgrade',
ORIGIN: 'origin',
ORIGIN_WHEN_CROSS_ORIGIN: 'origin-when-cross-origin',
SAME_ORIGIN: 'same-origin',
STRICT_ORIGIN: 'strict-origin',
STRICT_ORIGIN_WHEN_CROSS_ORIGIN: 'strict-origin-when-cross-origin',
UNSAFE_URL: 'unsafe-url'
}
/**
* Referrer 策略选项列表(用于UI选择)
*/
export const REFERRER_POLICIES_LIST = [
{ value: 'no-referrer', label: '不发送Referrer' },
{ value: 'no-referrer-when-downgrade', label: 'HTTPS到HTTP时不发送' },
{ value: 'origin', label: '只发送源域名' },
{ value: 'origin-when-cross-origin', label: '跨域时只发送源域名' },
{ value: 'same-origin', label: '同源时发送完整Referrer' },
{ value: 'strict-origin', label: '严格源域名策略' },
{ value: 'strict-origin-when-cross-origin', label: '跨域时严格控制' },
{ value: 'unsafe-url', label: '总是发送完整Referrer(不安全)' }
]
/**
* 获取当前的referrer策略
* @returns {string} 当前的referrer策略
*/
export function getCurrentReferrerPolicy() {
const metaTag = document.querySelector('meta[name="referrer"]')
return metaTag ? metaTag.getAttribute('content') : 'default'
}
/**
* 设置全局referrer策略
* @param {string} policy - referrer策略
*/
export function setGlobalReferrerPolicy(policy) {
let metaTag = document.querySelector('meta[name="referrer"]')
if (!metaTag) {
metaTag = document.createElement('meta')
metaTag.setAttribute('name', 'referrer')
document.head.appendChild(metaTag)
}
metaTag.setAttribute('content', policy)
console.log(`已设置全局referrer策略为: ${policy}`)
}
/**
* 为特定的视频元素设置referrer策略
* @param {HTMLVideoElement} videoElement - 视频元素
* @param {string} policy - referrer策略
*/
export function setVideoReferrerPolicy(videoElement, policy) {
if (videoElement && videoElement.tagName === 'VIDEO') {
videoElement.setAttribute('referrerpolicy', policy)
console.log(`已为视频元素设置referrer策略: ${policy}`)
}
}
/**
* 创建带有特定referrer策略的视频元素
* @param {string} policy - referrer策略
* @returns {HTMLVideoElement} 配置好的视频元素
*/
export function createVideoWithReferrerPolicy(policy = REFERRER_POLICIES.NO_REFERRER) {
const video = document.createElement('video')
video.setAttribute('referrerpolicy', policy)
video.setAttribute('crossorigin', 'anonymous')
return video
}
/**
* 为fetch请求设置no-referrer策略
* @param {string} url - 请求URL
* @param {object} options - fetch选项
* @returns {Promise} fetch请求
*/
export function fetchWithNoReferrer(url, options = {}) {
return fetch(url, {
...options,
referrerPolicy: REFERRER_POLICIES.NO_REFERRER
})
}
/**
* 检查URL是否可能需要特殊的referrer策略
* @param {string} url - 视频URL
* @returns {boolean} 是否需要特殊处理
*/
export function needsSpecialReferrerPolicy(url) {
if (!url) return false
// 常见的需要no-referrer的域名模式
const specialDomains = [
'qq.com',
'iqiyi.com',
'youku.com',
'bilibili.com',
'douyin.com',
'tiktok.com',
'youtube.com',
'vimeo.com'
]
return specialDomains.some(domain => url.includes(domain))
}
/**
* 智能设置referrer策略
* 根据URL自动判断是否需要设置no-referrer
* @param {string} videoUrl - 视频URL
* @param {HTMLVideoElement} videoElement - 视频元素(可选)
*/
export function smartSetReferrerPolicy(videoUrl, videoElement = null) {
const policy = needsSpecialReferrerPolicy(videoUrl)
? REFERRER_POLICIES.NO_REFERRER
: REFERRER_POLICIES.STRICT_ORIGIN_WHEN_CROSS_ORIGIN
// 设置全局策略
setGlobalReferrerPolicy(policy)
// 如果提供了视频元素,也为其设置策略
if (videoElement) {
setVideoReferrerPolicy(videoElement, policy)
}
console.log(`智能设置referrer策略: ${policy} (URL: ${videoUrl})`)
return policy
}
/**
* 重置referrer策略为默认值
*/
export function resetReferrerPolicy() {
setGlobalReferrerPolicy(REFERRER_POLICIES.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
}
/**
* CSP绕过配置对象
*/
export const CSP_BYPASS_CONFIG = {
// 是否启用CSP绕过功能
enabled: true,
// 默认referrer策略
referrerPolicy: REFERRER_POLICIES.NO_REFERRER,
// 是否启用自动CSP绕过
autoBypass: true,
// 是否在播放失败时自动重试不同的策略
autoRetry: true,
// 重试策略列表
retryPolicies: [
REFERRER_POLICIES.NO_REFERRER,
REFERRER_POLICIES.ORIGIN,
REFERRER_POLICIES.SAME_ORIGIN,
REFERRER_POLICIES.UNSAFE_URL
]
}
/**
* 获取CSP绕过配置
* @returns {object} CSP配置对象
*/
export function getCSPConfig() {
const stored = localStorage.getItem('csp_bypass_config')
return stored ? { ...CSP_BYPASS_CONFIG, ...JSON.parse(stored) } : CSP_BYPASS_CONFIG
}
/**
* 保存CSP绕过配置
* @param {object} config - 配置对象
*/
export function saveCSPConfig(config) {
localStorage.setItem('csp_bypass_config', JSON.stringify(config))
}
/**
* 应用CSP绕过策略到视频播放
* @param {string} videoUrl - 视频URL
* @param {HTMLVideoElement} videoElement - 视频元素
* @returns {string} 应用的策略
*/
export function applyCSPBypass(videoUrl, videoElement) {
const config = getCSPConfig()
if (!config.autoBypass) {
return getCurrentReferrerPolicy()
}
return smartSetReferrerPolicy(videoUrl, videoElement)
}