惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
云风的 BLOG
云风的 BLOG
博客园 - 三生石上(FineUI控件)
人人都是产品经理
人人都是产品经理
美团技术团队
V
Visual Studio Blog
有赞技术团队
有赞技术团队
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
博客园 - 司徒正美
D
Docker
宝玉的分享
宝玉的分享
小众软件
小众软件
U
Unit 42
A
About on SuperTechFans
I
InfoQ
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Fortinet All Blogs
Microsoft Security Blog
Microsoft Security Blog
月光博客
月光博客
G
Google Developers Blog
The Cloudflare Blog
H
Help Net Security
B
Blog
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
I
Intezer
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyberwarzone
Cyberwarzone
C
Cyber Attacks, Cyber Crime and Cyber Security
Blog — PlanetScale
Blog — PlanetScale
C
Cisco Blogs
Project Zero
Project Zero
腾讯CDC
Help Net Security
Help Net Security
Latest news
Latest news
A
Arctic Wolf
T
The Exploit Database - CXSecurity.com
B
Blog RSS Feed
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Hacker News
The Hacker News
P
Palo Alto Networks Blog
AI
AI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

姓王者的博客

Linux用户Secure Boot自主维护指南 | 姓王者的博客 MAD Bugs 已经开始——关于信息安全的军备竞赛 | 姓王者的博客 解决钉钉Dingtalk无法在Linux新版内核上启动问题-修复可执行栈错误 | 姓王者的博客 突发:GitHub 正遭受大规模 Issue 赌博广告轰炸 | 姓王者的博客 Ubuntu26.04-beta体验:坚毅浣熊! | 姓王者的博客 fakeclaw装作龙虾发贴吧 | 姓王者的博客 找回12年前的QQ记忆 | 姓王者的博客 在Linux上玩Flash网页游戏-洛克王国 | 姓王者的博客 Copilot将使用交互数据来训练 | 姓王者的博客 重要通知-请更新我的GPG公钥 | 姓王者的博客 为了自由Android | 姓王者的博客 GPL"2,3"事 | 姓王者的博客 短文-对VitePlus的一点🤏小贡献 | 姓王者的博客 Bing收录没了?亲测有效的快速恢复指南 | 姓王者的博客 解决桌面设备二维码快速识别的工具-ClipQR | 姓王者的博客 解决 Nautilus 自定义终端插件安装依赖问题 | 姓王者的博客 OpenClaw 该熄火了 | 姓王者的博客 Vite8 - 统一的基建开始 | 姓王者的博客 Astro 6 推出啦 | 姓王者的博客 ubuntu的openvpn异常暂停推送更新 | 姓王者的博客 Ubuntu 24.04 安装 Win10 虚拟机 | 姓王者的博客 ESA-后记:热爱阿里云 | 姓王者的博客 Moonbit 0.8.0 重大发布,我也要改一下我的包 | 姓王者的博客 ESA Pages 边缘开发大赛获奖 | 姓王者的博客 Astro: 优化katex,mermaid和灯箱使用 | 姓王者的博客 从edgeone迁移到esa | 姓王者的博客 出租人类:AI时代的荒诞与真实 | 姓王者的博客 Astro 5.17构建性能优化实践:从18s到13s | 姓王者的博客 Moonbit License Checker 开发使用 | 姓王者的博客 Stalux Astro博客主题自荐 | 姓王者的博客 把Hexo永久链接迁移到Astro | 姓王者的博客 再见👋 LeanCloud | 姓王者的博客 2025年终总结 | 姓王者的博客 许可合规-fancybox | 姓王者的博客 博客主题的软著下来了 | 姓王者的博客 友链图谱 - 汇聚千丝万缕的联系 | 姓王者的博客 chen-er 专为Chen式ER图打造的npm包 | 姓王者的博客 为什么我推荐你使用GPG来加密你的邮件 | 姓王者的博客 2025第三方客户端登录东北大学邮箱 | 姓王者的博客 好久没更新了,过去与未来 | 姓王者的博客 1024 重要的日子 | 姓王者的博客 再也不见Windows10 | 姓王者的博客 偷梁换柱,解决Ubuntu24.04安装Packet Tracer缺失依赖问题 | 姓王者的博客 中秋-来试试Moonbit吧 | 姓王者的博客 Obsidian使用体验 | 姓王者的博客 猪猪侠·一只老猪的逆袭 | 姓王者的博客 国庆日纪念 | 姓王者的博客 GNU 42周年,AI时代的自由精神 | 姓王者的博客 解决Linux上启动游戏总是默认English的情况 | 姓王者的博客 7x24:运维使命 | 姓王者的博客 Tauri2.x实现系统菜单导航Vue路由 | 姓王者的博客 计算机图形学-基本图形生成算法 | 姓王者的博客 数据库原理-关系数据 | 姓王者的博客 数据库原理-设计技巧 | 姓王者的博客 数据库原理E-R模型 | 姓王者的博客 旧忆 - 我曾玩过的游戏 | 姓王者的博客 再谈自由软件 | 姓王者的博客 可能解决Tauri多窗口应用阻塞问题 | 姓王者的博客 Xingwangzhe! Z-Library We miss you and we need your help | 姓王者的博客 计算机组成原理第二章 - 定点数与浮点数 | 姓王者的博客 计算机组成原理第一章 | 姓王者的博客 不小心写死循环窗口弹出了 | 姓王者的博客 美化Grub界面 | 姓王者的博客 计算机图形学-图形的表示与数据结构 | 姓王者的博客 计算机图形学绪论 | 姓王者的博客 为什么说,大学教育与社会脱节 | 姓王者的博客 VSCode Remote 远程连接服务器记录 | 姓王者的博客 解决Tauri2.x拖拽事件问题 | 姓王者的博客 新学期第一课《计算机图形学》报告 | 姓王者的博客 Tauri在GNOME46+上通知无效的临时解决方法 | 姓王者的博客 窃文者:未经授权转载我文章 | 姓王者的博客 GPG公钥分享文化 | 姓王者的博客 解决在ubuntu上,打包vscode插件问题 | 姓王者的博客 伪造squaremap的玩家显示 | 姓王者的博客 爆,沉浸式翻译泄露敏感信息 | 姓王者的博客 读书:《Free as in Freedom》——若为自由故 | 姓王者的博客 首页文章列表懒加载优化 | 姓王者的博客 Ubuntu 24.04 安装 Vivado 2018.3 | 姓王者的博客 腾讯Edgeone免费版体验 | 姓王者的博客 在 Ubuntu 上实现 Thetis FIDO U2F 密钥登录 | 姓王者的博客 Thetis物理密钥,为什么我们应该使用物理密钥 | 姓王者的博客 高考生过来看!教你精准转换录取位次! | 姓王者的博客 ubuntu无法访问windows磁盘问题 | 姓王者的博客 收信有感,防范钓鱼邮件 | 姓王者的博客 自由不止软件-记录一次zlib上传书籍 | 姓王者的博客 时隔两年,通关夺命邮差2 | 姓王者的博客 博客一周年了,竟然坚持了下来 | 姓王者的博客 Minecraft大电影:不建不散! | 姓王者的博客 是时候了解docker了! | 姓王者的博客 编译原理:LL(1)文法 | 姓王者的博客 编译原理:文法转换 | 姓王者的博客 离散数学:子群的陪集及拉格朗日定理 | 姓王者的博客 离散数学:半群,独异点 | 姓王者的博客 《人工智能生成合成内容标识办法》与个人博客--我们应该做什么? | 姓王者的博客 通识学习:形式语言与自动机,布尔代数与数进制 | 姓王者的博客 Webmapview:一个我的世界内置网页地图浏览Fabric模组 | 姓王者的博客 海岛机器人农场试玩 | 姓王者的博客 正则表达式学习 | 姓王者的博客 抓取个人博客文章目录到github主页 | 姓王者的博客 制作github贪吃蛇贡献图 | 姓王者的博客
在hexo-next配置gitalk | 姓王者的博客
作者:xingwangzhe · 2024-09-20 · via 姓王者的博客

