【计算基础|网络06】HTTPS(上):加密体系与 RSA 握手

【计算基础|网络06】HTTPS(上):加密体系与 RSA 握手

打开浏览器访问银行、邮箱、支付页面,地址栏那把小绿锁到底在保护什么?为什么我们天天说"别用 HTTP 要用 HTTPS",但真被问到 HTTPS 到底解决了什么问题、握手过程里为什么要发三个随机数、RSA 密钥交换又为什么被 TLS 1.3 踢出去------多数人是说不清楚的。

这一篇不背八股,先把 HTTP 的裸奔问题讲透,再把支撑 HTTPS 的四块"砖头"------对称加密、非对称加密、哈希函数、数字签名------每一块都用 Python 代码跑一遍,让你亲眼看到密文长什么样、签名怎么验。然后顺藤摸瓜讲清楚证书链和 CA 信任体系,最后把 TLS 1.2 的 RSA 握手完整画出来。下篇再讲 ECDHE、TLS 1.3 和性能优化。

环境:macOS + Python 3.14 + OpenSSL 3.5.6,Python 侧用 cryptography 库(pip install cryptography)。所有命令均可在本机复现。


一、HTTP 到底哪里不安全

结论先给:HTTP 本身是一张明信片,谁都能看、谁都能改、寄给谁也不核对。它有三个根本性缺陷:

缺陷 后果 典型场景
明文传输 路由上任何一跳(运营商、公共 Wi-Fi、公司网关)都能看到全部内容 你在咖啡馆 Wi-Fi 登录邮箱,密码被旁边的人嗅探到
身份不验证 你无法确认对面那台服务器真的是 mail.google.com,还是中间人伪造的钓鱼站 公共 Wi-Fi 弹个"登录认证"页,其实在偷你的 Cookie
完整性不保护 中间人可以在传输过程中篡改内容,你和服务器都发现不了 网页里被注入广告 JS、下载链接被换成木马

🔴 这三件事不是"加密一下数据"就能同时解决的。光把数据加密,你仍然不知道对面是不是真服务器;光验证身份,内容仍可能被篡改。HTTPS 的设计目标就是同时解决这三个问题,它靠的不是某一个魔法算法,而是把下面四类工具拼起来用。


二、加密体系四大基石

这四个工具各自解决不同问题,缺一个都不行。先放一张总表,后面逐个拆开实测:

工具 解决什么 速度 密钥分发 典型算法
对称加密 内容机密性(加密后看不懂) 极快 难(双方要先共享密钥) AES、DES、3DES
非对称加密 安全地共享密钥 / 身份认证 慢 易(公钥随便公开) RSA、ECC
哈希函数 内容完整性(防篡改) 快 无密钥 MD5、SHA-1、SHA-256
数字签名 身份认证 + 完整性 中 公钥公开 RSA-PSS、ECDSA

2.1 对称加密:快,但密钥怎么送过去是个死结

对称加密的核心思想:加解密用同一把密钥。就像一个带锁的盒子,你和朋友各拿一把相同的钥匙,你放东西进去锁上寄给他,他用钥匙打开。

主流算法演进:DES(56 位,已破)→ 3DES(三倍 DES,慢且即将淘汰)→ AES(现在的事实标准,128/192/256 位密钥)。TLS 1.2 之后基本只用 AES。

⚠️ 对称加密的死结是密钥分发:你和朋友第一次通信,怎么把钥匙安全地交给他?当面给可以,跨网络给------钥匙本身又得加密,于是问题无限套娃。这就是为什么必须有非对称加密。

下面用 Python cryptography 库实测 AES-256-CBC 加解密(CBC 是 TLS 里最常用的分组模式之一):

python 复制代码
# aes_demo.py
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding

key = os.urandom(32)          # AES-256:密钥 32 字节 = 256 位
iv  = os.urandom(16)          # CBC 模式需要 16 字节初始向量
plaintext = "Hello HTTPS! 这是一段需要加密的敏感数据。".encode("utf-8")

# PKCS7 填充:明文长度必须是分组(16字节)的整数倍
padder = padding.PKCS7(128).padder()
padded = padder.update(plaintext) + padder.finalize()

