XieJava's blog

记录最好的自己


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于

什么是RACI矩阵,应用在什么场景?

发表于 2025-04-08 | 更新于: 2025-04-08 | 分类于 管理 , 项目管理 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 5

一、什么是RACI

RACI矩阵是一种用于明确项目或任务中角色与责任的管理工具,通过定义不同人员在任务中的参与程度来避免职责不清的问题。以下是其核心要点:

  1. ‌RACI的含义‌
  • ‌R(Responsible)执行者‌:直接完成任务的具体负责人。
  • ‌A(Accountable)批准者‌:对任务结果负最终责任,通常为决策者。
  • ‌C(Consulted)被咨询者‌:提供专业意见的专家或利益相关方。
  • ‌I(Informed)被通知者‌:需知悉进展但不直接参与的人员。
  1. ‌典型应用场景‌
  • ‌跨部门协作项目‌:例如新产品发布,需明确市场、研发、生产等部门的职责。
  • ‌复杂流程优化‌:如企业ERP系统实施,区分流程设计、数据迁移等任务的责任人。
  • ‌危机管理‌:如安全事故处理时明确指挥、执行、沟通等角色。
  • ‌日常运营‌:适用于周期性工作(如财务审计)的职责划分。
  1. ‌使用案例‌
  • ‌软件开发项目‌:
任务 项目经理(A) 开发团队(R) 测试组(R) 客户(C) 法务(I)
需求确认 A R - C I
代码审查 R C - -
  1. 构建要点‌
  • 每个任务确保‌仅1个A角色‌,避免多头领导
  • 避免R角色过多导致执行分散(如单个任务超过3个R)
  • 关键干系人必须纳入C或I,防止遗漏重要意见
  1. 常见误区‌
  • 混淆A和R角色(如误将部门领导设为所有任务的A)
  • 过度咨询(C角色过多导致决策延迟)
  • 忽略变更管理(未随项目进展更新矩阵)

二、如何适用RACI矩阵

结合不同场景的关键步骤与操作要点:

  1. 前期准备‌

    • 分解任务清单‌
      基于项目目标,将工作拆解为具体任务(如软件开发中的需求收集、测试、部署等)‌。
      示例:在IT系统迁移项目中,任务可拆分为“制定迁移方案”“数据备份验证”等‌。
    • 识别参与角色‌
      列出所有相关角色或部门(如项目经理、开发团队、法务部等),避免仅使用个人姓名,需标注岗位或职能‌。
  2. 构建矩阵‌

    • 分配RACI角色‌
      ○ 每个任务需指定 ‌1个A角色‌(唯一责任人)和若干R/C/I角色‌。
      示例:在需求确认阶段,产品经理为A,开发团队为R,法务部为I‌。
      ○ 避免单任务分配过多R角色(建议≤3个),防止执行分散‌。
    • 关键逻辑验证‌
      ○ ‌横向检查‌:每项任务需至少包含R和A角色,确保无遗漏‌。
      ○ ‌纵向检查‌:单个角色名下任务量需合理,避免过度集中(如某成员承担过多R角色)‌。
  3. 应用中的关键技巧‌

    • 与项目工具结合‌
      ○ 将RACI矩阵与甘特图、WBS(工作分解结构)联动,识别关键路径任务并优先分配资源‌。
      示例:在部署阶段,明确运维团队为R角色并与甘特图中的时间节点对齐‌。
    • 动态更新机制‌
      ○ 项目变更时同步调整矩阵(如新增任务或角色变更)‌。
      ○ 定期向I角色推送进展(如周报同步),向C角色发起咨询(如需求评审会)‌。
  4. 常见问题与规避策略‌

问题类型 解决方案
‌角色冲突‌(多个A) 重新界定任务边界,仅保留1个A角色‌。
‌沟通低效‌(C/I过多) 精简咨询范围(如仅核心专家参与C角色),减少非必要通知‌。
‌ 责任模糊‌(无明确R) 通过工作分解细化任务颗粒度,确保每个子任务均有R角色‌。
  1. 扩展应用场景‌
  • ‌RASCI矩阵‌:在RACI基础上增加S(Support)角色,标注辅助支持团队(如IT部门协助数据迁移)‌15。
  • ‌多层级矩阵‌:针对复杂项目分层设计(如战略级、执行级),分别分配责任‌7。

总结:核心操作流程
1.‌分解任务 → 2. 定义角色 → 3. 填充矩阵 → 4. 验证逻辑 → 5. 动态维护‌
示例:某市政工程通过RACI矩阵将环评报告责任唯一分配给环保机构(A角色),施工执行由承包商(R角色)承担,社区代表仅需知悉(I角色)‌。
通过结构化分配与持续优化,RACI矩阵可显著提升跨团队协作效率,减少责任争议‌。

三、应用案例

  1. IT系统升级项目‌
    ‌背景‌:某企业需将本地服务器迁移至云端,涉及IT部、安全部、财务部及外部供应商。
    ‌任务分解与角色分配‌:
任务 IT经理 (A) 运维团队 (R) 安全部 (C) 财务部 (I) 供应商 (R)
制定迁移方案 A R C I C
数据备份与验证 I R C - R
云环境安全测试 - C A I R

‌关键点‌:

  • 安全部需深度参与方案设计和测试(C/A角色),避免安全漏洞;
  • 供应商负责具体执行(R),但需接受IT经理的最终审批(A)。
  1. 日常运维(IT支持团队)‌
    ‌背景‌:某公司IT部门处理日常故障,需明确一线支持、二线专家及管理层职责。
任务 IT主管 (A) 一线支持 (R) 二线专家 (C) 用户部门 (I)
故障初步诊断 - R - I
复杂问题升级处理 I - R C
故障解决率报告 A C - I

‌注意事项‌:

  • 一线支持直接处理简单问题(R),二线专家解决技术难点(R);
  • 用户部门仅需知悉进展(I),避免干扰技术处理。

从以上看出,RACI矩阵适用于‌任何需要明确角色分工的场景‌,尤其适合跨职能、多利益相关方的复杂任务。


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

什么是互联网暴露面?什么是攻击面?暴露面与攻击面有什么区别?

发表于 2025-02-24 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 911 | 阅读时长 ≈ 3

一、定义与核心概念

1. ‌互联网暴露面‌

  • 定义:指组织在互联网上公开可访问的数字化资产和服务,如服务器、开放端口、API、网站、云服务等。

暴露面指网络系统中对外界开放的可见部分,包括公开的接口、网络端口、服务或应用程序等。例如Web服务、API、数据库端口等,这些资源可直接被外部访问或识别‌。暴露面的大小直接影响潜在攻击机会‌。

  • 核心特点:

    • 可见性:能被外部扫描或探测到(如通过IP、域名、端口)。
    • 入口点:是外部与内部系统交互的桥梁(如登录页面、文件上传接口)。
  • 示例:

    • 公网IP地址、开放的SSH端口(22)、公开的Web应用、未加密的HTTP服务。

2. ‌攻击面

  • 定义:指所有可能被攻击者利用的潜在漏洞和风险点,涵盖技术、人员、流程等多个维度。‌

攻击面指攻击者可能利用的所有潜在入口点和攻击路径,不仅包含暴露面中的可见部分,还涵盖漏洞、错误配置、权限问题、社会工程等动态风险因素。攻击面越大,系统被入侵的概率越高‌。

  • 核心特点:

    • 全面性:不仅包括暴露面,还包含内部漏洞(如配置错误、弱密码、员工安全意识不足)。
    • 动态性:随系统更新、新漏洞披露、业务扩展而变化。
  • 示例:

    • 暴露面中的漏洞(如SQL注入)、内部数据库弱口令、员工易受钓鱼攻击、过时的内部软件版本。

二、区别与关联

关系:从定义上看,攻击面包含暴露面,并且更加广泛。

暴露面与攻击面的关系

区别:

维度‌ ‌暴露面‌ ‌攻击面‌
范围‌ 仅包含对外可见的开放部分‌ 包含所有潜在攻击路径(含暴露面及内部系统、人为因素等)‌
‌动态性‌ 相对静态,与系统配置直接相关‌ 动态变化,受漏洞、人为因素等影响‌
关注点‌ 资源对外暴露的“可见性”‌,可见性和可访问性 攻击者可利用的“漏洞总和”‌,潜在漏洞和攻击路径
防御重点 减少不必要的公开资产 全面风险管理(技术+管理)
管理策略 定期扫描并关闭不必要的服务,使用防火墙限制访问,最小化公开资产。 漏洞管理、员工培训、权限控制、持续监控(如日志审计、入侵检测)。
示例 如:公司官网(example.com)开放了80和443端口,允许用户访问。 若官网存在未修复的XSS漏洞(技术风险),且管理员使用弱密码(人为风险),两者均属于攻击面。

