Skip to content

Commit

Permalink
Merge pull request #11 from zhuba-Ahhh/dev
Browse files Browse the repository at this point in the history
feat: ✨ wordCount
  • Loading branch information
zhuba-Ahhh authored Aug 28, 2024
2 parents a7b6792 + de074f3 commit cf1454e
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 83 deletions.
8 changes: 7 additions & 1 deletion src/app/blog/[id]/AnimatedBlogPost.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface AnimatedBlogPostProps {
post: BlogPost;
headings: Heading[];
readingTime: number;
wordCount: number;
relatedPosts: BlogPost[];
prevPost?: BlogPost;
nextPost?: BlogPost;
Expand All @@ -26,6 +27,7 @@ export default function AnimatedBlogPost({
prevPost,
nextPost,
headings,
wordCount,
readingTime,
relatedPosts,
}: AnimatedBlogPostProps) {
Expand Down Expand Up @@ -53,7 +55,11 @@ export default function AnimatedBlogPost({
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.5, delay: 0.3 }}
>
<BlogHeader post={post} readingTime={readingTime} />
<BlogHeader
post={post}
readingTime={readingTime}
wordCount={wordCount}
/>
<BlogContent
content={post.content}
contentFile={post?.contentFile}
Expand Down
11 changes: 8 additions & 3 deletions src/app/blog/[id]/BlogHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import { BlogPost } from "@/data/blogPosts";
interface BlogHeaderProps {
post: BlogPost;
readingTime: number;
wordCount: number;
}

export default function BlogHeader({ post, readingTime }: BlogHeaderProps) {
export default function BlogHeader({
post,
readingTime,
wordCount,
}: BlogHeaderProps) {
const { title, author, date, coverImage } = post;
return (
<>
Expand All @@ -20,8 +25,8 @@ export default function BlogHeader({ post, readingTime }: BlogHeaderProps) {
<span>{author}</span>
<span>|</span>
<span className="flex items-center">
<ClockIcon className="w-4 h-4 mr-1" />
预计阅读时间: {readingTime} 分钟
<ClockIcon className="w-4 h-4 mr-1" />{wordCount} 字,预计阅读时间:{" "}
{readingTime} 分钟
</span>
</div>
{coverImage && (
Expand Down
3 changes: 2 additions & 1 deletion src/app/blog/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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}
Expand Down
152 changes: 76 additions & 76 deletions src/data/ts/14.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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属性,确保内容未被篡改。
- 示例: \`<script src="https://cdn.example.com/lib.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>\`
3.子资源完整性 (SRI):
- 为CDN资源添加integrity属性,确保内容未被篡改。
- 示例: \`<script src="https://cdn.example.com/lib.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"></script>\`
## 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应用的安全性,保护用户数据和隐私。记住,安全不是一次性的工作,而是需要持续关注和改进的领域。让我们共同努力,为用户创造一个更安全的网络环境!
Expand Down
4 changes: 2 additions & 2 deletions src/utils/blogHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit cf1454e

Please sign in to comment.