# 加密
enc = Cipher(algorithms.AES(key), modes.CBC(iv)).encryptor()
ciphertext = enc.update(padded) + enc.finalize()

# 解密
dec = Cipher(algorithms.AES(key), modes.CBC(iv)).decryptor()
dec_padded = dec.update(ciphertext) + dec.finalize()
unpadder = padding.PKCS7(128).unpadder()
recovered = unpadder.update(dec_padded) + unpadder.finalize()

print(f"密文(hex): {ciphertext.hex()}")
print(f"解密还原: {recovered}")
print(f"还原一致: {recovered == plaintext}")

实测输出(密钥每次随机,你的输出会和这里不同):

text 复制代码
密文(hex): 09bdbc85a9ee938de9b7d85f47be6063e2157c1fb57b62221f9a95b45a867384dbe86bc46aefb576b5d71c718a52f2121d0afffcd32b9c040f80c4938ea7db42
解密还原: b'Hello HTTPS! \xe8\xbf\x99\xe6\x98\xaf...'
还原一致: True

⚠️ 三个新手必踩的坑:

  1. IV(初始向量)必须每次随机,且不需要保密。IV 不是密钥,它的作用是让相同明文每次加密出不同密文。IV 可以明文跟在密文前面发出去。
  2. CBC 模式本身不防篡改,只保证机密性。TLS 1.2 用 CBC 时还要额外拼 HMAC 做完整性校验;TLS 1.3 直接改用 AES-GCM(认证加密,一把搞定机密性+完整性)。
  3. AES 极快。在现代 CPU 上有 AES-NI 硬件指令集,加密一 MB 数据是微秒级,这就是为什么大批量应用数据要用对称加密。

2.2 非对称加密:公钥随便公开,私钥自己保管

非对称加密彻底换了个思路:每个人生成一对钥匙------公钥(public key)和私钥(private key)。公钥可以公开给全世界,私钥自己藏好。两种用法:

  • 公钥加密、私钥解密:用我的公钥加密,只有我的私钥能解开 → 解决"安全地把密钥送给我"的问题。
  • 私钥签名、公钥验证:用我的私钥签个名,任何人拿我的公钥都能验 → 解决"这东西确实是我发的"的问题。

主流算法:RSA (基于大整数分解难题,TLS 1.2 时代主力)和 ECC(椭圆曲线,更短的密钥达到同等安全,TLS 1.3 起全面转向 ECC)。

⚠️ 非对称加密极慢,RSA-2048 加密一次几毫秒,比 AES 慢几个数量级。所以它从不用来加密大块数据,只用来:① 加密一个小的"会话密钥";② 做数字签名。

实测 RSA-2048 公钥加密/私钥解密:

python 复制代码
# rsa_demo.py
import time
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes

# 生成 RSA-2048 密钥对(实际服务器证书里的公钥就是这么来的)
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()

secret = b"pre_master_secret_123456"   # 这就是 TLS 握手里要送的"预主密钥"

# 公钥加密:用服务器公钥把预主密钥加密
t0 = time.time()
enc_data = public_key.encrypt(
    secret,
    padding.OAEP(mgf=padding.MGF1(hashes.SHA256()),
                 algorithm=hashes.SHA256(), label=None))
print(f"RSA 加密耗时: {(time.time()-t0)*1000:.2f} ms")
print(f"密文长度: {len(enc_data)} 字节 (RSA-2048 固定 256 字节)")

# 私钥解密:只有服务器自己能解
t0 = time.time()
dec_data = private_key.decrypt(
    enc_data,
    padding.OAEP(mgf=padding.MGF1(hashes.SHA256()),
                 algorithm=hashes.SHA256(), label=None))
print(f"RSA 解密耗时: {(time.time()-t0)*1000:.2f} ms")
print(f"解密还原: {dec_data == secret}")

实测输出:

text 复制代码
生成 RSA-2048 密钥对耗时: 0.097s
RSA 加密耗时: 0.43 ms
密文长度: 256 字节 (RSA-2048 固定 256 字节)
RSA 解密耗时: 1.75 ms
解密还原: True

🔴 看两个关键数字:RSA 密文固定 256 字节(2048 位 = 256 字节),所以 RSA 一次只能加密很短的数据(OAEP 填充后明文上限大约 190 字节)。这就是为什么 TLS 里 RSA 只用来加密 48 字节的预主密钥,而不是直接加密 HTTP 请求。