三、防护侧重点

1. ‌暴露面管理‌

  • ‌原则‌:遵循最小权限,仅开放必要端口或服务‌。
  • ‌措施‌:网络隔离、访问控制、定期审查暴露资源‌。

2. ‌攻击面管理‌

  • ‌原则‌:降低漏洞利用可能性,覆盖技术、流程、人为因素‌。
  • ‌措施‌:渗透测试、安全评估、漏洞修复、权限管控‌。

四、总结

‌暴露面是攻击面的子集‌,两者区别在于:暴露面聚焦“对外可见性”,攻击面覆盖“可利用性”;前者是静态防御的基础,后者需动态应对综合风险‌。缩小暴露面可降低被攻击概率,而减少攻击面则能全面降低风险。


作者博客:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

一文搞懂什么是攻击面管理(ASM)

发表于 2025-02-19 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 3.3k | 阅读时长 ≈ 11

攻击面是网络安全防御的“第一道防线”,其管理能力直接决定企业的安全基线。

攻击面管理(Attack Surface Management,ASM)是一种新兴的网络安全策略和实践,旨在通过持续发现、分析、监控和评估组织内外部的所有资产,识别并管理潜在的安全风险。其核心是从攻击者的视角出发,主动识别企业网络资产的攻击面及脆弱性,包括已知和未知的资产、漏洞、配置缺陷以及泄露信息等。

一、什么是攻击面

要了解攻击面管理(ASM)首先需要了解什么是攻击面。攻击面指的是所有可能被攻击者利用的入口点,比如硬件、软件、云服务等等。攻击面(Attack Surface) 是网络安全领域的核心概念,指一个系统、网络或组织中可能被攻击者利用的所有潜在入口点和漏洞的集合。简单来说,它是攻击者可能发起攻击的“可触及范围”,范围越大,暴露的风险越高,防御难度也越大。

攻击面的核心组成部分

攻击面通常由以下要素构成:

  1. 技术资产
    ○ 硬件:服务器、路由器、IoT设备、摄像头等。
    ○ 软件:操作系统、应用程序、API、开源组件等。
    ○ 网络服务:开放的端口(如HTTP 80端口、SSH 22端口)、云服务(如AWS S3存储桶)、域名等。
  2. 配置缺陷
    ○ 默认密码未修改、权限设置错误、未加密的通信协议(如HTTP)、冗余服务(如未关闭的测试环境)等。
  3. 数据暴露
    ○ 敏感数据泄露(如数据库备份文件被公开)、代码仓库中的密钥硬编码、日志文件中的用户信息等。
  4. 人为因素
    ○ 员工的安全意识薄弱(如点击钓鱼链接)、第三方供应商的访问权限、社会工程攻击的潜在目标。
  5. 供应链风险
    ○ 依赖的第三方软件漏洞(如Log4j)、开源库的未更新版本、外包开发引入的后门等。

攻击面扩大的原因

  1. 数字化转型:云服务、微服务架构、远程办公导致资产分散化。
  2. 影子IT:员工私自部署未授权的应用或设备(如个人NAS)。
  3. 复杂供应链:第三方服务、开源组件的依赖增加。
  4. 自动化攻击工具:攻击者可快速扫描全网暴露资产(如Shodan搜索引擎)

二、攻击面的分类

根据视角和范围,攻击面可分为以下两类:

  1. 外部攻击面(External Attack Surface)
    ○ 定义:暴露在互联网上,能被外部攻击者直接访问的资产和漏洞。
    ○ 典型示例:
    ■ 面向公网的Web应用、API接口。
    ■ 云存储桶的错误配置(如公开可读)。
    ■ 员工在GitHub意外上传的数据库凭证。
    ○ 管理工具:EASM(外部攻击面管理)。
  2. 内部攻击面(Internal Attack Surface)
    ○ 定义:仅限内部网络访问,但可能被已渗透的攻击者横向利用的弱点。
    ○ 典型示例:
    ■ 内网未修复的漏洞(如永恒之蓝漏洞)。
    ■ 域控制器权限滥用、共享文件夹过度开放。
    ■ 内部员工滥用权限窃取数据。
    ○ 管理工具:CAASM(网络资产攻击面管理)、内部漏洞扫描器。

三、网络资产攻击面管理(CAASM)

网络资产攻击面管理(CAASM)全称(Cyber Asset Attack Surface Management, CAASM)是一种网络安全技术或方法论,旨在帮助组织全面发现、识别、监控和管理其数字化资产(包括硬件、软件、云服务、API、物联网设备等)的潜在攻击面,从而降低安全风险并提升防御能力。CAASM通过整合现有安全工具(如漏洞扫描器、EDR、CMDB等)的数据,构建统一的资产视图,覆盖内部网络、云环境、第三方服务等所有资产。其核心目标是解决资产分散、数据孤岛和未知资产的问题,帮助安全团队识别安全控制中的漏洞与差距,并协调修复。

CAASM 的核心功能

  1. 自动化资产发现
    ○ 通过主动扫描、被动流量分析、API集成等方式,自动发现企业内外的所有资产,包括未授权的“影子IT”(如员工私建的云实例、未知设备)。
    ○ 覆盖范围包括本地基础设施、云环境(AWS、Azure等)、第三方服务、物联网设备等。
  2. 资产分类与优先级排序
    ○ 根据资产类型(服务器、数据库、API)、业务重要性、暴露程度(如是否面向公网)等,对资产进行分类和风险评估。
    ○ 帮助安全团队优先处理高风险资产(如暴露在互联网的敏感数据库)。
  3. 攻击面可视化与实时监控
    ○ 通过仪表盘展示所有资产的拓扑关系和暴露路径,直观呈现攻击面。
    ○ 实时监控资产状态变化(如新开放的端口、新增的云服务),及时发现异常。
  4. 与现有工具集成
    ○ 整合漏洞扫描工具(如Nessus)、EDR(端点检测与响应)、防火墙日志等,形成统一的资产视图。
    ○ 利用API打通数据孤岛,避免不同工具间的信息割裂。
  5. 风险评估与缓解建议
    ○ 结合漏洞数据、威胁情报和资产上下文,生成风险评分。
    ○ 提供修复建议(如关闭不必要的端口、更新补丁)或临时缓解措施(如配置防火墙规则)。

网络资产攻击面管理(CAASM)与传统资产管理的区别

传统资产管理工具(如CMDB)通常依赖手动录入或静态数据,且缺乏对攻击面的动态分析。而CAASM的特点包括:
● 主动发现:自动识别资产,减少人为遗漏。
● 攻击面视角:不仅记录资产,还分析其暴露程度和潜在风险。
● 实时性:持续监控变化,适应动态环境(如云资源的弹性扩展)。
● 威胁关联:结合漏洞、配置错误和威胁情报进行综合分析。

四、外部攻击面管理(EASM)

外部攻击面管理(External Attack Surface Management, EASM) 是一种以攻击者视角为核心的安全管理方法,旨在持续发现、监控和评估组织暴露在互联网上的所有数字资产及其潜在风险。这些资产包括服务器、域名、云服务、API、物联网设备等,同时也涵盖影子资产(如未授权的云实例)、错误配置、开放端口、未修复漏洞以及敏感数据泄露等问题。EASM的关键在于通过外部视角模拟攻击者的行为,识别可能被利用的薄弱点,从而提前修复风险。

外部攻击面管理(EASM)的核心功能