打开github,点击右上角的图片,选择Settings,然后在左边栏最下方找到Developer settings并点击,然后在左边栏找到OAuth Apps选中点击,主页面右上角有new OAuth App 点击创建新OAuth Apps,输入必要参数,记录ID,创建密码,记得复制,然后转到blog\themes\next下的_config.yml文件修改其中的配置,转到cloudflare配置worker,然后就大功告成了,不过光听我讲没用,看图更容易理解,所以请一步一步按图片示意做:

## ---------------------------------------------------------------

## Comments Settings

## See: https://theme-next.org/docs/third-party-services/comments

## ---------------------------------------------------------------

## Multiple Comment System Support

comments:

#use: Valine

text: true

# Available values: tabs | buttons

style: tabs

count: true

# Choose a comment system to be displayed by default.

# Available values: changyan | disqus | disqusjs | gitalk | livere | valine

active: gitalk

# Setting `true` means remembering the comment system selected by the visitor.

storage: true

# Lazyload all comment systems.

lazyload: false

# Modify texts or order for any navs, here are some examples.

nav:

gitalk:

order: -1

#disqus:

# text: Load Disqus

# order: -1

#gitalk:

# order: -2

## Gitalk

## For more information: https://gitalk.github.io, https://github.com/gitalk/gitalk

