feat!: allowlist & denylist (#13681)

* feat!: allowlist & denylist

* Update website/i18n/zh/docusaurus-plugin-content-docs/current/install/README.md

* Update website/i18n/zh/docusaurus-plugin-content-docs/current/install/README.md

* Update website/i18n/zh/docusaurus-plugin-content-docs/current/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* Update website/docs/install/README.md

* chore: revert

---------
This commit is contained in:
Henry Wang
2023-11-03 13:21:17 +00:00
committed by GitHub
parent 90026020a8
commit d6056e2dbc
7 changed files with 72 additions and 72 deletions

View File

@@ -85,8 +85,8 @@ const calculateValue = () => {
pass: envs.HTTP_BASIC_AUTH_PASS || 'passw0rd',
},
// access control
blacklist: envs.BLACKLIST && envs.BLACKLIST.split(','),
whitelist: envs.WHITELIST && envs.WHITELIST.split(','),
denylist: envs.DENYLIST && envs.DENYLIST.split(','),
allowlist: envs.ALLOWLIST && envs.ALLOWLIST.split(','),
allowLocalhost: envs.ALLOW_LOCALHOST,
accessKey: envs.ACCESS_KEY,
// logging

View File

@@ -15,7 +15,7 @@ module.exports = async (ctx, next) => {
const accessKey = ctx.query.key;
const accessCode = ctx.query.code;
const isControlled = config.accessKey || config.whitelist || config.blacklist;
const isControlled = config.accessKey || config.allowlist || config.denylist;
const allowLocalhost = config.allowLocalhost && (await isLocalhost(ip));
@@ -38,14 +38,14 @@ module.exports = async (ctx, next) => {
}
}
if (config.whitelist) {
if (config.whitelist.find((white) => ip.includes(white) || requestPath.includes(white) || requestUA.includes(white))) {
if (config.allowlist) {
if (config.allowlist.find((item) => ip.includes(item) || requestPath.includes(item) || requestUA.includes(item))) {
return grant();
}
}
if (config.blacklist) {
if (!config.blacklist.find((black) => ip.includes(black) || requestPath.includes(black) || requestUA.includes(black))) {
if (config.denylist) {
if (!config.denylist.find((item) => ip.includes(item) || requestPath.includes(item) || requestUA.includes(item))) {
return grant();
}
}

View File

@@ -6,7 +6,7 @@ const timezone = require('@/utils/timezone');
module.exports = async (ctx) => {
const baseUrl = 'https://ostudy.ynnedu.cn/';
const blacklist = ['ynnu-mv.html', 'https://chjiao.ynnu.edu.cn/zsgz/zsjz.htm', 'https://chjiao.ynnu.edu.cn/info/1006/1404.htm', 'https://chjiao.ynnu.edu.cn/zsgz/dksw.htm'];
const denylist = ['ynnu-mv.html', 'https://chjiao.ynnu.edu.cn/zsgz/zsjz.htm', 'https://chjiao.ynnu.edu.cn/info/1006/1404.htm', 'https://chjiao.ynnu.edu.cn/zsgz/dksw.htm'];
const { body } = await got(baseUrl);
const $index = cheerio.load(body);
ctx.state.data = {
@@ -16,7 +16,7 @@ module.exports = async (ctx) => {
// 顶部幻灯片抓取
Promise.all(
$index('div[carousel-item] > div')
.filter((_, element) => !blacklist.includes($index(element).find('a').attr('href')))
.filter((_, element) => !denylist.includes($index(element).find('a').attr('href')))
.map((_, element) => {
const $element = $index(element);
const $a = $element.find('a');
@@ -46,7 +46,7 @@ module.exports = async (ctx) => {
Promise.all(
cheerio
.load($index('#serviceInform-tpl').html())('.news-li:not(:last-child)')
.filter((_, element) => !blacklist.includes($index(element).find('a').attr('href')))
.filter((_, element) => !denylist.includes($index(element).find('a').attr('href')))
.map((_, element) => {
const $element = $index(element);
const $a = $element.find('a');

View File

@@ -1,5 +1,5 @@
const noFound = 'Auto: Route No Found';
const whiteListedUser = ['dependabot[bot]', 'pull[bot]']; // dependabot and downstream PR requested by pull[bot]
const allowedUser = ['dependabot[bot]', 'pull[bot]']; // dependabot and downstream PR requested by pull[bot]
module.exports = async ({ github, context, core }, body, number, sender) => {
core.debug(`sender: ${sender}`);
@@ -82,10 +82,10 @@ module.exports = async ({ github, context, core }, body, number, sender) => {
await updatePrState('open');
}
if (whiteListedUser.includes(sender)) {
core.info('PR created by a whitelisted user, passing');
if (allowedUser.includes(sender)) {
core.info('PR created by a allowed user, passing');
await removeLabel();
await addLabels(['Auto: whitelisted']);
await addLabels(['Auto: allowed']);
return;
} else {
core.debug('PR created by ' + sender);

View File

@@ -10,17 +10,17 @@ function checkBlock(response) {
afterEach(() => {
delete process.env.ACCESS_KEY;
delete process.env.BLACKLIST;
delete process.env.WHITELIST;
delete process.env.DENYLIST;
delete process.env.ALLOWLIST;
jest.resetModules();
server.close();
});
describe('access-control', () => {
it(`blacklist`, async () => {
it(`denylist`, async () => {
const key = '1L0veRSSHub';
const code = md5('/test/2' + key);
process.env.BLACKLIST = 'est/1,233.233.233.,black';
process.env.DENYLIST = 'est/1,233.233.233.,black';
process.env.ACCESS_KEY = key;
server = require('../../lib/index');
const request = supertest(server);
@@ -43,21 +43,21 @@ describe('access-control', () => {
const response23 = await request.get('/test/2').set('user-agent', 'blackua');
checkBlock(response23);
// wrong key/code, not on blacklist
// wrong key/code, not on denylist
const response311 = await request.get(`/test/2?key=wrong+${key}`);
expect(response311.status).toBe(200);
const response312 = await request.get(`/test/2?code=wrong+${code}`);
expect(response312.status).toBe(200);
// wrong key/code, on blacklist
// wrong key/code, on denylist
const response321 = await request.get(`/test/2?key=wrong+${key}`).set('X-Forwarded-For', '233.233.233.233');
checkBlock(response321);
const response322 = await request.get(`/test/2?code=wrong+${code}`).set('X-Forwarded-For', '233.233.233.233');
checkBlock(response322);
// right key/code, on blacklist
// right key/code, on denylist
const response331 = await request.get(`/test/2?key=${key}`).set('X-Forwarded-For', '233.233.233.233');
expect(response331.status).toBe(200);
@@ -65,10 +65,10 @@ describe('access-control', () => {
expect(response332.status).toBe(200);
});
it(`whitelist`, async () => {
it(`allowlist`, async () => {
const key = '1L0veRSSHub';
const code = md5('/test/2' + key);
process.env.WHITELIST = 'est/1,233.233.233.,white';
process.env.ALLOWLIST = 'est/1,233.233.233.,white';
process.env.ACCESS_KEY = key;
server = require('../../lib/index');
const request = supertest(server);
@@ -97,14 +97,14 @@ describe('access-control', () => {
const response23 = await request.get('/test/2').set('user-agent', 'whiteua');
expect(response23.status).toBe(200);
// wrong key/code, not on whitelist
// wrong key/code, not on allowlist
const response311 = await request.get(`/test/2?code=wrong+${code}`);
checkBlock(response311);
const response312 = await request.get(`/test/2?key=wrong+${key}`);
checkBlock(response312);
// wrong key/code, on whitelist
// wrong key/code, on allowlist
const response321 = await request.get(`/test/2?code=wrong+${code}`).set('X-Forwarded-For', '233.233.233.233');
expect(response321.status).toBe(200);

View File

@@ -638,15 +638,15 @@ For readers that do not support HTTP Basic authentication, please refer to [Acce
### Access Control Configuration
RSSHub supports access control via access key/code, whitelisting and blacklisting, enabling any will activate access control for all routes. `ALLOW_LOCALHOST: true` will grant access to all localhost IP addresses.
RSSHub supports access control via access key/code, allowlisting and denylisting, enabling any will activate access control for all routes. `ALLOW_LOCALHOST: true` will grant access to all localhost IP addresses.
#### White/blacklisting
#### Allowlisting/denylisting
- `WHITELIST`: the blacklist. When set, values in `BLACKLIST` are disregarded
- `ALLOWLIST`: the allowlist. When set, values in `DENYLIST` are disregarded
- `BLACKLIST`: the blacklist
- `DENYLIST`: the denylist
White/blacklisting support IP, route and UA as values, fuzzy matching. Use `,` as the delimiter to separate multiple values, eg: `WHITELIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
Allowlisting/denylisting support IP, route and UA as values, fuzzy matching. Use `,` as the delimiter to separate multiple values, eg: `ALLOWLIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
#### Access Key/Code
@@ -662,12 +662,12 @@ Access code is the md5 generated based on the access key + route, eg:
- Or using `key` directly, eg: `https://rsshub.app/qdaily/column/59?key=ILoveRSSHub`
See the relation between access key/code and white/blacklisting.
See the relation between access key/code and allowlist/denylisting.
| | Whitelisted | Blacklisted | Correct access key/code | Wrong access key/code | No access key/code |
| | Allowlist | Denylist | Correct access key/code | Wrong access key/code | No access key/code |
| ----------- | ----------- | ----------- | ----------------------- | --------------------- | ------------------ |
| Whitelisted | ✅ | ✅ | ✅ | ✅ | ✅ |
| Blacklisted | ✅ | ❌ | ✅ | ❌ | ❌ |
| Allowlist | ✅ | ✅ | ✅ | ✅ | ✅ |
| Denylist | ✅ | ❌ | ✅ | ❌ | ❌ |
### Logging Configurations
@@ -781,7 +781,7 @@ See docs of the specified route and `lib/config.js` for detailed information.
- BUPT
- `BUPT_PORTAL_COOKIE`: 登录后获得的 Cookie 值,获取方式
1. 打开 [https://webapp.bupt.edu.cn/wap/login.html?redirect=https://](https://webapp.bupt.edu.cn/wap/login.html?redirect=https://)并登录
1. 打开 [https://webapp.bupt.edu.cn/wap/login.html?redirect=https://](https://webapp.bupt.edu.cn/wap/login.html?redirect=https://) 并登录
2. 无视掉报错,并打开 [https://webapp.bupt.edu.cn/extensions/wap/news/list.html?p-1&type=xnxw](https://webapp.bupt.edu.cn/extensions/wap/news/list.html?p-1&type=xnxw)
3. 打开控制台,刷新
4. 找到 `https://webapp.bupt.edu.cn/extensions/wap/news/list.html?p-1&type=xnxw` 请求
@@ -888,7 +888,7 @@ See docs of the specified route and `lib/config.js` for detailed information.
- pianyuan 全部路由:[注册地址](https://pianyuan.org)
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例: PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- Pixabay: [Documentation](https://pixabay.com/api/docs/)
@@ -1020,7 +1020,7 @@ See docs of the specified route and `lib/config.js` for detailed information.
- 网易云歌单及听歌排行
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值.
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值
- 微博 个人时间线路由:[申请地址](https://open.weibo.com/connect)
@@ -1030,11 +1030,11 @@ See docs of the specified route and `lib/config.js` for detailed information.
- 微博 自定义分组
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式:
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) (确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件)
2. 按下`F12`打开控制台,切换至`Network(网络)`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 (该情形下捕获到的请求路径应包含`/feed/group`)
4. 查看该请求的`Headers(请求头)`, 找到`Cookie`字段并复制内容
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) 确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件
2. 按下`F12`打开控制台,切换至`Network网络`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 该情形下捕获到的请求路径应包含`/feed/group`
4. 查看该请求的`Headers请求头`, 找到`Cookie`字段并复制内容
- 小宇宙:需要 App 登陆后抓包获取相应数据。
@@ -1054,5 +1054,5 @@ See docs of the specified route and `lib/config.js` for detailed information.
- 知乎用户关注时间线
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值.
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值.
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值

View File

@@ -27,7 +27,7 @@ sidebar: auto
默认推荐使用 `diygod/rsshub``diygod/rsshub:latest` 最新版镜像以获取最新路由。
`diygod/rsshub:latest` 存在问题时,可以使用以日期为标签的近期镜像临时使用,例如:
`diygod/rsshub:latest` 存在问题时,可以使用以日期为标签的近期镜像临时使用,例如
```bash
$ docker pull diygod/rsshub:2021-06-18
@@ -144,7 +144,7 @@ $ docker run -d --name rsshub -p 1200:1200 -e CACHE_EXPIRE=3600 -e GITHUB_ACCESS
## Ansible 部署
这个 Ansible playbook 包括了 RSSHub, Redis, browserless (依赖 Docker) 以及 Caddy 2
这个 Ansible playbook 包括了 RSSHub, Redis, browserless 依赖 Docker 以及 Caddy 2
目前只支持 Ubuntu 20.04
@@ -337,7 +337,7 @@ Heroku [不再](https://blog.heroku.com/next-chapter) 提供免费服务。
### 自动更新部署
1. 将 RSSHub [分叉fork](https://github.com/DIYgod/RSSHub/fork) 到自己的账户下
2. 去 Vercel 部署一个新项目:使用 GitHub 账户登录 Vercel进入[项目创建页面](https://vercel.com/new/) 选择导入 RSSHub 仓库进行部署
2. 去 Vercel 部署一个新项目:使用 GitHub 账户登录 Vercel进入 [项目创建页面](https://vercel.com/new/) 选择导入 RSSHub 仓库进行部署
3. 安装 [Pull](https://github.com/apps/pull) 应用,定期将 RSSHub 改动自动同步至你的仓库
## 部署到 Fly.io
@@ -393,7 +393,7 @@ $ fly redis create
来创建一个新的 Redis 数据库,地域选择与你上面创建 RSSHub app 时相同的地域,建议选择开启 [eviction](https://redis.io/docs/reference/eviction/)。创建完成后会输出类似于 `redis://default:<password>@<domain>.upstash.io` 的字符串。
因目前[上游依赖的一个 bug](https://github.com/luin/ioredis/issues/1576),你暂时需要在 Fly.io 给你的连接 URL 后追加 `family=6` 的参数,即使用 `redis://default:<password>@<domain>.upstash.io/?family=6` 作为连接 URL。
因目前 [上游依赖的一个 bug](https://github.com/luin/ioredis/issues/1576),你暂时需要在 Fly.io 给你的连接 URL 后追加 `family=6` 的参数,即使用 `redis://default:<password>@<domain>.upstash.io/?family=6` 作为连接 URL。
再配置 fly.toml 中的 `[env]` 段或运行
@@ -551,11 +551,11 @@ RSSHub 支持 `memory` 和 `redis` 两种缓存方式
部分路由反爬严格,可以配置使用代理抓取。
可通过**代理 URI**或**代理选项**或**反向代理**三种方式来配置代理。
可通过**代理 URI **或**代理选项**或**反向代理**三种方式来配置代理。
#### 代理 URI
`PROXY_URI`: 代理 URI支持 socks4, socks5本地查询域名的 SOCKS5不推荐使用, socks5h传域名的 SOCKS5推荐使用以防止 DNS 污染或 DNS 泄露), http, https具体以 [socks-proxy-agent](https://www.npmjs.com/package/socks-proxy-agent) NPM 包的支持为准,也可参考[curl 中 SOCKS 代理协议的用法](https://daniel.haxx.se/blog/2020/05/26/curl-ootw-socks5/)。
`PROXY_URI`: 代理 URI支持 socks4, socks5本地查询域名的 SOCKS5不推荐使用, socks5h传域名的 SOCKS5推荐使用以防止 DNS 污染或 DNS 泄露), http, https具体以 [socks-proxy-agent](https://www.npmjs.com/package/socks-proxy-agent) NPM 包的支持为准,也可参考 [curl 中 SOCKS 代理协议的用法](https://daniel.haxx.se/blog/2020/05/26/curl-ootw-socks5/)。
> 代理 URI 的格式为:
>
@@ -632,15 +632,15 @@ async function handleRequest(request) {
### 访问控制配置
RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行访问控制。开启任意选项将会激活全局访问控制,没有访问权限将会导致访问被拒绝。同时可以通过 `ALLOW_LOCALHOST: true` 赋予所有本地 IP 访问权限。
RSSHub 支持使用访问密钥 / 码,允许清单和拒绝清单三种方式进行访问控制。开启任意选项将会激活全局访问控制,没有访问权限将会导致访问被拒绝。同时可以通过 `ALLOW_LOCALHOST: true` 赋予所有本地 IP 访问权限。
#### 黑白名
#### 允许清单/拒绝清
- `WHITELIST`: 白名单,设置白名单后黑名单无效
- `ALLOWLIST`: 允许清单,设置允许清单后拒绝清单无效
- `BLACKLIST`: 黑名
- `DENYLIST`: 拒绝清
黑白名单支持 IP、路由和 UA模糊匹配设置多项时用英文逗号 `,` 隔开,例如 `WHITELIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
允许清单/拒绝清单支持 IP、路由和 UA模糊匹配设置多项时用英文逗号 `,` 隔开,例如 `ALLOWLIST=1.1.1.1,2.2.2.2,/qdaily/column/59`
#### 访问密钥 / 码
@@ -656,13 +656,13 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 或使用访问密钥 `key` 直接访问所有路由,例如:`https://rsshub.app/qdaily/column/59?key=ILoveRSSHub`
访问密钥 / 码与黑白名单的访问控制关系如下:
访问密钥 / 码与允许清单/拒绝清单的访问控制关系如下:
| | 正确访问密钥 / 码 | 错误访问密钥 / 码 | 无访问密钥 / 码 |
| ---------- | ----------------- | ----------------- | --------------- |
| 在白名单中 | ✅ | ✅ | ✅ |
| 在黑名单中 | ✅ | ❌ | ❌ |
| 无黑白名单 | ✅ | ❌ | ❌ |
| 在允许清单中 | ✅ | ✅ | ✅ |
| 在拒绝清单中 | ✅ | ❌ | ❌ |
| 无允许清单/拒绝清单 | ✅ | ❌ | ❌ |
### 日志配置
@@ -785,9 +785,9 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- Discourse
- `DISCOURSE_CONFIG_{id}`: 一个 Discourse 驱动的论坛的配置信息, `id` 可自由设定为任意数字或字符串。值应形如`{"link":link,"key":key}`。其中:
- `DISCOURSE_CONFIG_{id}`: 一个 Discourse 驱动的论坛的配置信息, `id` 可自由设定为任意数字或字符串。值应形如`{"link":link,"key":key}`。其中
- `link`:论坛的链接。
- `key`访问论坛API的密钥可参考[此处代码](https://pastebin.com/YbLCgdWW)以获取。需要确保有足够权限访问对应资源。
- `key`访问论坛 API 的密钥,可参考 [此处代码](https://pastebin.com/YbLCgdWW) 以获取。需要确保有足够权限访问对应资源。
- Discuz cookies 设定
@@ -867,11 +867,11 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- `NHENTAI_PASSWORD`: nhentai 密码
- Notion
- `NOTION_TOKEN`: Notion 内部集成 Token请按照[Notion 官方指引](https://developers.notion.com/docs/authorization#internal-integration-auth-flow-set-up)申请 Token
- `NOTION_TOKEN`: Notion 内部集成 Token请按照 [Notion 官方指引](https://developers.notion.com/docs/authorization#internal-integration-auth-flow-set-up) 申请 Token
- pianyuan 全部路由:[注册地址](https://pianyuan.org)
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例: PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- `PIANYUAN_COOKIE`: 对应 cookie 中的 `py_loginauth`, 例PIANYUAN_COOKIE='py_loginauth=xxxxxxxxxx'
- pixiv 全部路由:[注册地址](https://accounts.pixiv.net/signup)
@@ -932,7 +932,7 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 订阅列表路由额外设置
- `YOUTUBE_CLIENT_ID`: YouTube API 的 OAuth 2.0 客户端 ID
- `YOUTUBE_CLIENT_SECRET`: YouTube API 的 OAuth 2.0 客户端 Secret
- `YOUTUBE_REFRESH_TOKEN`: YouTube API 的 OAuth 2.0 客户端 Refresh Token。可以按照[此 gist](https://gist.github.com/Kurukshetran/5904e8cb2361623498481f4a9a1338aa) 获取。
- `YOUTUBE_REFRESH_TOKEN`: YouTube API 的 OAuth 2.0 客户端 Refresh Token。可以按照 [此 gist](https://gist.github.com/Kurukshetran/5904e8cb2361623498481f4a9a1338aa) 获取。
- ZodGame:
@@ -1011,7 +1011,7 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 网易云歌单及听歌排行
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值.
- `NCM_COOKIES`: 网易云音乐登陆后的 cookie 值
- 微博 个人时间线路由:[申请地址](https://open.weibo.com/connect)
@@ -1021,11 +1021,11 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 微博 自定义分组
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式:
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) (确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件)
2. 按下`F12`打开控制台,切换至`Network(网络)`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 (该情形下捕获到的请求路径应包含`/feed/group`)
4. 查看该请求的`Headers(请求头)`, 找到`Cookie`字段并复制内容
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的 cookie, 获取方式
1. 打开并登录 [https://m.weibo.cn](https://m.weibo.cn) 确保打开页面为手机版,如果强制跳转电脑端可尝试使用可更改 UserAgent 的浏览器插件
2. 按下`F12`打开控制台,切换至`Network网络`面板
3. 在该网页切换至任意关注分组,并在面板打开最先捕获到的请求 该情形下捕获到的请求路径应包含`/feed/group`
4. 查看该请求的`Headers请求头`, 找到`Cookie`字段并复制内容
- 小宇宙:需要 App 登陆后抓包获取相应数据。
@@ -1045,5 +1045,5 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- 知乎用户关注时间线
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值.
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值.
- `ZHIHU_COOKIES`: 知乎登录后的 cookie 值
1. 可以在知乎网页版的一些请求的请求头中找到,如 `GET /moments` 请求头中的 `cookie` 值