外部攻击面管理(EASM)的核心功能主要包括以下几个方面:

  1. 泛资产发现与监控
    通过分布式探测引擎,持续扫描和监控外部环境,识别和编目从互联网可访问的数字资产,包括域名、IP地址、网页应用程序、API、云服务、影子资产、仿冒资产等。这些功能为企业提供了全面的资产暴露面视图。
  2. 攻击触点识别与评估
    在攻防视角下,依托指纹库和情报库,对发现的资产进行弱点检测,包括漏洞扫描、弱口令检测、敏感数据识别等。同时,结合供应链情报和攻防情报,评估资产被利用的风险。
  3. 数据泄露监测
    覆盖全网(包括暗网、深网、代码托管平台、网盘、文库等)范围,监测敏感数据泄露情况,及时发现并处理潜在的数据泄露风险。
  4. 攻击面分析
    基于弱点检测结果,综合分析资产的风险,识别可能的攻击路径和风险等级。评估一旦发生安全事件,业务可能受影响的范围,并提供风险收敛的优先级建议。
  5. 风险评估与预警
    评估外部攻击面相关的风险,并根据威胁的潜在影响和可能性进行优先级排序。提供7×24小时的风险预警服务,包括暴露面变动提醒、数据泄露监测、网站篡改和黑链预警等。
  6. 持续监控与适应
    定期对外部攻击面进行实时扫描和监控,结合威胁情报源和漏洞管理,检测新的或变化的资产、漏洞和威胁,并根据这些变化调整安全策略。

五、网络资产攻击面管理(CAASM)与外部攻击面管理(EASM)的联系与区别

EASM与CAASM的联系

  1. 共同目标:两者均属于攻击面管理(ASM)的核心组成部分,旨在缩小攻击面、降低安全风险。
  2. 互补性:EASM提供外部视角的资产发现和风险分析,而CAASM整合内外资产数据,形成全局视图。例如,EASM发现的外部暴露资产可输入到CAASM系统中进行关联分析。
  3. 数据整合:CAASM依赖EASM和DRPS(数字风险保护服务)的数据源,实现更全面的资产清单管理。

EASM与CAASM的区别

维度 EASM CAASM
视角 攻击者视角(外部“黑盒”扫描) 防御者视角(内部“白盒”数据整合)
覆盖范围 互联网暴露的资产(如云服务、域名、第三方应用) 内外部所有资产(包括网络设备、服务器、API、IoT设备等)
技术手段 依赖网络空间测绘、主动扫描、暗网监控 通过API与现有工具集成(如CMDB、漏洞扫描器),聚合多源数据
核心功能 资产发现、漏洞优先级排序、数据泄露检测、供应链风险评估 资产清点、数据关联分析、安全控制差距识别、自动化修复建议
适用场景 暴露在公网的资产风险管理(如云服务、子公司资产) 复杂混合环境(如多云、本地数据中心)的资产可见性与合规管理
数据来源 外部扫描、公开网络、暗网情报 内部系统日志、IT工具接口、CMDB数据库

典型应用场景对比

  1. EASM:
    ○ 云安全治理:发现公有云上的错误配置或未授权实例。
    ○ 供应链风险:评估第三方服务商的暴露面,如合作伙伴的漏洞代码。
    ○ 敏感数据泄露:监控暗网或公共平台(如GitHub)上的数据泄露。
  2. CAASM:
    ○ 影子资产管理:通过整合EDR、防火墙日志等,发现未登记的内部设备。
    ○ 漏洞优先级排序:结合资产业务价值与漏洞严重性,优化修复策略。
    ○ 合规性报告:生成统一的资产与安全控制报告,满足ISO 27001等合规要求。

● EASM更强调从外部攻击者的角度发现风险,适用于防御边界模糊的互联网暴露场景。
● CAASM则聚焦于内部资产的全面可见性,解决复杂IT环境下的数据孤岛问题。
● 协同作用:在实际应用中,两者需结合使用。例如,EASM发现的外部风险需通过CAASM与内部资产关联分析,形成闭环管理。

未来,随着攻击面管理技术的成熟,EASM与CAASM可能会进一步融合到统一平台中,实现更高效的风险收敛。

六、攻击面管理的优势与应用场景

随着技术的发展,攻击面正从传统IT向云、物联网、供应链等方向快速扩展,企业需借助自动化工具(如EASM、CAASM)和系统化策略,实现攻击面的持续收敛与风险控制。

攻击面管理的优势

● 主动防御:从传统的被动防御模式转变为积极主动地发现和管理潜在风险。
● 全面覆盖:不仅关注已知资产,还能发现未知的影子资产和泄露信息。
● 动态适应:能够适应云计算、物联网等复杂环境,并与现有安全工具(如SOC、SIEM)集成。
● 风险量化:提供更精细的风险评估和量化功能,帮助企业制定有效的安全策略。

应用场景

攻击面管理适用于多种场景,包括但不限于:
● 企业数字化转型:应对云计算、物联网等新技术带来的复杂攻击面。
● 供应链安全:评估和管理供应商基础设施中的安全风险。
● 安全运营:与安全运营中心(SOC)结合,提升整体安全管理水平。

随着技术的不断发展,攻击面管理正朝着自动化、智能化、云原生化的方向发展,并与企业的业务风险管理流程紧密结合。


博客文章:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

网络安全“挂图作战”及其场景

发表于 2025-02-18 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 2.1k | 阅读时长 ≈ 7

一、网络安全挂图作战来源与定义

1、网络安全挂图作战的来源

网络安全挂图作战的概念源于传统军事作战中的“挂图作战”,即通过地图来指挥和协调作战行动。在网络空间安全领域,这一概念被引入并发展为一种新的网络安全管理和防御策略。其灵感来自于地理学中的“人地”关系理论,通过将网络空间的要素与地理空间相结合,构建网络空间地图。

在2020年7月,网络安全专家郭启全等在《中国科学院院刊》上发表了《发展网络空间可视化技术支撑网络安全综合防控体系建设》研究文章,论述了网络空间“挂图作战”的基本理念和发展愿景。

同年公安部印发《贯彻落实网络安全等保制度和关保制度的指导意见》(公网安[2020]1960号),明确提出“要加强网络新技术研究和应用,研究绘制网络空间地理信息图谱(网络地图),实现挂图作战”。

2、网络安全挂图作战的定义

挂图作战: 按计划、按目标、按进度、按要求实施的一种作战方式或工作方法。
网络安全挂图作战的核心思想:将攻击者的攻击路径和影响范围以图形化方式展现,帮助防守方更直观、全面地理解攻击者的行为以及对组织资产的影响,从而更有效地进行威胁检测、分析、响应等动作。

网络安全挂图作战是一种通过可视化技术将网络安全态势、资产、威胁等信息以图形化方式展示出来的方法。其核心在于通过构建网络空间地图,实现对网络安全事件的全过程展示和管理,通过“看、管、防、控”一体化实现主动防御的工作模式。

其核心价值在于:
● 攻防视角可视化:将攻击者的路径、手段及影响范围图形化呈现,辅助防守方快速定位薄弱点。
● 全生命周期管理:覆盖威胁检测、分析、响应、复盘的全流程闭环。
● 协同作战能力:整合多部门、多工具数据,打破信息孤岛,提升响应效率。

具体来说,挂图作战包括以下几个方面:

  1. 可视化展示:将网络环境中的各个要素(如资产、漏洞、威胁等)以图形化的方式呈现,提高网络安全的可视化程度。
  2. 态势感知与分析:通过挂图作战平台,实时监测和感知网络安全态势,及时发现和分析安全威胁。
  3. 决策支持:为安全决策提供直观的数据支持,帮助安全团队更好地研判和处置安全事件。
  4. 协同作战:支持多方协同作战,整合不同安全工具和平台的信息,提高安全事件的响应速度和处理效率。

通过这些功能,网络安全挂图作战能够有效地提升网络安全防护的效率和准确性,帮助组织更好地应对复杂的网络安全挑战。

二、挂图作战关键技术

  1. 网络空间测绘技术
    ● 资产指纹库:通过主动扫描(如端口探测、协议解析)和被动流量分析(如流量镜像),识别网络中的设备、服务、应用及版本信息。
    ● 拓扑自动发现:利用路由追踪、SNMP协议等,绘制网络节点间的连接关系和通信路径。
  2. 动态可视化引擎
    ● 图数据库(Neo4j、GraphX):存储复杂的资产关系与攻击链路,支持快速查询和路径分析。
    ● 威胁热力图:根据攻击频率、漏洞严重性等参数生成风险热区,直观标注高危区域。
  3. 攻击链建模(Cyber Kill Chain)
    ● MITRE ATT&CK框架集成:将攻击者的TTPs(战术、技术、过程)映射到网络地图中,预判攻击路径。
    ● 攻击模拟推演:基于红队工具(如Cobalt Strike)模拟攻击行为,验证防御策略有效性。
  4. 自动化响应编排(SOAR)
    ● 剧本(Playbook)驱动:当检测到攻击时,自动触发防火墙封禁、隔离主机、下发补丁等动作。
    ● 人机协同:高风险操作需人工确认,避免误拦截影响业务。
  5. 多源数据融合
    ● 跨平台集成:对接EDR、SIEM、漏洞扫描器等工具,聚合日志、告警和资产数据。
    ● 威胁情报联动:接入外部威胁情报(如恶意IP库、漏洞库),实时更新攻击特征。

