工程化与框架系列(33)--前端安全实践指南

前端安全实践指南 🔒

引言

前端安全是Web应用开发中的关键环节。本文将深入探讨前端安全实践,包括XSS防护、CSRF防御、内容安全策略等,帮助开发者构建更安全的前端应用。

安全概述

前端安全主要包括以下方面:

  • XSS防护:跨站脚本攻击防御
  • CSRF防御:跨站请求伪造防护
  • CSP配置:内容安全策略
  • 数据加密:敏感信息保护
  • 访问控制:权限管理

安全工具实现

安全管理器

// 安全管理器类
class SecurityManager {private static instance: SecurityManager;private config: SecurityConfig;private constructor() {this.config = {xssFilter: true,csrfProtection: true,contentSecurityPolicy: true,httpsOnly: true,maxTokenAge: 3600};this.initialize();}// 获取单例实例static getInstance(): SecurityManager {if (!SecurityManager.instance) {SecurityManager.instance = new SecurityManager();}return SecurityManager.instance;}// 初始化安全管理器private initialize(): void {// 配置CSPif (this.config.contentSecurityPolicy) {this.setupCSP();}// 配置HTTPSif (this.config.httpsOnly) {this.enforceHTTPS();}// 初始化CSRF保护if (this.config.csrfProtection) {this.initializeCsrfProtection();}}// 设置CSPprivate setupCSP(): void {const csp = ["default-src 'self'","script-src 'self' 'unsafe-inline' 'unsafe-eval'","style-src 'self' 'unsafe-inline'","img-src 'self' data: https:","font-src 'self'","connect-src 'self'","media-src 'self'","object-src 'none'","frame-src 'self'","worker-src 'self' blob:"].join('; ');const meta = document.createElement('meta');meta.httpEquiv = 'Content-Security-Policy';meta.content = csp;document.head.appendChild(meta);}// 强制HTTPSprivate enforceHTTPS(): void {if (window.location.protocol === 'http:' && window.location.hostname !== 'localhost') {window.location.href = window.location.href.replace('http:', 'https:');}}// 初始化CSRF保护private initializeCsrfProtection(): void {this.setupCsrfToken();this.interceptXHR();this.interceptFetch();}// 设置CSRF Tokenprivate setupCsrfToken(): void {const token = this.generateToken();document.cookie = `XSRF-TOKEN=${token}; path=/; secure; samesite=strict`;const meta = document.createElement('meta');meta.name = 'csrf-token';meta.content = token;document.head.appendChild(meta);}// 拦截XHR请求private interceptXHR(): void {const originalOpen = XMLHttpRequest.prototype.open;const originalSend = XMLHttpRequest.prototype.send;const manager = this;XMLHttpRequest.prototype.open = function(method: string,url: string,...args: any[]) {this._method = method;this._url = url;originalOpen.apply(this, [method, url, ...args]);};XMLHttpRequest.prototype.send = function(data?: any) {if (this._method?.toUpperCase() !== 'GET') {const token = manager.getCsrfToken();this.setRequestHeader('X-XSRF-TOKEN', token);}originalSend.call(this, data);};}// 拦截Fetch请求private interceptFetch(): void {const originalFetch = window.fetch;const manager = this;window.fetch = function(input: RequestInfo,init?: RequestInit): Promise<Response> {if (init?.method && init.method.toUpperCase() !== 'GET') {const token = manager.getCsrfToken();init.headers = {...init.headers,'X-XSRF-TOKEN': token};}return originalFetch.call(window, input, init);};}// 生成Tokenprivate generateToken(): string {const array = new Uint8Array(32);crypto.getRandomValues(array);return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');}// 获取CSRF Tokenprivate getCsrfToken(): string {const meta = document.querySelector('meta[name="csrf-token"]');return meta?.getAttribute('content') || '';}// XSS过滤sanitizeHTML(html: string): string {const div = document.createElement('div');div.textContent = html;return div.innerHTML;}// 验证输入validateInput(input: string,pattern: RegExp | string): boolean {const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;return regex.test(input);}// 加密数据async encryptData(data: string,password: string): Promise<string> {const encoder = new TextEncoder();const salt = crypto.getRandomValues(new Uint8Array(16));const keyMaterial = await crypto.subtle.importKey('raw',encoder.encode(password),'PBKDF2',false,['deriveBits', 'deriveKey']);const key = await crypto.subtle.deriveKey({name: 'PBKDF2',salt,iterations: 100000,hash: 'SHA-256'},keyMaterial,{name: 'AES-GCM',length: 256},false,['encrypt']);const iv = crypto.getRandomValues(new Uint8Array(12));const encryptedContent = await crypto.subtle.encrypt({name: 'AES-GCM',iv},key,encoder.encode(data));const encryptedArray = new Uint8Array(encryptedContent);const resultArray = new Uint8Array(salt.length + iv.length + encryptedArray.length);resultArray.set(salt, 0);resultArray.set(iv, salt.length);resultArray.set(encryptedArray, salt.length + iv.length);return btoa(String.fromCharCode(...resultArray));}// 解密数据async decryptData(encryptedData: string,password: string): Promise<string> {const decoder = new TextDecoder();const encoder = new TextEncoder();const data = Uint8Array.from(atob(encryptedData),c => c.charCodeAt(0));const salt = data.slice(0, 16);const iv = data.slice(16, 28);const content = data.slice(28);const keyMaterial = await crypto.subtle.importKey('raw',encoder.encode(password),'PBKDF2',false,['deriveBits', 'deriveKey']);const key = await crypto.subtle.deriveKey({name: 'PBKDF2',salt,iterations: 100000,hash: 'SHA-256'},keyMaterial,{name: 'AES-GCM',length: 256},false,['decrypt']);const decryptedContent = await crypto.subtle.decrypt({name: 'AES-GCM',iv},key,content);return decoder.decode(decryptedContent);}// 生成安全的随机值generateSecureRandom(length: number): string {const array = new Uint8Array(length);crypto.getRandomValues(array);return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');}// 哈希密码async hashPassword(password: string,salt?: string): Promise<{ hash: string; salt: string }> {const encoder = new TextEncoder();salt = salt || this.generateSecureRandom(16);const keyMaterial = await crypto.subtle.importKey('raw',encoder.encode(password),'PBKDF2',false,['deriveBits']);const bits = await crypto.subtle.deriveBits({name: 'PBKDF2',salt: encoder.encode(salt),iterations: 100000,hash: 'SHA-256'},keyMaterial,256);const hash = Array.from(new Uint8Array(bits), byte =>byte.toString(16).padStart(2, '0')).join('');return { hash, salt };}// 验证密码async verifyPassword(password: string,hash: string,salt: string): Promise<boolean> {const result = await this.hashPassword(password, salt);return result.hash === hash;}
}// 接口定义
interface SecurityConfig {xssFilter: boolean;csrfProtection: boolean;contentSecurityPolicy: boolean;httpsOnly: boolean;maxTokenAge: number;
}// 使用示例
const security = SecurityManager.getInstance();// XSS防护
const userInput = '<script>alert("xss")</script>';
const safeHtml = security.sanitizeHTML(userInput);// 输入验证
const email = 'user@example.com';
const isValidEmail = security.validateInput(email,/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
);// 数据加密
const sensitiveData = 'secret information';
security.encryptData(sensitiveData, 'password123').then(encrypted => {console.log('Encrypted:', encrypted);return security.decryptData(encrypted, 'password123');}).then(decrypted => {console.log('Decrypted:', decrypted);});// 密码哈希
security.hashPassword('myPassword123').then(({ hash, salt }) => {console.log('Hash:', hash);console.log('Salt:', salt);return security.verifyPassword('myPassword123', hash, salt);}).then(isValid => {console.log('Password valid:', isValid);});

