Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions lib/db/notion/getPageProperties.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import BLOG from '@/blog.config'
import { getDateValue, getTextContent } from 'notion-utils'
import formatDate from '../../utils/formatDate'
// import { createHash } from 'crypto'
import md5 from 'js-md5'
import { siteConfig } from '../../config'
import { convertUrlStartWithOneSlash, getLastSegmentFromUrl, isHttpLink, isMailOrTelLink } from '../../utils'
import { extractLangPrefix } from '../../utils/pageId'
import {
isMd5Digest,
isSHA256Digest,
sha256Digest
} from '../../utils/password'
import { mapImgUrl } from './mapImage'
import notionAPI from '@/lib/db/notion/getNotionAPI'

Expand Down Expand Up @@ -223,10 +227,16 @@ export function adjustPageProperties(properties, NOTION_CONFIG) {
}
}

// 密码字段md5
properties.password = properties.password
? md5(properties.slug + properties.password)
: ''
// 文章锁:新版为 SHA256(明文);支持 Notion 内直接填 64 位 SHA256;保留 32 位 md5 摘要以兼容旧数据(PR #3389)
if (!properties.password) {
properties.password = ''
} else if (isSHA256Digest(properties.password)) {
properties.password = properties.password.trim()
} else if (isMd5Digest(properties.password)) {
properties.password = properties.password.trim()
} else {
properties.password = sha256Digest(properties.password)
}
}

/**
Expand Down
31 changes: 31 additions & 0 deletions lib/utils/password.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
import { sha256 } from 'js-sha256'
import { isBrowser } from '.'

/** SHA256(hex),用于文章锁新版存储(明文仅存在于 Notion,同步后为摘要) */
export const sha256Digest = str => sha256(String(str))

/** Notion 密码字段直接填入的预计算 SHA256(64 位 hex) */
export const isSHA256Digest = str =>
typeof str === 'string' && /^[a-fA-F0-9]{64}$/.test(str.trim())

/** 旧版 md5(slug+明文) 的 32 位 hex,同步回字段时原样保留 */
export const isMd5Digest = str =>
typeof str === 'string' && /^[a-fA-F0-9]{32}$/.test(str.trim())

/**
* 与 getPasswordQuery 中 localStorage 键一致:pathname only,不含 ?query / #hash
* (修复带查询参数或锚点时读写键不一致导致无法自动解锁,见 PR #3389)
*/
export const getPasswordStoragePath = path => {
if (!path) {
return '/'
}
try {
const base =
isBrowser && typeof window !== 'undefined'
? window.location.origin
: 'http://localhost'
return new URL(path, base).pathname || '/'
} catch {
return String(path).split(/[?#]/)[0] || '/'
}
}

/**
* 获取默认密码
* 用户可以通过url中拼接参数,输入密码
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"feed": "^4.2.2",
"ioredis": "^5.6.1",
"js-md5": "^0.8.3",
"js-sha256": "^0.11.1",
"memory-cache": "^0.2.0",
"next": "^14.2.30",
"notion-client": "7.10.0",
Expand Down
18 changes: 13 additions & 5 deletions pages/[prefix]/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { siteConfig } from '@/lib/config'
import { fetchGlobalAllData, resolvePostProps } from '@/lib/db/SiteDataApi'
import { useGlobal } from '@/lib/global'
import { getPageTableOfContents } from '@/lib/db/notion/getPageTableOfContents'
import { getPasswordQuery } from '@/lib/utils/password'
import {
getPasswordQuery,
getPasswordStoragePath,
sha256Digest
} from '@/lib/utils/password'
import { checkSlugHasNoSlash } from '@/lib/utils/post'
import { DynamicLayout } from '@/themes/theme'
import md5 from 'js-md5'
Expand Down Expand Up @@ -38,11 +42,15 @@ const Slug = props => {
if (!post) {
return false
}
const encrypt = md5(post?.slug + passInput)
if (passInput && encrypt === post?.password) {
const legacy = md5(String(post?.slug ?? '') + passInput)
const nextHash = sha256Digest(passInput)
if (nextHash === post?.password || legacy === post?.password) {
setLock(false)
// 输入密码存入localStorage,下次自动提交
localStorage.setItem('password_' + router.asPath, passInput)
// 输入密码存入 localStorage;键仅含 pathname,避免 query/hash 导致读写不一致(PR #3389)
localStorage.setItem(
'password_' + getPasswordStoragePath(router.asPath),
passInput
)
showNotification(locale.COMMON.ARTICLE_UNLOCK_TIPS) // 设置解锁成功提示显示
return true
}
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5280,6 +5280,11 @@ js-md5@^0.8.3:
resolved "https://registry.npmjs.org/js-md5/-/js-md5-0.8.3.tgz"
integrity sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==

js-sha256@^0.11.1:
version "0.11.1"
resolved "https://registry.npmmirror.com/js-sha256/-/js-sha256-0.11.1.tgz#712262e8fc9569d6f7f6eea72c0d8e5ccc7c976c"
integrity sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg==

"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz"
Expand Down
Loading