2.3 哈希函数:单向、雪崩、定长

哈希函数把任意长度的数据压缩成固定长度的摘要(digest),三个性质:

  • 单向性:从摘要无法反推原文。
  • 抗碰撞:找两段不同数据算出相同摘要,计算上不可行。
  • 雪崩效应:原文改一个比特,摘要翻天覆地。
算法 摘要长度 现状
MD5 128 位(16 字节) ❌ 已被破解,可伪造碰撞,禁止用于安全
SHA-1 160 位(20 字节) ❌ 2017 年 Google 已做出实际碰撞,TLS 1.3 移除
SHA-256 256 位(32 字节) ✅ 现在的标准,TLS 1.2/1.3 默认

实测:

python 复制代码
# hash_demo.py
from cryptography.hazmat.primitives import hashes

msg = b"hello https"
for name in ["MD5", "SHA1", "SHA256"]:
    h = hashes.Hash(getattr(hashes, name)())
    h.update(msg)
    print(f"{name:8s} = {h.finalize().hex()}")

# 改一个字母,看雪崩效应
h1 = hashes.Hash(hashes.SHA256()); h1.update(b"hello https")
h2 = hashes.Hash(hashes.SHA256()); h2.update(b"hello httpS")  # s 大写
print(f"原文: {h1.finalize().hex()}")
print(f"改后: {h2.finalize().hex()}")

实测输出:

text 复制代码
MD5      = e9aded2a1b0dd6d497f079b71f504315
SHA1     = 2658f6e013c6d9f56f14310daca008d4018e7166
SHA256   = d151a4b5ca6a480026e716d49117d738dc7eac4b05dbb21123e4ae095c015d3d

原文 hello https : d151a4b5ca6a480026e716d49117d738dc7eac4b05dbb21123e4ae095c015d3d
改后 hello httpS : 7dab81e9ce47c25e90b65c816d6fc1041f88b74529571d667571fae25f9f9eaa

看,只把小写 s 改成大写 S,SHA-256 摘要从 d151... 变成 7dab...,完全不同。哈希不是加密(没有密钥、不能解密),它是"指纹"------你把文档的哈希值和别人对一对,就知道文档有没有被改过。

2.4 数字签名:私钥签名 + 公钥验签,把"身份"和"完整性"焊死

光有哈希只能验证完整性(两份东西是否一致),但谁来对这个哈希负责?数字签名就是解决这个:

  1. 发送方对文档算哈希,用自己的私钥对这个哈希加密 → 这就是签名。
  2. 接收方用发送方的公钥解密签名,得到原始哈希;再自己对收到的文档算哈希,两个一对比,一致就说明:① 文档确实由私钥持有者发出(身份);② 文档中途没被改过(完整性)。

实测 RSA-PSS 签名验签:

python 复制代码
# sign_demo.py
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes

private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()

doc = b"contract: pay 100 yuan to alice, order=20260922"

# 私钥签名(PSS 是 RSA 签名的现代填充方案)
signature = private_key.sign(
    doc,
    padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH),
    hashes.SHA256())
print(f"签名长度: {len(signature)} 字节")

# 公钥验签:不抛异常即通过
public_key.verify(signature, doc,
    padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                salt_length=padding.PSS.MAX_LENGTH),
    hashes.SHA256())
print("验签通过")

# 篡改文档再验签,必然失败
doc_tampered = b"contract: pay 10000 yuan to mallory, order=20260922"
try:
    public_key.verify(signature, doc_tampered,
        padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH),
        hashes.SHA256())
except Exception:
    print("篡改金额后验签失败(符合预期)")

实测输出:

text 复制代码
签名长度: 256 字节
验签通过:文档确实由对应私钥签署,且未被篡改
篡改金额后验签失败(符合预期:签名与文档绑定)

🔴 一句话记住这四块砖头怎么配合:

  • 对称加密管"快"------加密应用数据。
  • 非对称加密管"安全地送密钥"------把对称密钥安全递给对方。
  • 哈希管"指纹"------算数据摘要。
  • 数字签名管"身份"------用私钥给证书/握手消息盖章。