三、挂图作战与传统态势感知的差异

对比维度 传统态势感知 挂图作战
核心目标 被动监控全网安全状态 主动防御,聚焦攻击路径阻断与协同响应
数据粒度 宏观指标(如告警数量、风险等级) 微观到单个资产、漏洞、攻击链节点的精准定位
可视化方式 仪表盘(Dashboard)与统计图表 交互式网络地图,支持攻击链路动态推演
响应模式 人工研判后分步处置 自动化剧本执行 + 跨团队指令同步
适用场景 日常监控与合规报告 实战攻防(如HW行动)、应急响应、红蓝对抗
技术重心 大数据分析与告警聚合 攻击链建模、可视化指挥、自动化编排

四、挂图作战主要场景

  1. 关键基础设施防护
    ● 场景痛点:能源、交通等行业的OT系统(工控网络)存在大量老旧设备,难以实时监控。
    ● 挂图方案:
    ○ 绘制OT网络拓扑,标注PLC、SCADA系统的物理位置与逻辑连接。
    ○ 当检测到异常指令(如未授权的参数修改)时,地图自动定位受影响设备并隔离。
  2. 重大活动安保
    ● 场景痛点:活动期间网络访问激增,需防范DDoS、网页篡改等针对性攻击。
    ● 挂图方案:
    ○ 构建“活动专属作战地图”,集成CDN节点、票务系统、直播平台等核心资产。
    ○ 实时标注攻击源IP(如来自特定国家的扫描行为),联动云WAF自动封禁。
  3. 供应链攻击防御
    ● 场景痛点:第三方软件或服务漏洞可能成为攻击跳板(如SolarWinds事件)。
    ● 挂图方案:
    ○ 标注供应链厂商的接入点及权限范围,监控异常横向移动。
    ○ 当某供应商账号异常登录时,地图高亮关联资产并触发权限回收。
  4. 红蓝对抗演练
    ● 场景痛点:传统攻防演练中防守方难以快速定位攻击入口。
    ● 挂图方案:
    ○ 红队攻击路径实时映射到地图,蓝队可追溯攻击者从外网渗透到内网提权的全过程。
    ○ 演练结束后生成攻击路径复盘报告,优化防御策略。
  5. 零日漏洞应急响应
    ● 场景痛点:漏洞爆发后(如Log4j),企业需快速定位受影响资产。
    ● 挂图方案:
    ○ 输入漏洞特征(如JNDI调用),地图自动标记存在漏洞的服务实例。
    ○ 联动补丁管理系统,按业务优先级分批修复。

五、未来趋势

  1. 数字孪生融合:结合数字孪生技术,实现网络空间与物理世界的1:1映射。
  2. AI辅助决策:通过大语言模型(LLM)生成自然语言防御建议,降低操作门槛。
  3. 跨域协同:与国土安全、城市应急系统联动,构建国家级网络空间地图。

结语

“挂图作战”标志着网络安全从“被动告警”迈向“主动防御”的范式转变。通过将虚拟攻击映射为可视化的“战场”,企业不仅能看清自身防御盲区,更能在攻防对抗中抢占先机。随着技术的演进,未来的网络安全指挥中心或许将如军事作战室一般,通过一张动态地图掌控全局。


博客文章:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

网络安全之国际主流网络安全架构模型

发表于 2024-11-18 | 更新于: 2025-04-08 | 分类于 技术 , 网络安全 | | 阅读次数:
字数统计: 2.1k | 阅读时长 ≈ 7

目前,国际主流的网络安全架构模型主要有:
● 信息技术咨询公司Gartner的ASA(Adaptive Security Architecture自适应安全架构)
● 美国政府资助的非营利研究机构MITRE的ATT&CK(Adversarial Tactics Techniques & Common Knowledge 对抗战术技术和常识)
● 信息技术咨询公司Gartner的CSMA(Cybersecurity Mesh Architecture网络安全网格架构)

1. Gartner提出的ASA(Adaptive Security Architecture自适应安全架构)

2014年,针对于当时业界安全产品主要重在防御和边界,安全态势形成严重挑战的问题,Gartner公司首次提出ASA(Adaptive Security Architecture自适应安全架构),希望业界能从单纯被动防御和应急响应的思路中解放出来,通过加强持续监测和分析预测提升主动防御能力,1.0架构主要包括以下四个象限:

1) 预防Pretect,通过系统加固和隔离等手段来减少系统暴漏面积,比如采用黑名单;
2) 检测Detect,持续监视/检测事故的发生并对其进行评估,对检出的事故进行隔离,以防止其造成进一步的破坏;
3) 响应Response,事故发生之后需要对事故进行补救和溯源;
4) 预测Predict,根据以往已经存在的威胁,来预测潜在的威胁。

2017年,针对于高级攻击的防御架构,Gartner公司在1.0架构的基础上进行了相关的理论丰富,将自适应安全架构的外延扩大,自适应安全架构进入2.0时期:

1) “持续监控分析”改成“持续可视化和评估”,同时加入UEBA相关的内容(User& Entity behavior analytics用户和实体的行为分析);
2) 引入每个象限的小循环体系,不仅仅是四个象限大循环;
3) 在大循环中加入了策略和合规要求,同时对大循环的每个步骤说明了循环的目的,到保护象限是实施动作、到检测象限是监测动作、到响应和预测象限都是调整动作。

2018年,Gartner公司正式确认了CARTA(Continuous Adaptive Risk and Trust Assessment持续自适应风险与信任评估)的安全趋势,即自适应安全架构3.0。相比2.0架构,3.0架构最大的变化是把2.0架构作为攻击的保护外环,增加关于访问的保护内环,原因在于:

1) 2.0架构未考虑认证问题,导致完整性有缺失,如黑客获取有效认证内容,如用户名密码,自适应架构对于此类事件是“可信”的,威胁无法感知;
2) 为加强云时代下的云服务的发现、访问、监控和管理,3.0架构将CASB(Cloud Access Security Broker云访问安全代理)作为原型挪到了这个总体架构中,解决了部分认证问题;
3) 如果认证体系只是一次性认证并没有持续的监控和审计,必须要有被窃取认证信息的心理预期,所以要持续的进行监控和分析以及响应,形成闭环。

3.0架构的适用场景变得更为广泛,包括了安全响应、数据保护、安全运营中心、开发安全运维、物联网、供应链安全、业务持续和灾难恢复等领域。

ASA自适应安全架构

2. MITRE提出ATT&CK(Adversarial Tactics Techniques & Common Knowledge 对抗战术技术和常识)

ATT&CK(Adversarial Tactics Techniques & Common Knowledge 对抗战术技术和常识)是一个知识库,它从攻击者的角度看待问题,理顺了攻击者渗透网络、入侵主机、提升权限、隐秘移动和渗漏数据的攻击链,建立了网络攻击中使用的战术和技术的详尽列表,呈现了攻击者在攻击网络时所采用的行为,并且详细介绍了每一种技术的利用方式。

该模型被CISA(美国网络安全与基础设施安全局)和FBI以及超过80%的企业用于威胁调查,它对于政府或企业组织来说都非常有用,因为组织需要建立一个基于威胁的防御体系。

ATT&CK模型可以帮助网络事件响应团队(CERT)、安全运营中心(SOC)、红蓝队、威胁猎手、IT部门等安全团队,更好地测试、开发和排序其检测和响应机制,对公司的业务、行业和知识产权提供高效安全保障,具体可分为:

1) Detections and Analytics(检测和分析):帮助网络防御者开发分析程序,以检测对手使用的技术。
2) Threat Intelligence(威胁情报):为分析人员提供了一种通用语言来构造,比较和分析威胁情报。
3) Adversary Emulation and Red Teaming(攻击模拟):提供了一种通用语言和框架,攻击模拟团队可以使用该语言和框架来模拟特定威胁并计划其行动。
4) Assessment and Engineering(评估与工程化):可用于评估组织的能力并推动工程决策。

但是,安全公司McAfee与加州大学伯克利分校长期网络安全中心的联合调研项目发现,很多网络安全团队在框架应用方面仍然面临诸多挑战:

1) 大多数采用ATT&CK框架的安全团队都没有实现自动化。虽然91%的企业使用ATT&CK框架来标记网络安全事件,但只有不到一半的企业可以自动更改部分安全策略;
2) ATT&CK框架和安全产品之间的互操作性存在困难;
3) 难以将网络安全事件映射到安全策略更改,以及无法关联来自云、网络和端点的事件;
4) 企业使用的安全产品可能无法检测到ATT&CK矩阵中存在的所有技术。

2021年,MITRE发布了ATT&CK的第十个版本,该版本最大的变化是在企业矩阵(Enterprise ATT&CK)中添加了一组新的数据源和数据组件对象,以补充ATT&CK v9中发布的数据源名称更改。新版ATT&CK企业矩阵包含14个战术、188个技术、379个子技术、129个组和638个软件。

ATT&CK架构

3. Gartner提出的CSMA(Cybersecurity Mesh Architecture网络安全网格架构)

随着更多的应用和数据迁移到云服务,传统网络边界已经消失,网络安全威胁形势日益复杂。同时,网络攻击手段也在快速演进,AI和大规模自动化技术驱动的新型威胁层出不穷,带来了快速增长的网络攻击数量。在这种形势下,传统安全手段已经无以为继,组织普遍存在网络安全技能短缺的困境。因此,Gartner在2021年一种全新的安全架构模式CSMA(Cybersecurity Mesh Architecture网络安全网格架构)。

CSMA架构是一种现代安全方法,包括在最需要的地方部署控制措施、构建身份化的零信任网络并以身份作为安全边界,通过提供基础安全服务以及集中式策略管理和编排功能,使诸多工具能够协同操作,而不是每个安全工具都在孤岛环境中使用。
通过CSMA架构,可以获得所有边缘的深度可见性、集中管理分布式解决方案、策略的一致执行、利用威胁情报、通过集成第三方能力以更好地防卫已知和未知攻击、跨混合环境自动执行可操作响应等优势。

CSMA网络安全网格架构

CSMA架构希望通过搭建一个全面覆盖、深度集成、动态协同的“网络安全网格平台”,将不同厂商的安全工具整合为一个协同生态系统,让组织能够灵活地进行方案部署,同时从集成和融合的运营、可视化和安全性中受益,对于在当前不断扩展的网络中,降低复杂度和提高整体安全有效性至关重要。


博客文章:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

vue3实现登录获取token并自动刷新token进行JWT认证

发表于 2024-10-10 | 更新于: 2025-04-08 | 分类于 技术 | | 阅读次数:
字数统计: 1.6k | 阅读时长 ≈ 8

在《django应用JWT(JSON Web Token)实战》介绍了如何通过django实现JWT,并以一个具体API接口实例的调用来说明JWT如何使用。本文介绍如何通过vue3的前端应用来使用JWT认证调用后端的API接口,实现一下的登录认证获取JWT进行接口认证。

账号密码验证jwt流程

一、账号密码登录获取JWT

通过Login.vue实现登录的用户名、密码表单信息收集,调用getToken()方法进行鉴权验证并获取jwt的token。
Login.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<template>
<div class="body">
<el-form :model="form" :rules="rules" ref="loginForm" class="loginContainer">
<h3 class="loginTitle">
欢迎登录
</h3>
<el-form-item label="用户名" prop="username" :label-width="formLabelWidth">
<el-input type="text" v-model="form.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password" :label-width="formLabelWidth">
<el-input type="password" v-model="form.password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item :label-width="formLabelWidth">
<el-button type="primary" :plain="true" @click="submitForm('form')">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>

<script>
import { useUserStore } from '@/stores/user'
import { ElMessage } from 'element-plus';
import {getToken} from '../api/user'
export default {
data() {
return {
form: {
username: '',
password: '',
err_username: "",
err_password: "",
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' }
],
password: [
{ required: true, min:6, message: '请输入密码', trigger: 'blur' }
]
},
formLabelWidth: '120px'
};
},
methods: {
submitForm(formName) {
if (this.$refs.loginForm) {
this.$refs.loginForm.validate(valid => {
if (valid) {
// 提交表单逻辑
console.log('提交成功:', this.form);
this.login();
} else {
console.log('验证失败');
ElMessage.error('验证失败,请检查您的输入!');
}
});
} else {
console.error('表单未找到');
}
},
login() {
var that = this;
this.message = "";
// 用户名密码鉴权获取jwt的token
getToken({
'username': this.form.username,
'password': this.form.password,
}).then((Response) => {
console.log(Response);
if (Response && Response.access) {
// //保存数据到本地存储
this.username= that.form.username;
useUserStore().login(this.username,Response.access,Response.refresh)
this.username = "";
this.password = "";
this.$router.push({name:"home"}); //跳转到首页
}
})
.catch(function (error) {
console.log(error);
if ("username" in error) {
that.err_username = error.username[0];
} else if ("password" in error) {
that.err_password = error.password[0];
} else {
ElMessage.error('登录失败!');
}
});
},

}
};
</script>

<style scoped>
.loginContainer{
border-radius: 15px;
background-clip: padding-box;
text-align: left;
margin: auto;
margin-top: 180px;
width: 450px;
padding: 15px 35px 15px 35px;
background: aliceblue;
border:1px solid blueviolet;
box-shadow: 0 0 25px #f885ff;
}
.loginTitle{
margin: 0px auto 48px auto;
text-align: center;
font-size: 40px;
}
.loginRemember{
text-align: left;
margin: 0px 0px 15px 0px;
}
.loginbody{
width: 100vw;
height: 100vh;
background-size:100%;
overflow: hidden;
}
</style>

在登录时调用getToken()方法获取jwt的token
getToken的封装方法如下:

1
2
3
4
5
6
7
8
9
import request from '@/utils/request'

export function getToken(data) {
return request({
url: 'token/',
method: 'post',
data
})
}

通过用户名和密码鉴权可以获得JWT的token,接口会返回access的token和refresh的token,需要将这两个token保存下来,access的token用来进行API接口的jwt认证,refresh的token用来刷新失效的access的token。

二、将JWT保存至本地

通过pinia将token保存至浏览器的本地存储,以便于后面请求API时带上访问的token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import { defineStore } from 'pinia'
import { refreshToken } from '../api/user'

export const useUserStore = defineStore('user', {
persist: {
enabled: true, //开启数据持久化
strategies: [
{
key: "userState", //给一个要保存的名称
storage: localStorage, //sessionStorage / localStorage 存储方式
},
],
},
state: () => ({
isLoggedIn: false,
username: '',
jwtAccessToken: null,
jwtRefreshToken: null,
}),
actions: {
login(username, accessToken,refreshToken) {
this.username = username
this.isLoggedIn = true
this.setToken(accessToken, refreshToken)
},
logout() {
this.username = ''
this.jwtAccessToken = null
this.isLoggedIn = false
},
setToken(accessToken, refreshToken) {
this.jwtAccessToken = accessToken
this.jwtRefreshToken = refreshToken
},
refreshToken() {
return new Promise((resolve, reject) => {
refreshToken({"refresh":this.jwtRefreshToken}).then((response) => {
this.setToken(response.access, this.jwtRefreshToken)
resolve(response.access)
console.log('return refreshToken-----------'+response.access)
}).catch((error) => {
reject(error)
})
})
}

},
getters: {
getIsLoggedIn: (state) => state.isLoggedIn,
getUsername: (state) => state.username,
getUserAccessToken: (state) => state.jwtAccessToken,
getRefreshToken: (state) => state.jwtRefreshToken,
}
})

在登录的Login.vue组件中调用useUserStore().login(this.username,Response.access,Response.refresh)将用户名、access的token、refresh的token保存至浏览器的本地存储。

三、请求API带上JWT

将axios的调用封装成request.js在调用API接口时带上JWT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import axios from 'axios'
import Router from '@/components/tools/Router'
import { useUserStore } from '@/stores/user'
import { ElMessage } from 'element-plus'
import { refreshToken } from '../api/user'

const api_rul = import.meta.env.VITE_APP_API_URL

// create an axios instance
const service = axios.create({
baseURL: api_rul,
timeout: 5000, // request timeout
})

// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
const { url } = config
// 指定页面访问需要JWT认证。
if (url.indexOf('/login')!== -1) {
return config
}
let jwt = useUserStore().getUserAccessToken
config.headers.Authorization = `Bearer ${jwt}`
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)

export default service