安全HTTP客户端

// 安全HTTP客户端类
class SecureHttpClient {private baseUrl: string;private security: SecurityManager;constructor(config: SecureHttpConfig) {this.baseUrl = config.baseUrl || '';this.security = SecurityManager.getInstance();}// 发送GET请求async get<T>(url: string,config?: RequestConfig): Promise<T> {return this.request<T>({method: 'GET',url,...config});}// 发送POST请求async post<T>(url: string,data?: any,config?: RequestConfig): Promise<T> {return this.request<T>({method: 'POST',url,data,...config});}// 发送PUT请求async put<T>(url: string,data?: any,config?: RequestConfig): Promise<T> {return this.request<T>({method: 'PUT',url,data,...config});}// 发送DELETE请求async delete<T>(url: string,config?: RequestConfig): Promise<T> {return this.request<T>({method: 'DELETE',url,...config});}// 发送请求private async request<T>(config: RequestConfig): Promise<T> {const url = this.baseUrl + config.url;// 添加CSRF Tokenconst headers = {'Content-Type': 'application/json',...config.headers};if (config.method !== 'GET') {const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');if (token) {headers['X-XSRF-TOKEN'] = token;}}// 加密敏感数据let data = config.data;if (config.encrypt && data) {data = await this.security.encryptData(JSON.stringify(data),config.encryptKey || '');}try {const response = await fetch(url, {method: config.method,headers,body: data ? JSON.stringify(data) : undefined,credentials: 'same-origin'});if (!response.ok) {throw new Error(response.statusText);}// 解密响应数据let result = await response.json();if (config.encrypt && result.encrypted) {result = JSON.parse(await this.security.decryptData(result.data,config.encryptKey || ''));}return result;} catch (error) {console.error('Request failed:', error);throw error;}}
}// 接口定义
interface SecureHttpConfig {baseUrl?: string;
}interface RequestConfig {method: string;url: string;data?: any;headers?: Record<string, string>;encrypt?: boolean;encryptKey?: string;
}// 使用示例
const http = new SecureHttpClient({baseUrl: 'https://api.example.com'
});// 发送普通请求
http.get('/users').then(users => {console.log('Users:', users);});// 发送加密请求
http.post('/sensitive-data',{ secret: 'value' },{encrypt: true,encryptKey: 'secret-key-123'}
).then(response => {console.log('Response:', response);
});