gitalk:

enable: true

github_id: xingwangzhe

repo: xingwangzhe.github.io

client_id: sdaf # OAuth app的

client_secret: asdfghjgds #同上

admin_user: xingwangzhe

distraction_free_mode: true # Facebook-like distraction free mode

# Gitalk's display language depends on user's browser or system environment

# If you want everyone visiting your site to see a uniform language, you can set a force language value

# Available values: en | es-ES | fr | ru | zh-CN | zh-TW

language: zh-CN

proxy: "https://cors-anywhere.xingwangzhe.workers.dev/https://github.com/login/oauth/access_token"

#worker,请记住这段链接,接下来要用到

const exclude = []; // Regexp for blacklisted urls

const include = [/^https?:\/\/.*xingwangzhe\.github\.io$/, /^https?:\/\/localhost/]; // Regexp for whitelisted origins e.g.

const apiKeys = {

EZWTLwVEqFnaycMzdhBz: {

name: "Test App",

expired: false,

exclude: [], // Regexp for blacklisted urls

include: [

"^http.?://xingwangzhe.github.io$",

"xingwangzhe.github.io$",

"^https?://localhost/",

], // Regexp for whitelisted origins

},

};

// Config is all above this line.

// It should not be necessary to change anything below.

function verifyCredentials(request) {

// Throws exception on verification failure.

const requestApiKey = request.headers.get("x-cors-proxy-api-key");

if (!Object.keys(apiKeys).includes(requestApiKey)) {

throw new UnauthorizedException("Invalid authorization key.");

}

if (apiKeys[requestApiKey].expired) {

throw new UnauthorizedException("Expired authorization key.");

}

if (

apiKeys[requestApiKey].expiresAt &&

apiKeys[requestApiKey].expiresAt.getTime() < Date.now()

) {

throw new UnauthorizedException(

`Expired authorization key.\nKey was valid until: ${apiKeys[requestApiKey].expiresAt}`,

);

}

return apiKeys[requestApiKey];

}

function checkRequiredHeadersPresent(request) {

// Throws exception on verification failure.

if (!request.headers.get("Origin") && !request.headers.get("x-requested-with")) {

throw new BadRequestException(

"Missing required request header. Must specify one of: origin,x-requested-with",

);

}

}

function UnauthorizedException(reason) {

this.status = 401;

this.statusText = "Unauthorized";

this.reason = reason;

}

function BadRequestException(reason) {

this.status = 400;

this.statusText = "Bad Request";

this.reason = reason;

}

function isListed(uri, listing) {

let returnValue = false;

console.log(uri);

if (typeof uri === "string") {

for (const m of listing) {

if (uri.match(m) !== null) {

returnValue = true;

}

}

} else {

// Decide what to do when Origin is null

returnValue = true; // True accepts null origins false rejects them.

}

return returnValue;

}

