"上传数据怎么保证安全"这个问题,不能只回答"用加密"。加密只是手段之一,真正要保护的是传输过程、数据内容、调用身份、请求完整性和重放风险。
一句话概括:普通业务优先使用 HTTPS 保护传输通道;敏感字段可以额外加密;大数据适合对称加密,小数据和密钥交换适合非对称加密;接口还要配合签名、时间戳、随机数和权限校验。
先分清要防什么
上传数据安全通常要防这几类问题:
| 风险 | 说明 | 常见手段 |
|---|---|---|
| 窃听 | 数据在网络中被看到 | HTTPS、字段加密 |
| 篡改 | 请求内容被改掉 | 签名、摘要 |
| 冒充 | 非法客户端伪造请求 | Token、证书、AK/SK |
| 重放 | 把旧请求重复发送 | 时间戳、nonce、幂等 |
| 泄漏 | 服务端存储不当 | 脱敏、加密存储、权限控制 |
#mermaid-svg-WC4vCJTH00KhBbvS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-WC4vCJTH00KhBbvS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-WC4vCJTH00KhBbvS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-WC4vCJTH00KhBbvS .error-icon{fill:#552222;}#mermaid-svg-WC4vCJTH00KhBbvS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-WC4vCJTH00KhBbvS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-WC4vCJTH00KhBbvS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-WC4vCJTH00KhBbvS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-WC4vCJTH00KhBbvS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-WC4vCJTH00KhBbvS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-WC4vCJTH00KhBbvS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-WC4vCJTH00KhBbvS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-WC4vCJTH00KhBbvS .marker.cross{stroke:#333333;}#mermaid-svg-WC4vCJTH00KhBbvS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-WC4vCJTH00KhBbvS p{margin:0;}#mermaid-svg-WC4vCJTH00KhBbvS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-WC4vCJTH00KhBbvS .cluster-label text{fill:#333;}#mermaid-svg-WC4vCJTH00KhBbvS .cluster-label span{color:#333;}#mermaid-svg-WC4vCJTH00KhBbvS .cluster-label span p{background-color:transparent;}#mermaid-svg-WC4vCJTH00KhBbvS .label text,#mermaid-svg-WC4vCJTH00KhBbvS span{fill:#333;color:#333;}#mermaid-svg-WC4vCJTH00KhBbvS .node rect,#mermaid-svg-WC4vCJTH00KhBbvS .node circle,#mermaid-svg-WC4vCJTH00KhBbvS .node ellipse,#mermaid-svg-WC4vCJTH00KhBbvS .node polygon,#mermaid-svg-WC4vCJTH00KhBbvS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-WC4vCJTH00KhBbvS .rough-node .label text,#mermaid-svg-WC4vCJTH00KhBbvS .node .label text,#mermaid-svg-WC4vCJTH00KhBbvS .image-shape .label,#mermaid-svg-WC4vCJTH00KhBbvS .icon-shape .label{text-anchor:middle;}#mermaid-svg-WC4vCJTH00KhBbvS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-WC4vCJTH00KhBbvS .rough-node .label,#mermaid-svg-WC4vCJTH00KhBbvS .node .label,#mermaid-svg-WC4vCJTH00KhBbvS .image-shape .label,#mermaid-svg-WC4vCJTH00KhBbvS .icon-shape .label{text-align:center;}#mermaid-svg-WC4vCJTH00KhBbvS .node.clickable{cursor:pointer;}#mermaid-svg-WC4vCJTH00KhBbvS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-WC4vCJTH00KhBbvS .arrowheadPath{fill:#333333;}#mermaid-svg-WC4vCJTH00KhBbvS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-WC4vCJTH00KhBbvS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-WC4vCJTH00KhBbvS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WC4vCJTH00KhBbvS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-WC4vCJTH00KhBbvS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WC4vCJTH00KhBbvS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-WC4vCJTH00KhBbvS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-WC4vCJTH00KhBbvS .cluster text{fill:#333;}#mermaid-svg-WC4vCJTH00KhBbvS .cluster span{color:#333;}#mermaid-svg-WC4vCJTH00KhBbvS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-WC4vCJTH00KhBbvS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-WC4vCJTH00KhBbvS rect.text{fill:none;stroke-width:0;}#mermaid-svg-WC4vCJTH00KhBbvS .icon-shape,#mermaid-svg-WC4vCJTH00KhBbvS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-WC4vCJTH00KhBbvS .icon-shape p,#mermaid-svg-WC4vCJTH00KhBbvS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-WC4vCJTH00KhBbvS .icon-shape .label rect,#mermaid-svg-WC4vCJTH00KhBbvS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-WC4vCJTH00KhBbvS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-WC4vCJTH00KhBbvS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-WC4vCJTH00KhBbvS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 上传请求
传输安全
身份认证
完整性校验
重放防护
存储保护
如果只说"前端用公钥加密,后端用私钥解密",其实只覆盖了其中一小部分。
HTTPS 是基础
很多敏感数据上传场景,第一层保护应该是 HTTPS。
HTTPS 通过 TLS 建立加密通道,可以保护传输过程中的机密性和完整性,避免明文数据在网络链路上被直接截获。
"服务端" "客户端" "服务端" "客户端" #mermaid-svg-CZOJqlYfe9nsgGRU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CZOJqlYfe9nsgGRU .error-icon{fill:#552222;}#mermaid-svg-CZOJqlYfe9nsgGRU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CZOJqlYfe9nsgGRU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CZOJqlYfe9nsgGRU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CZOJqlYfe9nsgGRU .marker.cross{stroke:#333333;}#mermaid-svg-CZOJqlYfe9nsgGRU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CZOJqlYfe9nsgGRU p{margin:0;}#mermaid-svg-CZOJqlYfe9nsgGRU .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-CZOJqlYfe9nsgGRU text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-CZOJqlYfe9nsgGRU .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-CZOJqlYfe9nsgGRU .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-CZOJqlYfe9nsgGRU .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-CZOJqlYfe9nsgGRU .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-CZOJqlYfe9nsgGRU #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-CZOJqlYfe9nsgGRU .sequenceNumber{fill:white;}#mermaid-svg-CZOJqlYfe9nsgGRU #sequencenumber{fill:#333;}#mermaid-svg-CZOJqlYfe9nsgGRU #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-CZOJqlYfe9nsgGRU .messageText{fill:#333;stroke:none;}#mermaid-svg-CZOJqlYfe9nsgGRU .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-CZOJqlYfe9nsgGRU .labelText,#mermaid-svg-CZOJqlYfe9nsgGRU .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-CZOJqlYfe9nsgGRU .loopText,#mermaid-svg-CZOJqlYfe9nsgGRU .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-CZOJqlYfe9nsgGRU .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-CZOJqlYfe9nsgGRU .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-CZOJqlYfe9nsgGRU .noteText,#mermaid-svg-CZOJqlYfe9nsgGRU .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-CZOJqlYfe9nsgGRU .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-CZOJqlYfe9nsgGRU .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-CZOJqlYfe9nsgGRU .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-CZOJqlYfe9nsgGRU .actorPopupMenu{position:absolute;}#mermaid-svg-CZOJqlYfe9nsgGRU .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-CZOJqlYfe9nsgGRU .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-CZOJqlYfe9nsgGRU .actor-man circle,#mermaid-svg-CZOJqlYfe9nsgGRU line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-CZOJqlYfe9nsgGRU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "建立 TLS 连接""返回证书""校验证书""协商会话密钥""通过加密通道传输数据"
所以回答上传安全时,建议先说:
接口必须走 HTTPS,不能让账号、密码、身份证、支付信息等敏感数据明文传输。
然后再说是否需要业务层额外加密。
对称加密
对称加密指加密和解密使用同一把密钥。
#mermaid-svg-3uw4fcL84dDJId2l{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3uw4fcL84dDJId2l .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3uw4fcL84dDJId2l .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3uw4fcL84dDJId2l .error-icon{fill:#552222;}#mermaid-svg-3uw4fcL84dDJId2l .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3uw4fcL84dDJId2l .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3uw4fcL84dDJId2l .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3uw4fcL84dDJId2l .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3uw4fcL84dDJId2l .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3uw4fcL84dDJId2l .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3uw4fcL84dDJId2l .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3uw4fcL84dDJId2l .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3uw4fcL84dDJId2l .marker.cross{stroke:#333333;}#mermaid-svg-3uw4fcL84dDJId2l svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3uw4fcL84dDJId2l p{margin:0;}#mermaid-svg-3uw4fcL84dDJId2l .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3uw4fcL84dDJId2l .cluster-label text{fill:#333;}#mermaid-svg-3uw4fcL84dDJId2l .cluster-label span{color:#333;}#mermaid-svg-3uw4fcL84dDJId2l .cluster-label span p{background-color:transparent;}#mermaid-svg-3uw4fcL84dDJId2l .label text,#mermaid-svg-3uw4fcL84dDJId2l span{fill:#333;color:#333;}#mermaid-svg-3uw4fcL84dDJId2l .node rect,#mermaid-svg-3uw4fcL84dDJId2l .node circle,#mermaid-svg-3uw4fcL84dDJId2l .node ellipse,#mermaid-svg-3uw4fcL84dDJId2l .node polygon,#mermaid-svg-3uw4fcL84dDJId2l .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3uw4fcL84dDJId2l .rough-node .label text,#mermaid-svg-3uw4fcL84dDJId2l .node .label text,#mermaid-svg-3uw4fcL84dDJId2l .image-shape .label,#mermaid-svg-3uw4fcL84dDJId2l .icon-shape .label{text-anchor:middle;}#mermaid-svg-3uw4fcL84dDJId2l .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3uw4fcL84dDJId2l .rough-node .label,#mermaid-svg-3uw4fcL84dDJId2l .node .label,#mermaid-svg-3uw4fcL84dDJId2l .image-shape .label,#mermaid-svg-3uw4fcL84dDJId2l .icon-shape .label{text-align:center;}#mermaid-svg-3uw4fcL84dDJId2l .node.clickable{cursor:pointer;}#mermaid-svg-3uw4fcL84dDJId2l .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3uw4fcL84dDJId2l .arrowheadPath{fill:#333333;}#mermaid-svg-3uw4fcL84dDJId2l .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3uw4fcL84dDJId2l .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3uw4fcL84dDJId2l .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3uw4fcL84dDJId2l .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3uw4fcL84dDJId2l .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3uw4fcL84dDJId2l .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3uw4fcL84dDJId2l .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3uw4fcL84dDJId2l .cluster text{fill:#333;}#mermaid-svg-3uw4fcL84dDJId2l .cluster span{color:#333;}#mermaid-svg-3uw4fcL84dDJId2l div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3uw4fcL84dDJId2l .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3uw4fcL84dDJId2l rect.text{fill:none;stroke-width:0;}#mermaid-svg-3uw4fcL84dDJId2l .icon-shape,#mermaid-svg-3uw4fcL84dDJId2l .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3uw4fcL84dDJId2l .icon-shape p,#mermaid-svg-3uw4fcL84dDJId2l .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3uw4fcL84dDJId2l .icon-shape .label rect,#mermaid-svg-3uw4fcL84dDJId2l .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3uw4fcL84dDJId2l .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3uw4fcL84dDJId2l .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3uw4fcL84dDJId2l :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 原始数据
使用密钥加密
密文
使用同一密钥解密
原始数据
优点是速度快,适合大文件、大报文、批量数据加密。
缺点是密钥管理困难。只要密钥泄漏,攻击者就能加密和解密数据。
| 特点 | 说明 |
|---|---|
| 加密速度 | 快 |
| 适合数据量 | 大 |
| 关键风险 | 密钥分发和保管 |
| 常见算法 | AES |
对称加密适合这样的场景:
- 文件上传前先用 AES 加密。
- 服务端拿到密文后用同一密钥解密。
- 密钥通过更安全的方式协商或下发。
PPT 里常会说"对称加密相对不太安全,不要保存敏感信息",这句话容易让人误解。更准确的说法是:对称加密本身可以保护敏感数据,但安全性高度依赖密钥管理。 如果密钥和密文放在同一个系统里、密钥硬编码在代码里、长期不轮换,那再强的算法也救不了。
注意,不要把密钥硬编码在前端代码里。前端代码天然容易被逆向,硬编码密钥等于把钥匙贴在门上。
非对称加密
非对称加密有一对密钥:公钥和私钥。
常见用法是公钥加密,私钥解密。也可以反过来用私钥签名、公钥验签,但那解决的是身份和完整性,不是保密。
#mermaid-svg-gnazaL5QKuJYgo0T{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gnazaL5QKuJYgo0T .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gnazaL5QKuJYgo0T .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gnazaL5QKuJYgo0T .error-icon{fill:#552222;}#mermaid-svg-gnazaL5QKuJYgo0T .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gnazaL5QKuJYgo0T .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gnazaL5QKuJYgo0T .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gnazaL5QKuJYgo0T .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gnazaL5QKuJYgo0T .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gnazaL5QKuJYgo0T .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gnazaL5QKuJYgo0T .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gnazaL5QKuJYgo0T .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gnazaL5QKuJYgo0T .marker.cross{stroke:#333333;}#mermaid-svg-gnazaL5QKuJYgo0T svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gnazaL5QKuJYgo0T p{margin:0;}#mermaid-svg-gnazaL5QKuJYgo0T .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-gnazaL5QKuJYgo0T .cluster-label text{fill:#333;}#mermaid-svg-gnazaL5QKuJYgo0T .cluster-label span{color:#333;}#mermaid-svg-gnazaL5QKuJYgo0T .cluster-label span p{background-color:transparent;}#mermaid-svg-gnazaL5QKuJYgo0T .label text,#mermaid-svg-gnazaL5QKuJYgo0T span{fill:#333;color:#333;}#mermaid-svg-gnazaL5QKuJYgo0T .node rect,#mermaid-svg-gnazaL5QKuJYgo0T .node circle,#mermaid-svg-gnazaL5QKuJYgo0T .node ellipse,#mermaid-svg-gnazaL5QKuJYgo0T .node polygon,#mermaid-svg-gnazaL5QKuJYgo0T .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-gnazaL5QKuJYgo0T .rough-node .label text,#mermaid-svg-gnazaL5QKuJYgo0T .node .label text,#mermaid-svg-gnazaL5QKuJYgo0T .image-shape .label,#mermaid-svg-gnazaL5QKuJYgo0T .icon-shape .label{text-anchor:middle;}#mermaid-svg-gnazaL5QKuJYgo0T .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-gnazaL5QKuJYgo0T .rough-node .label,#mermaid-svg-gnazaL5QKuJYgo0T .node .label,#mermaid-svg-gnazaL5QKuJYgo0T .image-shape .label,#mermaid-svg-gnazaL5QKuJYgo0T .icon-shape .label{text-align:center;}#mermaid-svg-gnazaL5QKuJYgo0T .node.clickable{cursor:pointer;}#mermaid-svg-gnazaL5QKuJYgo0T .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-gnazaL5QKuJYgo0T .arrowheadPath{fill:#333333;}#mermaid-svg-gnazaL5QKuJYgo0T .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-gnazaL5QKuJYgo0T .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-gnazaL5QKuJYgo0T .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gnazaL5QKuJYgo0T .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-gnazaL5QKuJYgo0T .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gnazaL5QKuJYgo0T .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-gnazaL5QKuJYgo0T .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-gnazaL5QKuJYgo0T .cluster text{fill:#333;}#mermaid-svg-gnazaL5QKuJYgo0T .cluster span{color:#333;}#mermaid-svg-gnazaL5QKuJYgo0T div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-gnazaL5QKuJYgo0T .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-gnazaL5QKuJYgo0T rect.text{fill:none;stroke-width:0;}#mermaid-svg-gnazaL5QKuJYgo0T .icon-shape,#mermaid-svg-gnazaL5QKuJYgo0T .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-gnazaL5QKuJYgo0T .icon-shape p,#mermaid-svg-gnazaL5QKuJYgo0T .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-gnazaL5QKuJYgo0T .icon-shape .label rect,#mermaid-svg-gnazaL5QKuJYgo0T .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-gnazaL5QKuJYgo0T .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-gnazaL5QKuJYgo0T .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-gnazaL5QKuJYgo0T :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 客户端
使用公钥加密
密文
服务端使用私钥解密
原始数据
公钥可以公开,私钥必须由服务端安全保存。
| 特点 | 说明 |
|---|---|
| 安全性 | 密钥分发更安全 |
| 性能 | 比对称加密慢 |
| 适合数据量 | 小 |
| 常见算法 | RSA、ECC |
非对称加密适合加密少量敏感字段,或者用于交换对称密钥。大文件不适合全部用非对称加密,性能会很差。
混合加密更常见
真实系统里,经常是对称加密和非对称加密结合。
"服务端" "客户端" "服务端" "客户端" #mermaid-svg-YfR8fuE0PT31Dcvp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YfR8fuE0PT31Dcvp .error-icon{fill:#552222;}#mermaid-svg-YfR8fuE0PT31Dcvp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YfR8fuE0PT31Dcvp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YfR8fuE0PT31Dcvp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YfR8fuE0PT31Dcvp .marker.cross{stroke:#333333;}#mermaid-svg-YfR8fuE0PT31Dcvp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YfR8fuE0PT31Dcvp p{margin:0;}#mermaid-svg-YfR8fuE0PT31Dcvp .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-YfR8fuE0PT31Dcvp text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-YfR8fuE0PT31Dcvp .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-YfR8fuE0PT31Dcvp .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-YfR8fuE0PT31Dcvp .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-YfR8fuE0PT31Dcvp .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-YfR8fuE0PT31Dcvp #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-YfR8fuE0PT31Dcvp .sequenceNumber{fill:white;}#mermaid-svg-YfR8fuE0PT31Dcvp #sequencenumber{fill:#333;}#mermaid-svg-YfR8fuE0PT31Dcvp #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-YfR8fuE0PT31Dcvp .messageText{fill:#333;stroke:none;}#mermaid-svg-YfR8fuE0PT31Dcvp .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-YfR8fuE0PT31Dcvp .labelText,#mermaid-svg-YfR8fuE0PT31Dcvp .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-YfR8fuE0PT31Dcvp .loopText,#mermaid-svg-YfR8fuE0PT31Dcvp .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-YfR8fuE0PT31Dcvp .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-YfR8fuE0PT31Dcvp .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-YfR8fuE0PT31Dcvp .noteText,#mermaid-svg-YfR8fuE0PT31Dcvp .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-YfR8fuE0PT31Dcvp .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-YfR8fuE0PT31Dcvp .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-YfR8fuE0PT31Dcvp .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-YfR8fuE0PT31Dcvp .actorPopupMenu{position:absolute;}#mermaid-svg-YfR8fuE0PT31Dcvp .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-YfR8fuE0PT31Dcvp .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-YfR8fuE0PT31Dcvp .actor-man circle,#mermaid-svg-YfR8fuE0PT31Dcvp line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-YfR8fuE0PT31Dcvp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} "生成随机 AES 密钥""用 AES 加密大数据""用服务端公钥加密 AES 密钥""上传加密数据和加密后的 AES 密钥""用私钥解出 AES 密钥""用 AES 解密业务数据"
这样既利用了对称加密的性能,也解决了对称密钥传输的问题。
如果已经使用标准 HTTPS,其实 TLS 握手内部也有类似"非对称能力协商密钥、对称密钥加密数据"的思路。业务层再做混合加密,一般是为了满足更高的合规要求、端到端字段保护,或者防止日志、代理、内部链路误暴露敏感字段,而不是替代 HTTPS。
签名解决什么问题
加密解决"别人看不看得到",签名解决"数据有没有被改过,以及是谁发的"。
常见签名流程:
#mermaid-svg-jv1KXgaQ3VWhPWuh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jv1KXgaQ3VWhPWuh .error-icon{fill:#552222;}#mermaid-svg-jv1KXgaQ3VWhPWuh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jv1KXgaQ3VWhPWuh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .marker.cross{stroke:#333333;}#mermaid-svg-jv1KXgaQ3VWhPWuh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jv1KXgaQ3VWhPWuh p{margin:0;}#mermaid-svg-jv1KXgaQ3VWhPWuh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .cluster-label text{fill:#333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .cluster-label span{color:#333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .cluster-label span p{background-color:transparent;}#mermaid-svg-jv1KXgaQ3VWhPWuh .label text,#mermaid-svg-jv1KXgaQ3VWhPWuh span{fill:#333;color:#333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .node rect,#mermaid-svg-jv1KXgaQ3VWhPWuh .node circle,#mermaid-svg-jv1KXgaQ3VWhPWuh .node ellipse,#mermaid-svg-jv1KXgaQ3VWhPWuh .node polygon,#mermaid-svg-jv1KXgaQ3VWhPWuh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jv1KXgaQ3VWhPWuh .rough-node .label text,#mermaid-svg-jv1KXgaQ3VWhPWuh .node .label text,#mermaid-svg-jv1KXgaQ3VWhPWuh .image-shape .label,#mermaid-svg-jv1KXgaQ3VWhPWuh .icon-shape .label{text-anchor:middle;}#mermaid-svg-jv1KXgaQ3VWhPWuh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jv1KXgaQ3VWhPWuh .rough-node .label,#mermaid-svg-jv1KXgaQ3VWhPWuh .node .label,#mermaid-svg-jv1KXgaQ3VWhPWuh .image-shape .label,#mermaid-svg-jv1KXgaQ3VWhPWuh .icon-shape .label{text-align:center;}#mermaid-svg-jv1KXgaQ3VWhPWuh .node.clickable{cursor:pointer;}#mermaid-svg-jv1KXgaQ3VWhPWuh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .arrowheadPath{fill:#333333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jv1KXgaQ3VWhPWuh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jv1KXgaQ3VWhPWuh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jv1KXgaQ3VWhPWuh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jv1KXgaQ3VWhPWuh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jv1KXgaQ3VWhPWuh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jv1KXgaQ3VWhPWuh .cluster text{fill:#333;}#mermaid-svg-jv1KXgaQ3VWhPWuh .cluster span{color:#333;}#mermaid-svg-jv1KXgaQ3VWhPWuh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jv1KXgaQ3VWhPWuh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jv1KXgaQ3VWhPWuh rect.text{fill:none;stroke-width:0;}#mermaid-svg-jv1KXgaQ3VWhPWuh .icon-shape,#mermaid-svg-jv1KXgaQ3VWhPWuh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jv1KXgaQ3VWhPWuh .icon-shape p,#mermaid-svg-jv1KXgaQ3VWhPWuh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jv1KXgaQ3VWhPWuh .icon-shape .label rect,#mermaid-svg-jv1KXgaQ3VWhPWuh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jv1KXgaQ3VWhPWuh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jv1KXgaQ3VWhPWuh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jv1KXgaQ3VWhPWuh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
请求参数
按规则排序
拼接时间戳和 nonce
使用密钥生成签名
请求携带签名
服务端重新计算签名
签名是否一致
请求可信
拒绝请求
签名常见字段:
| 字段 | 作用 |
|---|---|
appId |
标识调用方 |
timestamp |
判断请求时间 |
nonce |
随机数,防止重放 |
bodyHash |
请求体摘要 |
sign |
签名结果 |
签名算法常见两类:一种是共享密钥生成的 HMAC,比如 HMAC-SHA256,适合 AK/SK 这类服务端到服务端接口;另一种是私钥签名、公钥验签,比如 SHA256withRSA 或 ECDSA,适合调用方持有私钥、服务端只保存公钥的场景。不要自己发明签名算法,字段规范、排序规则、编码规则必须固定,否则调用方和服务端很容易算出不同签名。
重放攻击指攻击者不理解请求内容,也不需要解密,只是把一段旧请求再次发送。如果没有时间戳和 nonce,服务端可能会重复处理。
重放防护一般这样做:
- 请求时间戳不能和服务器时间相差太大。
- nonce 在有效期内只能使用一次。
- 关键业务再加幂等号,避免重复下单或重复支付。
密码不要"加密存储"
还有一个非常容易误答的点:用户密码不要用可逆加密存储。
密码存储应该使用慢哈希算法,并加盐,例如 Argon2id、BCrypt、PBKDF2。OWASP 的密码存储建议也把这类专门面向密码的慢哈希算法作为主线。这样即使数据库泄漏,也不能直接解密出原密码,只能离线暴力猜测,而慢哈希的目的就是提高猜测成本。
#mermaid-svg-VBDUm8ci4prEDzA1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VBDUm8ci4prEDzA1 .error-icon{fill:#552222;}#mermaid-svg-VBDUm8ci4prEDzA1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VBDUm8ci4prEDzA1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VBDUm8ci4prEDzA1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VBDUm8ci4prEDzA1 .marker.cross{stroke:#333333;}#mermaid-svg-VBDUm8ci4prEDzA1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VBDUm8ci4prEDzA1 p{margin:0;}#mermaid-svg-VBDUm8ci4prEDzA1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VBDUm8ci4prEDzA1 .cluster-label text{fill:#333;}#mermaid-svg-VBDUm8ci4prEDzA1 .cluster-label span{color:#333;}#mermaid-svg-VBDUm8ci4prEDzA1 .cluster-label span p{background-color:transparent;}#mermaid-svg-VBDUm8ci4prEDzA1 .label text,#mermaid-svg-VBDUm8ci4prEDzA1 span{fill:#333;color:#333;}#mermaid-svg-VBDUm8ci4prEDzA1 .node rect,#mermaid-svg-VBDUm8ci4prEDzA1 .node circle,#mermaid-svg-VBDUm8ci4prEDzA1 .node ellipse,#mermaid-svg-VBDUm8ci4prEDzA1 .node polygon,#mermaid-svg-VBDUm8ci4prEDzA1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VBDUm8ci4prEDzA1 .rough-node .label text,#mermaid-svg-VBDUm8ci4prEDzA1 .node .label text,#mermaid-svg-VBDUm8ci4prEDzA1 .image-shape .label,#mermaid-svg-VBDUm8ci4prEDzA1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-VBDUm8ci4prEDzA1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VBDUm8ci4prEDzA1 .rough-node .label,#mermaid-svg-VBDUm8ci4prEDzA1 .node .label,#mermaid-svg-VBDUm8ci4prEDzA1 .image-shape .label,#mermaid-svg-VBDUm8ci4prEDzA1 .icon-shape .label{text-align:center;}#mermaid-svg-VBDUm8ci4prEDzA1 .node.clickable{cursor:pointer;}#mermaid-svg-VBDUm8ci4prEDzA1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VBDUm8ci4prEDzA1 .arrowheadPath{fill:#333333;}#mermaid-svg-VBDUm8ci4prEDzA1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VBDUm8ci4prEDzA1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VBDUm8ci4prEDzA1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VBDUm8ci4prEDzA1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VBDUm8ci4prEDzA1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VBDUm8ci4prEDzA1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VBDUm8ci4prEDzA1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VBDUm8ci4prEDzA1 .cluster text{fill:#333;}#mermaid-svg-VBDUm8ci4prEDzA1 .cluster span{color:#333;}#mermaid-svg-VBDUm8ci4prEDzA1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VBDUm8ci4prEDzA1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VBDUm8ci4prEDzA1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-VBDUm8ci4prEDzA1 .icon-shape,#mermaid-svg-VBDUm8ci4prEDzA1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VBDUm8ci4prEDzA1 .icon-shape p,#mermaid-svg-VBDUm8ci4prEDzA1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VBDUm8ci4prEDzA1 .icon-shape .label rect,#mermaid-svg-VBDUm8ci4prEDzA1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VBDUm8ci4prEDzA1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VBDUm8ci4prEDzA1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VBDUm8ci4prEDzA1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户密码
随机盐
慢哈希算法
密码哈希
存入数据库
登录时不是解密密码,而是把用户输入密码用同样规则计算哈希,再和数据库里的哈希比较。
#mermaid-svg-LDaAJdHPm6yIn31g{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LDaAJdHPm6yIn31g .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LDaAJdHPm6yIn31g .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LDaAJdHPm6yIn31g .error-icon{fill:#552222;}#mermaid-svg-LDaAJdHPm6yIn31g .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LDaAJdHPm6yIn31g .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LDaAJdHPm6yIn31g .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LDaAJdHPm6yIn31g .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LDaAJdHPm6yIn31g .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LDaAJdHPm6yIn31g .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LDaAJdHPm6yIn31g .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LDaAJdHPm6yIn31g .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LDaAJdHPm6yIn31g .marker.cross{stroke:#333333;}#mermaid-svg-LDaAJdHPm6yIn31g svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LDaAJdHPm6yIn31g p{margin:0;}#mermaid-svg-LDaAJdHPm6yIn31g .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LDaAJdHPm6yIn31g .cluster-label text{fill:#333;}#mermaid-svg-LDaAJdHPm6yIn31g .cluster-label span{color:#333;}#mermaid-svg-LDaAJdHPm6yIn31g .cluster-label span p{background-color:transparent;}#mermaid-svg-LDaAJdHPm6yIn31g .label text,#mermaid-svg-LDaAJdHPm6yIn31g span{fill:#333;color:#333;}#mermaid-svg-LDaAJdHPm6yIn31g .node rect,#mermaid-svg-LDaAJdHPm6yIn31g .node circle,#mermaid-svg-LDaAJdHPm6yIn31g .node ellipse,#mermaid-svg-LDaAJdHPm6yIn31g .node polygon,#mermaid-svg-LDaAJdHPm6yIn31g .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LDaAJdHPm6yIn31g .rough-node .label text,#mermaid-svg-LDaAJdHPm6yIn31g .node .label text,#mermaid-svg-LDaAJdHPm6yIn31g .image-shape .label,#mermaid-svg-LDaAJdHPm6yIn31g .icon-shape .label{text-anchor:middle;}#mermaid-svg-LDaAJdHPm6yIn31g .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LDaAJdHPm6yIn31g .rough-node .label,#mermaid-svg-LDaAJdHPm6yIn31g .node .label,#mermaid-svg-LDaAJdHPm6yIn31g .image-shape .label,#mermaid-svg-LDaAJdHPm6yIn31g .icon-shape .label{text-align:center;}#mermaid-svg-LDaAJdHPm6yIn31g .node.clickable{cursor:pointer;}#mermaid-svg-LDaAJdHPm6yIn31g .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LDaAJdHPm6yIn31g .arrowheadPath{fill:#333333;}#mermaid-svg-LDaAJdHPm6yIn31g .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LDaAJdHPm6yIn31g .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LDaAJdHPm6yIn31g .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LDaAJdHPm6yIn31g .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LDaAJdHPm6yIn31g .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LDaAJdHPm6yIn31g .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LDaAJdHPm6yIn31g .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LDaAJdHPm6yIn31g .cluster text{fill:#333;}#mermaid-svg-LDaAJdHPm6yIn31g .cluster span{color:#333;}#mermaid-svg-LDaAJdHPm6yIn31g div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LDaAJdHPm6yIn31g .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LDaAJdHPm6yIn31g rect.text{fill:none;stroke-width:0;}#mermaid-svg-LDaAJdHPm6yIn31g .icon-shape,#mermaid-svg-LDaAJdHPm6yIn31g .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LDaAJdHPm6yIn31g .icon-shape p,#mermaid-svg-LDaAJdHPm6yIn31g .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LDaAJdHPm6yIn31g .icon-shape .label rect,#mermaid-svg-LDaAJdHPm6yIn31g .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LDaAJdHPm6yIn31g .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LDaAJdHPm6yIn31g .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LDaAJdHPm6yIn31g :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
用户输入密码
结合盐计算哈希
是否等于数据库哈希
登录成功
登录失败
所以不要说"密码用 AES 加密保存"。AES 是可逆的,一旦密钥泄漏,全部密码都会暴露。密码校验只需要判断"用户输入是否和原密码一致",不需要拿回原文,这就是密码应该哈希而不是加密的根本原因。
面试怎么说
可以这样回答:
上传数据安全我会分层处理。第一,传输层必须走 HTTPS,避免敏感数据明文传输。第二,如果业务要求对字段做额外保护,可以对敏感字段加密。大文件或大报文适合用 AES 这类对称加密,速度快,但核心是密钥不能硬编码、不能和密文放在一起、要有轮换机制;少量敏感数据或密钥交换可以用 RSA、ECC 这类非对称加密。实际系统里也可以用混合加密,客户端生成随机 AES 密钥加密数据,再用服务端公钥加密 AES 密钥。第三,为了防篡改和防伪造,请求要做签名,签名里带时间戳、nonce 和请求体摘要,算法用 HMAC 或标准非对称签名,不自己造规则。第四,防重放要校验时间窗口,nonce 只能用一次,关键业务再做幂等。密码这类数据不能可逆加密保存,应该用 Argon2id、BCrypt、PBKDF2 这类加盐慢哈希。
小结
上传安全不能只记"对称加密快,非对称加密安全"。
更完整的思路是:
HTTPS 保通道,加密保内容,签名防篡改,时间戳和 nonce 防重放,后端权限和存储策略兜底。
这套回答既能覆盖普通上传,也能自然延伸到支付、开放接口和敏感数据传输。