最佳实践与建议

  1. 输入验证

    • 客户端验证
    • 服务端验证
    • 特殊字符过滤
    • 长度限制
  2. 数据加密

    • 使用HTTPS
    • 敏感数据加密
    • 安全密钥管理
    • 哈希算法选择
  3. 访问控制

    • 身份认证
    • 权限验证
    • 会话管理
    • 令牌验证
  4. 安全配置

    • CSP策略
    • Cookie设置
    • 错误处理
    • 日志记录

总结

前端安全需要考虑以下方面:

  1. XSS和CSRF防护
  2. 数据加密和传输
  3. 访问控制和认证
  4. 安全配置和监控
  5. 漏洞修复和更新

通过全面的安全实践,可以有效降低安全风险。

学习资源

  1. OWASP安全指南
  2. Web安全最佳实践
  3. 加密算法教程
  4. 安全测试工具
  5. 漏洞数据库

如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/33669.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【测试语言基础篇】Python基础之List列表

一、Python 列表(List) 序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置&#xff0c;或索引&#xff0c;第一个索引是0&#xff0c;第二个索引是1&#xff0c;依此类推。 Python有6个序列的内置类型&#xff0c;但最常见的是列表和元组。序列都可…

编译系统设计原理概述

目录 简介 词法分析 正则表达式 有穷状态自动机 从正则表达式到有穷自动机的转换 单词识别 简介 主要介绍编译系统设计过程中涉及的原理与技术&#xff0c;主要分为前端设计和后端设计两 个模块。前端部分包括词法分析器、语法分析器的构建和语义分析过程的设计…

ArcGIS Pro 车牌分区数据处理与地图制作全攻略

在大数据时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;技术在各个领域都有着广泛的应用&#xff0c;而 ArcGIS Pro 作为一款功能强大的 GIS 软件&#xff0c;为数据处理和地图制作提供了丰富的工具和便捷的操作流程。 车牌数据作为一种重要的地理空间数据&#xf…

前端登录鉴权全解析:主流方案对比与实现指南

文章目录 一、常见登录鉴权方式概览1.1 主流方案对比1.2 技术特性对比 二、Session/Cookie方案2.1 实现原理2.2 代码实现2.3 优缺点分析 三、JWT方案3.1 实现原理3.2 代码实现3.3 优缺点分析 四、OAuth方案4.1 实现原理4.2 代码实现4.3 优缺点分析 五、SSO方案5.1 实现原理5.2 …

算法系列之回溯算法求解数独及所有可能解

有没有对数独感兴趣的朋友呢&#xff1f;数独作为一款经典的逻辑游戏&#xff0c;其目标是在一个9x9的方格中填入数字1至9&#xff0c;确保每一行、每一列以及每一个3x3的子网格中都包含这些数字且不重复。尽管数独的规则看似简单&#xff0c;但编写一个能够自动求解数独的程序…

华为hcia——Datacom实验指南——TCP传输原理和数据段格式

什么是TCP TCP是一种可靠的端到端的传输层协议&#xff0c;仅应用于单波通信。 采用TCP协议作为传输方式的应用层服务&#xff0c;再进行数据传输前&#xff0c;都需要进行TCP协议的创建。 TCP报文的格式 sequence number&#xff08;序列号&#xff09; 占4个字节&#x…

Vlog 片头制作

打开剪映&#xff0c;新建草稿&#xff0c;导入黑色背景。 拉长时间轴&#xff0c;背景时常调整为4.2秒。 添加文本&#xff0c;输入 5 个“|”&#xff0c;每个中间 2 个空格&#xff0c;如下| | | | |&#xff0c;然后手动放大文本&#xff0c;让中间显示出四个间隔。 继续添…

【Nacos】服务发布之优雅预热上线方案

目录 一、背景二、注册时机2.1、注册机制2.2、分析源码找到注册时机 三、注册前心跳健康检测3.1、方案实施3.2、源码分析3.3、优化代码 四、流量权重配置五、总结5.1、整体完整流程&#xff1a;5.2、流程图&#xff1a;5.1、优化方案完整代码&#xff1a; 一、背景 有些面向广…