function fix(myHeaders, request, isOPTIONS) {

myHeaders.set("Access-Control-Allow-Origin", request.headers.get("Origin"));

if (isOPTIONS) {

myHeaders.set(

"Access-Control-Allow-Methods",

request.headers.get("access-control-request-method"),

);

const acrh = request.headers.get("access-control-request-headers");

if (acrh) {

myHeaders.set("Access-Control-Allow-Headers", acrh);

}

myHeaders.delete("X-Content-Type-Options");

}

return myHeaders;

}

function parseURL(requestUrl) {

const match = requestUrl.match(

/^(?:(https?:)?\/\/)?(([^/?]+?)(?::(\d{0,5})(?=[/?]|$))?)([/?][\S\s]*|$)/i,

);

// ^^^^^^^ ^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^

// 1:protocol 3:hostname 4:port 5:path + query string

// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

// 2:host

if (!match) {

console.log("no match");

throw new BadRequestException("Invalid URL for proxy request.");

}

console.log("parseURL:match:", match);

if (!match[1]) {

console.log("nothing in match group 1");

if (/^https?:/i.test(requestUrl)) {

console.log(

'The pattern at top could mistakenly parse "http:///" as host="http:" and path=///.',

);

throw new BadRequestException("Invalid URL for proxy request.");

}

// Scheme is omitted.

if (requestUrl.lastIndexOf("//", 0) === -1) {

console.log('"//" is omitted');

requestUrl = "//" + requestUrl;

}

requestUrl = (match[4] === "443" ? "https:" : "http:") + requestUrl;

}

const parsed = new URL(requestUrl);

if (!parsed.hostname) {

console.log('"http://:1/" and "http:/notenoughslashes" could end up here.');

throw new BadRequestException("Invalid URL for proxy request.");

}

return parsed;

}

async function proxyRequest(request, activeApiKey) {

const isOPTIONS = request.method === "OPTIONS";

const originUrl = new URL(request.url);

const origin = request.headers.get("Origin");

// ParseURL throws when the url is invalid

const fetchUrl = parseURL(request.url.replace(originUrl.origin, "").slice(1));

// Throws if it fails the check

checkRequiredHeadersPresent(request);

// Excluding urls which are not allowed as destination urls

// Exclude origins which are not int he included ones

if (

isListed(fetchUrl.toString(), [...exclude, ...(activeApiKey?.exclude || [])]) ||

!isListed(origin, [...include, ...(activeApiKey?.include || [])])

) {

throw new BadRequestException("Origin or Destination URL is not allowed.");

}

let corsHeaders = request.headers.get("x-cors-headers");

if (corsHeaders !== null) {

try {

corsHeaders = JSON.parse(corsHeaders);

} catch {}

}

if (!originUrl.pathname.startsWith("/")) {

throw new BadRequestException('Pathname does not start with "/"');

}

const recvHpaireaders = {};

for (const pair of request.headers.entries()) {

if (

pair[0].match("^origin") === null &&

pair[0].match("eferer") === null &&

pair[0].match("^cf-") === null &&

pair[0].match("^x-forw") === null &&

pair[0].match("^x-cors-headers") === null

) {

recvHpaireaders[pair[0]] = pair[1];

}

}

if (corsHeaders !== null) {

for (const c of Object.entries(corsHeaders)) {

recvHpaireaders[c[0]] = c[1];

}

}

const newRequest = new Request(request, {

headers: recvHpaireaders,

});

const response = await fetch(fetchUrl, newRequest);

let myHeaders = new Headers(response.headers);

const newCorsHeaders = [];

const allh = {};

for (const pair of response.headers.entries()) {

newCorsHeaders.push(pair[0]);

allh[pair[0]] = pair[1];

}

newCorsHeaders.push("cors-received-headers");

myHeaders = fix(myHeaders, request, isOPTIONS);

myHeaders.set("Access-Control-Expose-Headers", newCorsHeaders.join(","));

myHeaders.set("cors-received-headers", JSON.stringify(allh));

const body = isOPTIONS ? null : await response.arrayBuffer();

return new Response(body, {

headers: myHeaders,

status: isOPTIONS ? 200 : response.status,

statusText: isOPTIONS ? "OK" : response.statusText,

});

}