三、数字证书与 CA 体系:你凭什么信任这个公钥

非对称加密有个新问题:我怎么知道手里的"服务器公钥"真的属于 github.com,而不是中间人自己生成的假公钥?这就引出了证书 和CA。

3.1 证书是什么

证书(X.509 格式)本质上是一张被权威机构背书的公钥"身份证"。一张服务器证书里核心字段:

字段 含义 例子
Subject(主体) 这张证书属于谁 CN=example.com
Subject Alternative Name (SAN) 覆盖哪些域名 DNS:example.com, DNS:www.example.com
Public Key 服务器的公钥 2048 位 RSA 或 256 位 ECC
Issuer(颁发者) 哪个 CA 签的 Cloudflare TLS Issuing ECC CA 3
Validity(有效期) 生效/过期时间 2026-07-29 ~ 2026-10-27
Signature CA 用自己私钥对上述内容的签名 SHA256 签名

🔴 关键点:证书本身不加密任何东西,它只是把"某公钥属于某域名"这件事用 CA 的私钥签了个名。浏览器预装了全球可信 CA 的公钥,所以能验证这个签名。

3.2 证书链:根 CA → 中间 CA → 服务器证书

现实中 CA 不会用根证书直接给每个网站签证书(根私钥泄露后果太大),而是分层:

验证时从叶子往上逐级验签:用中间 CA 的公钥验服务器证书的签名 → 用根 CA 的公钥验中间 CA 的签名 → 根 CA 在浏览器信任列表里,到此为止。

下面用 openssl s_client 实测 example.com 到底发了几张证书、是谁签的:

bash 复制代码
echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null > ex_chain.pem

然后把 PEM 里每张证书拆开看 subject/issuer(macOS 自带 openssl):

bash 复制代码
# 提取每张证书的主题和颁发者
grep -c "BEGIN CERTIFICATE" ex_chain.pem    # 看有几张

实测拿到 4 张证书,逐级解析结果:

text 复制代码
=== 第1张 服务器证书 ===
subject=CN=example.com
issuer=C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3

=== 第2张 中间CA ===
subject=C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3
issuer=C=US, O=SSL Corporation, CN=SSL.com TLS Transit ECC CA R2

=== 第3张 中间CA ===
subject=C=US, O=SSL Corporation, CN=SSL.com TLS Transit ECC CA R2
issuer=C=US, O=SSL Corporation, CN=SSL.com TLS ECC Root CA 2022

=== 第4张 根/中间 ===
subject=C=US, O=SSL Corporation, CN=SSL.com TLS ECC Root CA 2022

看出来了吗?上一张的 issuer 正好是下一张的 subject,一级一级往上推,最后到根 CA。这就是证书链。

3.3 浏览器拿到证书后到底检查什么

浏览器收到服务器证书链后,要做四件事,任何一件不过就弹红字警告:

  1. 逐级验签:从叶子证书往上,每张都用下一张的公钥验签,最后一级必须能在操作系统/浏览器内置的根 CA 列表里找到。
  2. 有效期 :当前时间必须在 notBefore 和 notAfter 之间。过期/未生效都不行。
  3. 域名匹配 :证书的 CN 或 SAN 必须覆盖你访问的域名。访问 paypal.com 却拿到一张给 paypa1.com 的证书,直接拒绝。
  4. 吊销状态 :检查这张证书是否被 CA 提前吊销(私钥泄露了)。两种方式:
    • CRL(Certificate Revocation List):CA 定期发布一个吊销清单,浏览器下载下来查。
    • OCSP(Online Certificate Status Protocol):浏览器实时向 CA 发一个查询,问"这张证书现在有效吗"。

⚠️ 你日常看到的证书错误,九成是前三条:证书过期、域名不匹配、证书链不完整(服务器漏发了中间证书)。下一篇"排错"小节会系统讲。


四、RSA 握手全过程(TLS 1.2)

前面四块砖头都备齐了,现在看它们怎么在 TLS 握手里配合。RSA 握手是 TLS 1.2 时代最经典的密钥交换方式,也是面试必画的时序图。

4.1 七个消息,一图看懂

4.2 逐个消息拆解