主要是在请求头重带着jwt的信息

1
2
let jwt = useUserStore().getUserAccessToken
config.headers.Authorization = `Bearer ${jwt}`

四、在token失效时自动重新获取token

前面提到JWT基于安全考虑有两个token,一个是access token ,一个是refresh token 。access token的失效时间较短,可以有效降低泄露而造成的影响,两个token的区别和作用如下:

access token refresh token
有效时间 较短(如半小时) 较长(如一天)
作用 鉴权验证 重新获取access token
什么时候使用 每次接口鉴权验证时 access token失效时使用

使用refresh token的逻辑如下:
重新获取token流程

以下通过拦截器实现token失效后重新获取access token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import axios from 'axios'
import Router from '@/components/tools/Router'
import { useUserStore } from '@/stores/user'
import { ElMessage } from 'element-plus'
import { refreshToken } from '../api/user'

const api_rul = import.meta.env.VITE_APP_API_URL

// create an axios instance
const service = axios.create({
baseURL: api_rul,
timeout: 5000, // request timeout
})

// request interceptor
service.interceptors.request.use(
config => {
// do something before request is sent
const { url } = config
// 指定页面访问需要JWT认证。
if (url.indexOf('/login')!== -1) {
return config
}
let jwt = useUserStore().getUserAccessToken
config.headers.Authorization = `Bearer ${jwt}`
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)

// response interceptor
service.interceptors.response.use(

response => {
const res = response.data
return res
},
async error => {
console.log('err' + error) // for debug
const originalRequest = error.config;
// 授权验证失败
if (error.response.status === 401 && originalRequest._retry!== true) {
originalRequest._retry = true;
// 刷新token
let jwtRefreshToken=useUserStore().getRefreshToken
await refreshToken({"refresh":jwtRefreshToken}).then((response) => {
// 刷新token成功,重新请求
let jwtToken=response.access
useUserStore().setToken(jwtToken, jwtRefreshToken)
console.log('return refreshToken-----------'+response.access)
originalRequest.headers.Authorization = `Bearer ${jwtToken}`
return service(originalRequest)
}).catch((error) => {
// 刷新token失败,跳转到登录页面
ElMessage.error('请重新登录!')
Router.push({name:'login'})
})

}
// 内部错误
if (error.response.status === 500) {
let errormsg=error.response.data.msg
ElMessage.error('服务器内部错误!'+errormsg)
}
if (error.response.status === 400)
{
ElMessage.error('错误的请求!')
}
return Promise.reject(error)
}
)

export default service

在判断error.response.status === 401时调用refreshToken重新获取jwttoken进行接口的调用。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

django应用JWT(JsonWebToken)实战

发表于 2024-09-22 | 更新于: 2025-04-08 | 分类于 技术 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 5

在前后端分离的项目中,前后端进行身份验证通常用JWT来进行,JWT 提供了一个理想的认证解决方案,用来保护 RESTful API,确保只有经过认证的用户才能访问受保护的资源。基于前端框架(如React, Angular, Vue.js)的单页面应用 (SPA),开发者通过使用 JWT可以获得一种简单、安全、高效的方式来处理用户认证和授权的问题。本文通过django项目的实战来说明如何应用和使用JWT。

一、什么是JWT

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络各方之间以安全且紧凑的形式传输信息。JWT 是一个小型的凭证,通常用于身份验证和授权场景。JWT 由三部分组成:头部 (Header)、负载 (Payload) 和签名 (Signature)。
JWT信息由3段构成,它们之间用圆点“.”连接,格式如下:

1
aaaaaa.bbbbbb.cccccc

一个典型的JWT如下所示:

1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzI2OTcyMDc2LCJpYXQiOjE3MjY5NzAyNzYsImp0aSI6IjMyMTFiZjdmZDlhZTRmNTBhMDNmOGM2NjcwNDM2NjFiIiwidXNlcl9pZCI6Mn0.Ej6US4Uk-sSNm9P8kTU_cDAzBpO4I-BLhPstp5sG00Q
  • 头部 (Header):包含了关于 JWT 类型的信息以及所使用的签名算法。
  • 负载 (Payload):是 JWT 的主体部分,包含了实际需要声明的数据。这些数据通常包括用户ID、用户名、角色等信息。
  • 签名 (Signature):用于验证 JWT 的发送者就是它声称的发送者,同时也确保了 JWT 在传输过程中没有被篡改。

二、为什么使用JWT

使用 JWT 的原因主要有以下几点:

  • 安全性:JWT 通过签名来保证数据的完整性和防篡改性。如果有人试图修改 JWT 内容,签名会失效,接收方可以检测到这一行为。
  • 无状态性:JWT 是自包含的,这意味着不需要在服务器上保存会话状态。每个 JWT 都包含了所有必要的信息,从而减少了对服务器端存储的需求。
  • 跨域支持:JWT 可以轻松地在不同的域之间共享,这使得它非常适合微服务架构和分布式系统。
  • 性能提升:由于 JWT 是自包含的,所以服务器可以快速地验证 JWT,而无需查询数据库来获取用户信息,这提高了应用的响应速度。
  • 易于缓存和扩展:JWT 可以被缓存,并且因为它们是无状态的,所以可以很容易地扩展到多个服务器,而无需担心会话复制问题。
  • CSRF 防护:使用 JWT 可以帮助缓解跨站请求伪造(CSRF)攻击的风险,因为 JWT 不依赖于 cookie,也就不会随同 HTTP 请求自动发送。

总的来说,JWT 提供了一种高效、安全的方式来处理用户认证和授权,尤其是在需要跨域操作或构建无状态服务的情况下。

三、在django项目中如何应用JWT

JWT(JSON Web Token)是一种用于在网络应用中安全地传输信息的令牌。它通常用于身份验证和授权,特别是在单页应用(SPA)和API服务中。在Django中应用JWT,可以使用 djangorestframework-simplejwt。

1、安装djangorestframework-simplejwt库:

1
pip install djangorestframework-simplejwt

2、在settings.py中配置JWT认证:

在INSTALLED_APPS中添加rest_framework_simplejwt的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
INSTALLED_APPS = [
'blog',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_simplejwt', # 添加 simplejwt 应用
'django_filters', # 注册条件查询
'mdeditor', # 注册markdown的应用
'drf_yasg2', # 接口文档
]

添加REST_FRAMEWORK的默认认证类为JWT认证

1
2
3
4
5
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}

添加SIMPLE_JWT的相关配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# JWT 相关设置
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30), # 访问令牌的有效时间
'REFRESH_TOKEN_LIFETIME': timedelta(days=1), # 刷新令牌的有效时间
'ROTATE_REFRESH_TOKENS': False, # 是否允许刷新令牌循环
'BLACKLIST_AFTER_ROTATION': True, # 刷新令牌后是否加入黑名单
'UPDATE_LAST_LOGIN': False, # 登录时是否更新最后登录时间

'ALGORITHM': 'HS256', # 签名算法
'SIGNING_KEY': SECRET_KEY, # 签名密钥
'VERIFYING_KEY': None, # 验证密钥
'AUDIENCE': None, # 观众
'ISSUER': None, # 发行人
'JWK_URL': None, # JWK URL
'LEEWAY': 0, # 宽限期

'AUTH_HEADER_TYPES': ('Bearer',), # 授权头类型
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION', # 授权头名称
'USER_ID_FIELD': 'id', # 用户 ID 字段
'USER_ID_CLAIM': 'user_id', # 用户 ID 声明
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',

'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',), # 认证令牌类
'TOKEN_TYPE_CLAIM': 'token_type', # 令牌类型声明
'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',

'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp', # 滑动令牌刷新过期声明
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5), # 滑动令牌有效时间
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), # 滑动令牌刷新有效时间
}

3、在urls.py中配置JWT的获取和刷新路由:

1
2
3
4
5
6
7
from django.urls import path
from rest_framework_simplejwt.views import (TokenObtainPairView, TokenRefreshView)
urlpatterns = [
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
# 其他路由...
]

4、在视图中需要认证的地方使用JWT认证
如下modelviweset中使用,对于查询方法如list,retrieve不做鉴权,对于其他方法需要鉴权。

1
2
3
4
5
6
7
8
9
10
11
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
if self.action in ['list', 'retrieve']:
# 对于list方法,返回AllowAny权限类,表示不需要鉴权
permission_classes = [AllowAny, ]
else:
# 对于其他方法,返回IsAuthenticated权限类,表示需要用户已认证
permission_classes = [IsAuthenticated, ]
return [permission() for permission in permission_classes]