VXLAN 组播 RP

一、Anycast RP 在每个 VTEP 上&#xff0c;每个多播组都会建立一个源树 (S,G)&#xff0c;并且在双活 Leaf 设备上到 RP 地址是 ECMP 路径。 在 PIM ASM 模式下&#xff0c;(S,G) 组在 VTEP 端创建。由于每个 VTEP 都能够为特定的多播组发送和接收多播流量&#xff0c;因此每…

【第七节】windows sdk编程:Windows 中的对话框

目录 引言 一、对话框简介 1.1 对话框的创建 1.2 基本函数 1.3 模态对话框与非模态对话框 1.4 对话框与窗口的区别 二、模态对话框编程方法 2.1 模态对话框编程 2.2 消息框 三、非模态对话框编程方法 四、综合代码案例 引言 在Windows应用程序开发中&#xff0c;对话…

安装并配置终端字体

1. 简介 在使用 Oh My Zsh Powerlevel10k 时&#xff0c;正确的字体配置至关重要。Powerlevel10k 依赖 Nerd Fonts 扩展字体&#xff0c;以正确显示 Git 状态、分支、时间、图标等信息。 如果没有正确配置字体&#xff0c;你可能会看到 乱码、问号&#xff08;?&#xff09…

LeetCode - #227 基于 Swift 实现基本计算器

摘要 在这篇文章中&#xff0c;我们将实现一个基于 Swift 语言的基本计算器。该计算器能够解析和计算包含 、-、* 和 / 的数学表达式&#xff0c;并且遵循运算符的优先级规则。整数除法仅保留整数部分&#xff0c;不能使用 eval() 这样的内置解析方法。 描述 给你一个字符串表…

智慧应急消防解决方案(35页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。在当今社会&#xff0c;消防安全至关重要&#xff0c;关乎人民生命财产安全和社会稳定。随着科技的飞速发展&#xff0c;智慧应急消防解决方案应运而生&#xff0c;为消防工作带来了新的变革和机遇。接下来&#xff0c;让我们深入探讨这份智…

网络安全反渗透 网络安全攻防渗透

网络渗透防范主要从两个方面来进行防范&#xff0c;一方面是从思想意识上进行防范&#xff0c;另一方面就是从技术方面来进行防范。 1.从思想意识上防范渗透 网络攻击与网络安全防御是正反两个方面&#xff0c;纵观容易出现网络安全事故或者事件的公司和个人&#xff0c;在这些…

2025-03-15 学习记录--C/C++-PTA 练习3-4 统计字符

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 练习3-4 统计字符 本题要求编写程序&#xff0c;输入10个字符&#xff0c;统计其中英文字母、空格或回车、…

11a-PPDU

## 前导码和信令 OFDM 物理层&#xff08;PHY&#xff09;的 PPDU&#xff08;物理层协议数据单元&#xff09;格式包含以下实体信息&#xff1a; - **PPDU 组成**&#xff1a;由 OFDM PHY preamble&#xff08;前导码&#xff0c;12 个符号&#xff09;、PHY header&#xff…

TF-IDF:文本挖掘中的关键词提取利器

引言 在自然语言处理&#xff08;NLP&#xff09;和文本挖掘中&#xff0c;TF-IDF是一种常用的技术&#xff0c;用于评估一个词在文档中的重要性。它不仅在信息检索领域广泛应用&#xff0c;还在文本分类、关键词提取等任务中发挥着重要作用。本文将详细介绍TF-IDF的原理…

[新能源]新能源汽车快充与慢充说明

接口示意图 慢充接口为交流充电口&#xff08;七孔&#xff09;&#xff0c;快充接口为直流充电口&#xff08;九孔&#xff09;。 引脚说明 上图给的是充电口的引脚图&#xff0c;充电枪的为镜像的。 慢充接口引脚说明 快充接口引脚说明 充电流程 慢充示意图 慢充&…

docker3-容器与镜像命令

前言 容器命令[部分] docker run –name“nginx-lb” 这个就是为容器起一个名称 以前是随机起的名称 docker run -d --name mynginx1 nginx:1.24.0 docker ps 这样就可以看到我们起的名字了 docker stop mynginx1 这个就可以停掉指定名字的容器了&#xff0c;但不是删除…

vue/react/vite前端项目打包的时候加上时间最简单版本,防止后端扯皮

如果你是vite项目&#xff0c;直接写一个vite的插件&#xff0c;通过这个插件可以动态注入环境变量&#xff0c;然后当打包的时候&#xff0c;自动注入这个时间到环境变量中&#xff0c;然后在项目中App.vue中或者Main.tsx中打印出来&#xff0c;这就知道是什么时候编译的项目了…