消息 谁发 关键内容 作用
ClientHello 客户端 TLS 版本、客户端随机数(32 字节)、支持的 cipher suites 列表、SNI 客户端打招呼,报上自己会什么
ServerHello 服务器 选定版本、服务器随机数(32 字节)、选定的 cipher suite 服务器从列表里挑一个双方都支持的
Certificate 服务器 证书链(服务器证书 + 中间 CA) 把服务器公钥"身份证"给客户端
ServerHelloDone 服务器 空 告诉客户端"我说完了"
ClientKeyExchange 客户端 用服务器公钥加密的 PreMasterSecret(48 字节) 这是握手的核心:安全地把密钥材料送过去
ChangeCipherSpec 双向 一个小通知 "从下一条消息开始,我改用会话密钥加密了"
Finished 双向 对前面所有握手消息的哈希 校验握手过程没被篡改

🔴 为什么要三个随机数? 这是面试高频题。

  1. 客户端随机数(Client Random):客户端生成,明文传输。
  2. 服务器随机数(Server Random):服务器生成,明文传输。
  3. 预主密钥 (PreMasterSecret):客户端生成,用服务器公钥加密后传输,只有服务器私钥能解。

三者拼在一起,通过 PRF(伪随机函数)推导出主密钥(Master Secret),再派生出客户端/服务器各自的加密密钥、MAC 密钥。

为什么不能只用一个预主密钥?因为前向安全性 和防止重放。三个随机数都参与密钥推导,意味着:

  • 每次握手随机数都不同 → 每次会话的密钥都不同,即使同一客户端同一服务器。
  • 攻击者录下历史密文,没有当时的随机数组合,就算以后破解了算法也推不出当时的会话密钥(但 RSA 静态密钥交换做不到前向保密,见下节)。

4.3 密钥推导链路

有了这组会话密钥,后面所有 HTTP 请求/响应就用对称加密(AES-GCM 之类)跑,又快又安全。

4.4 用 Python 亲眼看看一次真实握手

下面这段脚本用标准库 ssl 连 github.com,把协商出来的协议版本、密码套件、证书信息全打出来:

python 复制代码
# ssl_demo.py
import ssl, socket

ctx = ssl.create_default_context()
with socket.create_connection(("github.com", 443), timeout=10) as sock:
    with ctx.wrap_socket(sock, server_hostname="github.com") as ssock:
        print(f"协议版本 : {ssock.version()}")
        c = ssock.cipher()
        print(f"密码套件 : {c[0]}")
        print(f"认证算法 : {c[1]}")
        print(f"密钥长度 : {c[2]} bit")
        cert = ssock.getpeercert()
        cn = dict(x[0] for x in cert['subject']).get('commonName')
        print(f"证书 CN  : {cn}")
        print(f"有效期   : {cert['notBefore']} ~ {cert['notAfter']}")

实测输出:

text 复制代码
协议版本 : TLSv1.3
密码套件 : TLS_AES_128_GCM_SHA256
认证算法 : TLSv1.3
密钥长度 : 128 bit
证书 CN  : github.com
有效期   : Sep  1 00:00:00 2026 GMT ~ Nov 29 23:59:59 2026 GMT

注意:现在主流大站默认走的是 TLS 1.3(我们下一篇细讲)。想看 TLS 1.2 的 RSA 握手细节,可以用老站点或者用 openssl s_client -connect 某站:443 -tls1_2 -msg 抓握手报文。


五、RSA 握手的致命缺陷:没有前向保密

RSA 握手虽然经典,但它有一个被 TLS 1.3 彻底抛弃的硬伤------不支持前向保密(Forward Secrecy)。

问题出在哪?在 RSA 握手里,预主密钥是用服务器的长期公钥(来自证书)加密后发出去的。这意味着:

  • 攻击者只要把你今天和昨天、和去年所有 HTTPS 通信全录下来(密文),存着。
  • 哪天服务器私钥泄露了(被偷、被勒索、被法院调取),攻击者用这把私钥把每段历史握手里的预主密钥都解出来。
  • 有了预主密钥 + 当时录下来的两个随机数,就能还原所有历史会话密钥 → 所有历史密文全部可解密。

🔴 这就是"没有前向保密"的含义:长期密钥一旦泄露,过去的通信全部沦陷。