四、JWT如何使用

通过上面的应用后,使用接口调用遇到需要鉴权的会提示需要认证。
如当我们调用删除接口时,如果没有获得鉴权,接口会返回需要认证的信息。
接口调用需要认证

那如何通过JWT进行认证呢?
JWT进行认证过程

下面通过postman来应用JWT的使用过程。

1、调用生成JWT的接口获取JWT

调用生成JWT的接口获取JWT

2、客户端保存JWT在调用接口时带上获取的JWT

调用接口时带上获取的JWT

至此,本文介绍了什么时JWT,为什么要使用JWT,通过django实现JWT,介绍了JWT的使用流程,最后以一个具体API接口实例的调用来说明JWT如何使用。后续将介绍VUE从前端登录获取JWT到JWT认证的实例。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

django实现开发、测试、生产环境配置区分

发表于 2024-09-16 | 更新于: 2025-04-08 | 分类于 技术 | | 阅读次数:
字数统计: 1.2k | 阅读时长 ≈ 4

任何实际的软件项目中都要经过开发、测试、然后上生产的阶段,在开发、测试的过程中往往会要频繁的切换开发、测试、生产等不同的环境。每个环境的配置有可能不一样,本文介绍如何实现django项目配置环境变量实现开发、测试、生产灵活便捷的切换。

一、为什么要区分开发 (dev)、测试 (test) 和生产 (prod) 环境

在Django项目中区分开发、测试和生产环境是非常重要的,这主要是因为不同环境在多个方面存在显著差异。
● 开发环境:通常配置为易于开发和调试,比如开启调试模式(DEBUG = True),这样可以提供更详细的错误信息和页面跟踪,方便开发者定位问题。同时,开发环境可能使用本地数据库或内存数据库,以便快速启动和测试。
● 测试环境:配置为模拟生产环境,但用于自动化测试。测试环境需要确保测试的独立性和一致性,以便准确地评估应用程序在类似生产条件下的表现。测试环境通常使用与生产环境相同或相似的数据库设置,但数据是测试专用的。
● 生产环境:配置为高性能、高可用性和高安全性。关闭调试模式,优化数据库连接和缓存策略,确保应用程序能够处理大量并发请求和保障数据的安全。
通过区分这些环境,开发者可以更有效地管理django项目,确保每个环境都能满足其特定的需求,从而提高开发效率、保障数据安全和提升用户体验。

二、django项目如何通过配置实现环境配置的区分

对于django项目实现开发(dev)、测试(test)和生产(prod)环境的配置分离可以通过使用不同的设置文件实现。
下面,我们以一个实例来介绍在django的项目如何通过使用不同的设置文件的方式区分不同的环境。

1、针对不同的环境创建不同的设置文件settings.py

针对不同的环境创建不同的设置文件,如开发环境settings_dev.py ,测试环境setting_test.py,正式生产环境使用默认的setting.py,对于共性的配置可以抽取到base.py中,其他的设置文件可以继承base.py中的配置,只有实现各个环境特有的设置就可以了。
创建设置文件的目录结构如下图所示。

根据不同的环境创建不同的配置文件

2、在设置文件中根据需要进行配置区分

典型的,如开发环境settings_dev.py用的本地数据库并开启debug模式、测试环境setting_test.py用sqlite3数据库开启debug模式。
注意:其他的设置文件要继承base.py中的配置,需要加入from .base import *
参考配置如下:
setting_test.py

1
2
3
4
5
6
7
8
9
10
11
12
13
from .base import *

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'test_db.sqlite3'),
}
}

setting_dev.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from .base import *

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['127.0.0.1', 'localhost','ishareblog.com']

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'ishareblog_test',
'USER': 'ishareblog',
'PASSWORD': 'yourpassword',
'HOST': '127.0.0.1',
'PORT': '3306',
# 1、取消外键约束,否则多对多模型迁移报django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint');
# 2、解决字符串4个字节的utf8编码的字符报错的问题
'OPTIONS': {
'charset': 'utf8mb4',"init_command": "SET foreign_key_checks = 0;",
}
}
}

3、根据不同的环境运行使用不同的设置文件

不同的环境有了不同的设置文件后,就可以在不同的环境运行和使用配置文件。
如生产环境使用的wsgi启动的服务,可以在wsgi.py文件中指定使用生产环境的配置文件

wsgi中使用生产环境配置文件

在开发环境中使用manage.py启动服务的,可以修改manage.py将设置文件改为setting_dev
开发环境在manage文件中使用开发设置文件

也可以通过命令行指定设置文件 python manage.py runserver --settings=ishareblog.settings_dev
如果时通过IDE启动,可以在IDE中指定使用的环境设置文件。
如下图所示:

在IDE中指定环境设置文件

如要使用测试环境的设置文件,可以配置成ishareblog.settings_test,或通过命令行指定设置文件 python manage.py runserver --settings=ishareblog.settings_test

至此,本文详细的介绍了通过不同的设置文件来区分配置开发、测试、生产环境的配置及如何根据不同的环境使用不同的设置文件。解决不同环境去频繁修改settings.py环境设置的问题。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注:微信公众号,一起学习成长!

vue3+elementplus的表格展示和分页实战

发表于 2024-09-02 | 更新于: 2025-04-08 | 分类于 技术 | | 阅读次数:
字数统计: 1.6k | 阅读时长 ≈ 8

Element Plus 是一个基于 Vue 3 的现代化 UI 组件库,旨在帮助开发者快速构建美观且功能丰富的 Web 应用程序。它提供了大量的 UI 组件,如按钮、表单、表格、弹出框、标签页、树形控件等,涵盖了 Web 应用开发中常见的大多数场景。本文通过一个实例来说明vue3+elementplus查询、展示和分页实战。

一、Element Plus的安装使用

要开始使用 Element Plus,首先需要在项目中安装它。如果你正在使用 Vue 3 的项目,可以通过 npm 或 yarn 安装 Element Plus:

1
npm install element-plus

然后可以在Vue 项目中全局引入 Element Plus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { createApp } from 'vue'
import App from './App.vue'

// 导入路由
import Router from './components/tools/Router'
// 导入ElementPlus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

const app = createApp(App)
// 遍历ElementPlusIconsVue中的所有组件进行祖册
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
// 向应用实例中全局注册图标组件
app.component(key, component)
}
app.use(ElementPlus) // 使用ElementPlus
app.use(Router); // 使用路由
app.mount('#app')

二、el-table 表格组件

el-table 是Element Plus 中的一个重要组件,用于展示列表数据。可以通过 组件来定义表格中的每一列,包括列标题、列宽、对齐方式等,可以结合 el-pagination 可以实现分页功能。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<el-table
ref="multipleTable"
:data="postList"
tooltip-effect="dark"
style="width: 100%"
fit
:pagination="pagination"
@selection-change="handleSelectionChange" >
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
label="ID"
width="100"
prop="id">
</el-table-column>
<el-table-column
label="标题"
width="450"
prop="title">
</el-table-column>
<el-table-column
label="是否置顶"
width="100"
prop="isTop">
</el-table-column>
<el-table-column
label="热度"
width="100"
prop="viewsCount">
</el-table-column>
<el-table-column
label="发布时间"
width="200"
prop="pubTime">
</el-table-column>
<el-table-column
label="操作"
>
<template #default="scope">
<el-button size="mini" type="danger" @click="deleteItem(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>

其中
:data="postList" 绑定要显示在表格中的数据源,通常是一个对象数组
fit: 让表格宽度自动填充父容器。
:pagination="pagination" 绑定分页的数据对象

数据定义如下:

1
2
3
4
5
6
7
8
9
// 博客文章列表数据
postList:[],
// 分页
pagination: {
currentPage: 1, // 当前页
pageSize: 10, // 每页显示条数
total: 0, // 总条数
layout: 'total,sizes,prev, pager, next, jumper', // 分页布局
},

三、el-pagination 分页组件

el-pagination Element Plus 中用于实现分页功能的重要组件。它可以与 el-table 组件结合使用,实现数据的分页显示。示例代码如下:

1
2
3
4
5
6
7
8
9
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-sizes="[10, 20, 30, 40]"
:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>

