From de074f39fce8b4c15b94e37421f9eb9a525d46f7 Mon Sep 17 00:00:00 2001 From: zhuba-Ahhh <3477826311@qq.com> Date: Wed, 28 Aug 2024 13:56:12 +0800 Subject: [PATCH] feat: :sparkles: wordCount --- src/app/blog/[id]/AnimatedBlogPost.tsx | 8 +- src/app/blog/[id]/BlogHeader.tsx | 11 +- src/app/blog/[id]/page.tsx | 3 +- src/data/ts/14.ts | 152 ++++++++++++------------- src/utils/blogHelpers.ts | 4 +- 5 files changed, 95 insertions(+), 83 deletions(-) diff --git a/src/app/blog/[id]/AnimatedBlogPost.tsx b/src/app/blog/[id]/AnimatedBlogPost.tsx index d611502..1dc20d7 100644 --- a/src/app/blog/[id]/AnimatedBlogPost.tsx +++ b/src/app/blog/[id]/AnimatedBlogPost.tsx @@ -16,6 +16,7 @@ interface AnimatedBlogPostProps { post: BlogPost; headings: Heading[]; readingTime: number; + wordCount: number; relatedPosts: BlogPost[]; prevPost?: BlogPost; nextPost?: BlogPost; @@ -26,6 +27,7 @@ export default function AnimatedBlogPost({ prevPost, nextPost, headings, + wordCount, readingTime, relatedPosts, }: AnimatedBlogPostProps) { @@ -53,7 +55,11 @@ export default function AnimatedBlogPost({ animate={{ y: 0, opacity: 1 }} transition={{ duration: 0.5, delay: 0.3 }} > - + @@ -20,8 +25,8 @@ export default function BlogHeader({ post, readingTime }: BlogHeaderProps) { {author} | - - 预计阅读时间: {readingTime} 分钟 + 共 {wordCount} 字,预计阅读时间:{" "} + {readingTime} 分钟 {coverImage && ( diff --git a/src/app/blog/[id]/page.tsx b/src/app/blog/[id]/page.tsx index 5858edf..6254e64 100644 --- a/src/app/blog/[id]/page.tsx +++ b/src/app/blog/[id]/page.tsx @@ -29,7 +29,7 @@ export default async function BlogPost({ params }: BlogPostParams) { } const headings: Heading[] = extractHeadings(post.content); - const readingTime: number = estimateReadingTime(post.content); + const [readingTime, wordCount] = estimateReadingTime(post.content); const relatedPosts: BlogPost[] = blogPosts .filter( @@ -48,6 +48,7 @@ export default async function BlogPost({ params }: BlogPostParams) { post={post} headings={headings} readingTime={readingTime} + wordCount={wordCount} relatedPosts={relatedPosts} prevPost={prevPost} nextPost={nextPost} diff --git a/src/data/ts/14.ts b/src/data/ts/14.ts index 189adad..fe74f87 100644 --- a/src/data/ts/14.ts +++ b/src/data/ts/14.ts @@ -7,124 +7,124 @@ export const content14 = ` 跨站脚本攻击是最常见且危险的Web安全威胁之一。以下是防御XSS的关键策略: -1. 内容安全策略 (CSP): - - 实施严格的CSP: 限制可执行脚本、样式和其他资源的来源。 - - 示例: \`Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com\` - -2. 输入验证与输出编码: - - 对所有用户输入进行严格验证和过滤。 - - 在输出到HTML、JavaScript、CSS或URL时,使用适当的编码函数。 - - 使用成熟的库如DOMPurify进行HTML净化。 - -3. HttpOnly和Secure标志: - - 为敏感Cookie设置HttpOnly标志,防止JavaScript访问。 - - 使用Secure标志确保Cookie仅通过HTTPS传输。 - -4. X-XSS-Protection头: - - 启用浏览器内置的XSS过滤器: \`X-XSS-Protection: 1; mode=block\` +1.内容安全策略 (CSP): + - 实施严格的CSP: 限制可执行脚本、样式和其他资源的来源。 + - 示例: \`Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com\` + +2.输入验证与输出编码: + - 对所有用户输入进行严格验证和过滤。 + - 在输出到HTML、JavaScript、CSS或URL时,使用适当的编码函数。 + - 使用成熟的库如DOMPurify进行HTML净化。 + +3.HttpOnly和Secure标志: + - 为敏感Cookie设置HttpOnly标志,防止JavaScript访问。 + - 使用Secure标志确保Cookie仅通过HTTPS传输。 + +4.X-XSS-Protection头: + - 启用浏览器内置的XSS过滤器: \`X-XSS-Protection: 1; mode=block\` ## CSRF (跨站请求伪造) 保护 CSRF攻击利用用户的已认证会话执行未授权操作。防御措施包括: -1. CSRF令牌: - - 实现同步令牌模式: 在表单中包含随机生成的令牌。 - - 双重提交Cookie: 将令牌同时存储在Cookie和请求参数中。 +1.CSRF令牌: + - 实现同步令牌模式: 在表单中包含随机生成的令牌。 + - 双重提交Cookie: 将令牌同时存储在Cookie和请求参数中。 -2. SameSite Cookie属性: - - 设置\`SameSite=Strict\`或\`SameSite=Lax\`限制跨站Cookie传输。 +2.SameSite Cookie属性: + - 设置\`SameSite=Strict\`或\`SameSite=Lax\`限制跨站Cookie传输。 -3. 自定义请求头: - - 为AJAX请求添加自定义头,如\`X-Requested-With: XMLHttpRequest\`。 +3.自定义请求头: + - 为AJAX请求添加自定义头,如\`X-Requested-With: XMLHttpRequest\`。 -4. 验证Referer和Origin: - - 检查请求的Referer或Origin头,确保请求来自合法来源。 +4.验证Referer和Origin: + - 检查请求的Referer或Origin头,确保请求来自合法来源。 ## 安全的第三方库管理 第三方库可能引入安全漏洞,需要谨慎管理: -1. 依赖审计: - - 使用npm audit、yarn audit或Snyk定期检查依赖。 - - 集成到CI/CD流程中,自动化漏洞检测。 +1.依赖审计: + - 使用npm audit、yarn audit或Snyk定期检查依赖。 + - 集成到CI/CD流程中,自动化漏洞检测。 -2. 版本锁定: - - 使用package-lock.json或yarn.lock锁定依赖版本。 - - 定期更新并测试最新的安全补丁。 +2.版本锁定: + - 使用package-lock.json或yarn.lock锁定依赖版本。 + - 定期更新并测试最新的安全补丁。 -3. 子资源完整性 (SRI): - - 为CDN资源添加integrity属性,确保内容未被篡改。 - - 示例: \`\` +3.子资源完整性 (SRI): + - 为CDN资源添加integrity属性,确保内容未被篡改。 + - 示例: \`\` ## HTTPS 实施 HTTPS对于保护数据传输至关重要: -1. 全站HTTPS: - - 将所有HTTP流量重定向到HTTPS。 - - 使用HSTS (HTTP严格传输安全) 头强制HTTPS连接。 +1.全站HTTPS: + - 将所有HTTP流量重定向到HTTPS。 + - 使用HSTS (HTTP严格传输安全) 头强制HTTPS连接。 -2. 正确配置TLS: - - 使用强加密套件,禁用不安全的协议版本。 - - 定期更新和轮换SSL/TLS证书。 +2.正确配置TLS: + - 使用强加密套件,禁用不安全的协议版本。 + - 定期更新和轮换SSL/TLS证书。 -3. 证书透明度 (CT) 日志: - - 监控CT日志,及时发现针对您域名的可疑证书颁发。 +3.证书透明度 (CT) 日志: + - 监控CT日志,及时发现针对您域名的可疑证书颁发。 ## 安全的客户端存储 正确使用客户端存储机制对保护用户数据至关重要: -1. 敏感数据加密: - - 使用Web Crypto API进行客户端加密。 - - 避免在localStorage中存储敏感信息。 +1.敏感数据加密: + - 使用Web Crypto API进行客户端加密。 + - 避免在localStorage中存储敏感信息。 -2. IndexedDB安全: - - 实施适当的访问控制和数据隔离。 - - 考虑对存储的数据进行加密。 +2.IndexedDB安全: + - 实施适当的访问控制和数据隔离。 + - 考虑对存储的数据进行加密。 -3. 安全的会话管理: - - 使用服务器端会话存储敏感数据。 - - 实现会话超时和安全的注销机制。 +3.安全的会话管理: + - 使用服务器端会话存储敏感数据。 + - 实现会话超时和安全的注销机制。 ## 高级安全实践 -1. 子域隔离: - - 将不同功能部署到不同子域,限制潜在攻击面。 +1.子域隔离: + - 将不同功能部署到不同子域,限制潜在攻击面。 -2. 浏览器指纹防护: - - 最小化暴露给第三方脚本的信息。 - - 考虑使用隐私保护技术如Tor浏览器。 +2.浏览器指纹防护: + - 最小化暴露给第三方脚本的信息。 + - 考虑使用隐私保护技术如Tor浏览器。 -3. WebSocket安全: - - 实施适当的身份验证和授权机制。 - - 使用wss://协议确保加密传输。 +3.WebSocket安全: + - 实施适当的身份验证和授权机制。 + - 使用wss://协议确保加密传输。 -4. 防御点击劫持: - - 使用X-Frame-Options或CSP frame-ancestors指令。 +4.防御点击劫持: + - 使用X-Frame-Options或CSP frame-ancestors指令。 -5. API安全: - - 实施速率限制和请求节流。 - - 使用OAuth 2.0和OpenID Connect进行安全授权。 +5.API安全: + - 实施速率限制和请求节流。 + - 使用OAuth 2.0和OpenID Connect进行安全授权。 ## 持续安全实践 -1. 安全编码规范: - - 制定并执行安全编码指南。 - - 进行定期的代码审查和安全培训。 +1.安全编码规范: + - 制定并执行安全编码指南。 + - 进行定期的代码审查和安全培训。 -2. 漏洞赏金计划: - - 考虑建立漏洞赏金项目,鼓励外部研究人员报告安全问题。 +2.漏洞赏金计划: + - 考虑建立漏洞赏金项目,鼓励外部研究人员报告安全问题。 -3. 安全监控和响应: - - 实施日志记录和监控系统。 - - 制定并演练安全事件响应计划。 +3.安全监控和响应: + - 实施日志记录和监控系统。 + - 制定并演练安全事件响应计划。 -4. 定期安全评估: - - 进行渗透测试和安全审计。 - - 使用自动化工具进行持续的安全扫描。 +4.定期安全评估: + - 进行渗透测试和安全审计。 + - 使用自动化工具进行持续的安全扫描。 结论: 前端安全是一个动态且持续的过程,需要开发者保持警惕并不断学习。通过实施这些最佳实践,您可以显著提高Web应用的安全性,保护用户数据和隐私。记住,安全不是一次性的工作,而是需要持续关注和改进的领域。让我们共同努力,为用户创造一个更安全的网络环境! diff --git a/src/utils/blogHelpers.ts b/src/utils/blogHelpers.ts index ce1c1e9..5158abc 100644 --- a/src/utils/blogHelpers.ts +++ b/src/utils/blogHelpers.ts @@ -28,10 +28,10 @@ export function extractHeadings(content: string) { return headings; } -export function estimateReadingTime(content: string): number { +export function estimateReadingTime(content: string): number[] { const wordsPerMinute = 200; const wordCount = content.split(/\s+/).length; - return Math.ceil(wordCount / wordsPerMinute); + return [Math.ceil(wordCount / wordsPerMinute), wordCount]; } export function useExtractHeadings(content: string) {