对比一下:

场景 RSA 密钥交换 临时(ECDHE)密钥交换
每次会话的密钥 由长期公钥加密预主密钥推导 每次生成临时密钥对
长期私钥泄露后 历史全部密文可解密 历史密文仍不可解密
握手轮次 2-RTT 2-RTT(TLS 1.3 压到 1-RTT)

怎么解决?答案就是 Diffie-Hellman 临时密钥交换 ,更准确地说是 ECDHE。它让每次会话都用一对临时生成的密钥,会话一结束就扔掉,即使服务器长期私钥泄露,攻击者也没法回溯解密历史。这正是下一篇要讲的核心。


六、总结:你真正需要记住的 8 件事

  1. HTTP 有三个死穴:明文传输、不验证身份、不保护完整性。HTTPS 就是来同时解决这三件事的。
  2. 四大基石各司其职:对称加密快 (AES)、非对称加密慢但安全地送密钥 (RSA/ECC)、哈希是指纹 (SHA-256)、数字签名绑身份和完整性。
  3. 证书不是加密工具,它是CA 用私钥给"某公钥属于某域名"签的名。浏览器靠内置根 CA 公钥验证这条链。
  4. 证书链 = 服务器证书 → 中间 CA → 根 CA,浏览器逐级验签 + 查有效期 + 对域名 + 查吊销。
  5. TLS 1.2 RSA 握手七步:ClientHello → ServerHello → Certificate → ServerHelloDone → ClientKeyExchange → ChangeCipherSpec → Finished。
  6. 三个随机数(客户端随机、服务器随机、预主密钥)共同经 PRF 推导出会话密钥,保证每次会话密钥不同。
  7. RSA 握手用服务器长期公钥加密预主密钥 → 没有前向保密:私钥泄露则历史密文全部可解。
  8. 现代实战中,用 Python cryptography 跑一遍 AES/RSA/哈希/签名,比背十遍概念都管用。

验证清单

  • 能用一句话说清 HTTP 明文、身份、完整性三个问题分别对应什么攻击
  • 能跑通 AES-256-CBC 加解密,并解释 IV 的作用
  • 能跑通 RSA 公钥加密/私钥解密,说出为什么 RSA 不能直接加密大块数据
  • 能用 SHA-256 算一段文本的哈希,并演示"改一个字节哈希完全不同"
  • 能跑通 RSA-PSS 签名验签,并篡改文档验证验签失败
  • 能用 openssl s_client -connect 某站:443 -showcerts 拉出证书链,并逐级指出 subject/issuer
  • 能在纸上画出 TLS 1.2 RSA 握手的 7 个消息和三个随机数的流向
  • 能解释"前向保密"为什么在 RSA 握手里不成立

参考资源


下一篇《HTTPS(下):ECDHE 握手与优化》讲:Diffie-Hellman 与 ECDHE 怎么实现前向保密、TLS 1.3 为什么把握手从 2-RTT 压到 1-RTT、Session Ticket / OCSP Stapling / TLS False Start 等性能优化手段,以及证书过期、域名不匹配、证书链不完整这三类最常见的 HTTPS 排错。

相关推荐
夜之眷属1 小时前
JVM实战:服务器堆外内存去哪了(NMT实测)
java·服务器·jvm·后端·性能优化
vipxieliang1 小时前
PHP 依赖注入容器从零实现:控制反转、手动注入与容器管理全解析
后端·php
JAVA面经实录9171 小时前
Java高级后端 · 全套面试通关手册(Nginx)
java·nginx·面试
天空鸟_时光不老2 小时前
01-我不转Python把AI塞进Java里
java·人工智能·spring boot·后端·spring·spring cloud·架构
hsfxuebao2 小时前
Hermes Agent能力篇:会话、工具、MCP、记忆
人工智能·后端
vx_Biye_Design2 小时前
flask学生课程笔记共享系统29026-计算机课程设计、毕业设计
java·javascript·spring boot·后端·elasticsearch·flask·课程设计
卷无止境2 小时前
用Rust重写:三条清晰的收益曲线
后端·rust
考研保研资料分享2 小时前
211工商管理保研北大光华:夏令营笔试、科研面试与人力资源复习经验
面试·职场和发展