属性
● @size-change="handleSizeChange" 当每页显示数量变化时触发。
● @current-change="handleCurrentChange" 当当前页变化时触发。
● :current-page="currentPage" 设置当前页。
● :page-sizes="[10, 20, 30, 40]" 设置每页可选的数量。
● :page-size="pageSize" 设置每页显示的数量。
● layout="total, sizes, prev, pager, next, jumper" 设置分页布局。
● :total="tableData.length" 设置总数据量。
方法:
● handleSelectionChange(val) 处理行选择变化。
● deleteItem(index) 删除指定行。
● handleSizeChange(val) 处理每页显示数量变化。
● handleCurrentChange(val) 处理当前页变化。

四、全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
<template>
<div class="content-container" direction="vertical">
<!-- input -->
<div>
<el-container class="content-row">
<div class="input-tip">
文章标题:
</div>
<div class="input-field" style="width: 400px;">
<el-input v-model="queryParam.words"></el-input>
</div>
<el-button type="primary" @click="getBlogList">筛选</el-button>
<el-button type="danger" @click="clear">清空筛选</el-button>
</el-container>
</div>
<!-- list -->
<div>
<el-tabs type="card" @tab-click="handleClick">
<el-tab-pane label="全部"></el-tab-pane>
<el-tab-pane v-for="(item,index) in blogCategorys"
:key="index"
:label="item.title"
:name="item.id">
</el-tab-pane>
</el-tabs>
<el-table
ref="multipleTable"
:data="postList"
tooltip-effect="dark"
style="width: 100%"
fit
:pagination="pagination"
@selection-change="handleSelectionChange" >
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
label="ID"
width="100"
prop="id">
</el-table-column>
<el-table-column
label="标题"
width="450"
prop="title">
</el-table-column>
<el-table-column
label="是否置顶"
width="100"
prop="isTop">
</el-table-column>
<el-table-column
label="热度"
width="100"
prop="viewsCount">
</el-table-column>
<el-table-column
label="发布时间"
width="200"
prop="pubTime">
</el-table-column>
<el-table-column
label="操作"
>
<template #default="scope">
<el-button size="mini" type="danger" @click="deleteItem(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pagination.currentPage"
:page-sizes="[10, 20, 30, 40]"
:page-size="pagination.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total">
</el-pagination>
</div>
</div>
</div>
</template>

<style scoped>
.pagination-container {
margin-top: 20px;
text-align: center;
}
</style>

<script>
import {getBlogList,getBlogCategory} from '@/api'
export default {
data() {
return {
// 博客文章列表数据
postList:[],
// 筛选博客的参数
queryParam:{
words:"",
cateid:"",
tag:"",
search:"",
page:1,
size:10
},
// 分页
pagination: {
currentPage: 1, // 当前页
pageSize: 10, // 每页显示条数
total: 0, // 总条数
layout: 'total,sizes,prev, pager, next, jumper', // 分页布局
},
// 博客分类
blogCategorys:[],
// 当前选中的博客分类
selectCategory:"",
// 当前选中的博客文章
multipleSelection:[]
}
},
mounted () {
this.getBlogList();
this.getBlogCategory();
},
// 路由更新时刷新数据
beforeRouteUpdate (to) {
this.getBlogList();
this.getBlogCategory();
},
methods : {
// 获取博客文章列表数据
getBlogList() {
getBlogList(this.queryParam).then(res => {
this.postList = res.data.items
this.pagination.total = res.data.total
this.pagination.currentPage= res.data.page
console.log(res.data)
}).catch(err => {
console.log(err)
})
},
// 获取博客分类数据
getBlogCategory() {
getBlogCategory().then(res => {
this.blogCategorys = res.data
console.log(res)
}).catch(err => {
console.log(err)
})
},
// 改变分页大小
handleSizeChange(val) {
this.pagination.pageSize = val;
this.queryParam.size = val;
this.getBlogList();
},
// 跳到当前页
handleCurrentChange(val) {
this.pagination.currentPage = val;
this.queryParam.page = val;
this.getBlogList();
},
// 切换Tab 刷新数据
handleClick(tab) {
this.queryParam.cateid = tab.props.name
this.getBlogList();
},
// 清空筛选项
clear() {
this.queryParam.words=""
this.getBlogList();
},

}
}
</script>

五、效果

elementplus表格
表格展示及数据分页是前端开发常用的功能,通过vue3+elementplus能够快速是实现对数据的展示及分页。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

vue3+vite配置环境变量实现开发、测试、生产的区分

发表于 2024-08-25 | 更新于: 2025-04-08 | 分类于 技术 | | 阅读次数:
字数统计: 973 | 阅读时长 ≈ 3

在vue的实际项目中都要经过开发、测试、然后上生产的阶段,在开发、测试的过程中往往会要频繁的切换开发、测试、生产等不同的环境。每个环境的配置有可能不一样,本文介绍如何通过vue3+vite配置环境变量实现开发、测试、生产灵活便捷的切换。

一、为什么需要区分 (dev)、测试 (test) 和生产 (prod) 环境

做过大型项目开发的都知道,每个项目都会要经历开发、测试、再到生产上线,一般在开发时候最常用到(development)开发环境、(production)生产环境、(test)测试环境。每个环境的配置可能都不太一样。

  • 开发环境:为开发人员提供一个安全的地方来进行编码和调试,不会影响到其他环境,一般来说开发人员在本地机器上运行和测试应用程序。
  • 测试环境:用于测试,模拟生产环境,确保新功能在部署前能够正常工作,并且不会影响现有功能。
  • 生产环境:是面向用户的最终环境,任何更改都必须经过严格的测试才能部署到这里,通常具有优化和最少的日志记录。

区分开发 (dev)、测试 (test) 和生产 (prod) 环境是软件开发中的一个最佳实践。不同的环境通常有不同的资源配置。典型的如vue所调用的后台接口数据,在开发平台可能是本地服务提供的接口、用于自动化测试可能是mock提供的数据、生产应该是正式环境提供的真实接口。

二、vue3的项目如何通过配置方式区分不同的环境

vue3的项目可以通过vite的环境变量配置来进行不同环境的配置,可以参考vite的官方文档《环境变量和模式》
接下来,我们以一个实例来介绍在vue3的项目如何通过vite配置方式区分不同的环境。

1、创建不同环境的.env文件

在vue3根目录下创建三个文件分别为.env.develoment、.env.test、.env.production
创建的文件需要.env开头

env文件

2、在不同的.env文件中配置相应的环境变量

1).env.develoment

1
2
3
NODE_ENV='development'
# API URL
VITE_APP_API_URL='http://localhost:8000'

2).env.test

1
2
3
NODE_ENV='test'
# API URL
VITE_APP_API_URL=''

3).env.production

1
2
3
NODE_ENV='production'
# API URL
VITE_APP_API_URL='http://iblog.ishareread.com'

这里我们主要通过VITE_APP_API_URL变量来区分不同的环境调用不同的接口,在开发环境调用本地接口http://localhost:8000 ,在测试环境用mock接口,在生产环境调用真实接口。

3、在项目中使用环境变量

使用import.meta.env.VITE_APP_API_URL在axios请求中使用环境变量的配置来调用不同的接口。

1
2
3
4
5
6
7
8
import axios from 'axios'
const api_rul = import.meta.env.VITE_APP_API_URL
// create an axios instance
const service = axios.create({
baseURL: api_rul,
timeout: 5000 // request timeout
})
export default service

查看调用的哪些环境变量,可以在在main.js打印console.log('环境变量:', import.meta.env);看一下
main.js

1
2
3
4
5
6
7
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'

console.log('环境变量:', import.meta.env);

createApp(App).mount('#app')

4、在package.json中定义运行项目的脚本命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"name": "mocktest",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"test": "vite --mode test",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.7.5",
"vue": "^3.4.29"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.5",
"mockjs": "^1.1.0",
"vite": "^5.3.1",
"vite-plugin-mock": "^3.0.2"
}
}

package.json

三、运行效果

开发环境运行npm run dev

npm run dev

测试环境运行npm run test

npm run dev

可以看出通过运行不同的命令通过环境变量区分了不同的运行环境,避免了不同环境去改代码去适配不同的环境。


博客地址:http://xiejava.ishareread.com/


“fullbug”微信公众号

关注微信公众号,一起学习、成长!

12…20>
XieJava

XieJava

200 日志
11 分类
25 标签
RSS
GitHub
友情链接
  • 爱分享读书
  • CSDN
  • 豆瓣
© 2025 XieJava | Site words total count: 415.3k

主题 — NexT.Muse
0%