function homeRequest(request) {

const isOPTIONS = request.method === "OPTIONS";

const originUrl = new URL(request.url);

const origin = request.headers.get("Origin");

const remIp = request.headers.get("CF-Connecting-IP");

const corsHeaders = request.headers.get("x-cors-headers");

let myHeaders = new Headers();

myHeaders = fix(myHeaders, request, isOPTIONS);

let country = false;

let colo = false;

if (typeof request.cf !== "undefined") {

country = typeof request.cf.country === "undefined" ? false : request.cf.country;

colo = typeof request.cf.colo === "undefined" ? false : request.cf.colo;

}

return new Response(

"CLOUDFLARE-CORS-ANYWHERE\n\n" +

"Source:\nhttps://github.com/chrisspiegl/cloudflare-cors-anywhere\n\n" +

"Usage:\n" +

originUrl.origin +

"/{uri}\n" +

"Header x-cors-proxy-api-key must be set with valid api key\n" +

"Header origin or x-requested-with must be set\n\n" +

// + 'Limits: 100,000 requests/day\n'

// + ' 1,000 requests/10 minutes\n\n'

(origin === null ? "" : "Origin: " + origin + "\n") +

"Ip: " +

remIp +

"\n" +

(country ? "Country: " + country + "\n" : "") +

(colo ? "Datacenter: " + colo + "\n" : "") +

"\n" +

(corsHeaders === null ? "" : "\nx-cors-headers: " + JSON.stringify(corsHeaders)),

{ status: 200, headers: myHeaders },

);

}

async function handleRequest(request) {

const { protocol, pathname } = new URL(request.url);

// In the case of a "Basic" authentication, the exchange MUST happen over an HTTPS (TLS) connection to be secure.

if (protocol !== "https:" || request.headers.get("x-forwarded-proto") !== "https") {

throw new BadRequestException("Must use a HTTPS connection.");

}

switch (pathname) {

case "/favicon.ico":

case "/robots.txt":

return new Response(null, { status: 204 });

case "/":

return homeRequest(request);

default: {

// Not 100% sure if this is a good idea…

// Right now all OPTIONS requests are just simply replied to because otherwise they fail.

// This is necessary because apparently, OPTIONS requests do not carry the `x-cors-proxy-api-key` header so this can not be authorized.

if (request.method === "OPTIONS") {

return new Response(null, {

headers: fix(new Headers(), request, true),

status: 200,

statusText: "OK",

});

}

// The "x-cors-proxy-api-key" header is sent when authenticated.

//if (request.headers.has('x-cors-proxy-api-key')) {

// Throws exception when authorization fails.

//const activeApiKey = verifyCredentials(request);

// Only returns this response when no exception is thrown.

return proxyRequest(request);

//}

// Not authenticated.

//throw new UnauthorizedException('Valid x-cors-proxy-api-key header has to be provided.');

}

}

}

addEventListener("fetch", async (event) => {

event.respondWith(

handleRequest(event.request).catch((error) => {

const message = error.reason || error.stack || "Unknown Error";

return new Response(message, {

status: error.status || 500,

statusText: error.statusText || null,

headers: {

"Content-Type": "text/plain;charset=UTF-8",

// Disables caching by default.

"Cache-Control": "no-store",

// Returns the "Content-Length" header for HTTP HEAD requests.

"Content-Length": message.length,

},

});

}),

);

});

再次 hexo clean && hexo g -d, 即可使用 gitalk, 评论区会作为设置中的 repo 的 issue 存在.

如果你为你的博客购买了其他的域名,记得要在OAuh Apps设置的返回链接改成你的域名 当然,连带着worker应该也要改,但是在这里我还是建议你直接使用无脑的那个proxy