本文讲解阅读本系列其余内容之前你需要了解的核心安全概念。
术语表
- IdP(身份提供方,Identity Provider) --- 签发身份与令牌。这里是
Keycloak。 - PEP(策略执行点,Policy Enforcement Point) --- 拦截请求、执行决策。这里是
Kong。 - PDP(策略决策点,Policy Decision Point) --- 依据策略判定允许/拒绝。这里是
OPA。 - 资源服务器(Resource server) --- 拥有受保护的数据,并会再次校验令牌。这里是
banking-api-service。 - JWT --- 携带身份与声明(claims)的签名令牌。
认证 vs 授权
认证回答的是:
- 你是谁?
授权回答的是:
- 你被允许做什么?
在本项目中:
Keycloak负责认证。Kong与OPA负责执行授权。banking-api-service在返回银行数据前也会校验调用方。
IdP
IdP(身份提供方)是这样一个系统:
- 存储用户
- 校验用户名与密码
- 登录成功后签发令牌
在本项目中,Keycloak 就是 IdP。当 alice 登录时,Keycloak 对她进行认证并签发一个 JWT。
JWT
JWT 是一个携带身份信息与声明(claims)的签名令牌,例如:
- 用户名
- 角色
- 受众(audience)
- 签发者(issuer)
- 自定义声明,如
customer_id和account_ids
重要:JWT 不会仅因为存在就被信任 ------ 接收方必须对它进行校验。
校验项包括:
- 签名
- 签发者(issuer)
- 受众(audience)
- 过期时间(expiry)
PEP
PEP(策略执行点)位于受保护资源之前,要么:
- 放行请求,要么
- 拦截请求。
在本项目中,Kong 是位于边缘的 PEP。来自 alice 或 ops-admin 的每个请求,都要先经过 Kong 才能到达 banking-api-service。
PDP
PDP(策略决策点)评估策略规则并返回一个决策:
- 允许,或
- 拒绝。
在本项目中,OPA 是 PDP。Kong 把请求细节发送给 OPA,OPA 评估策略并返回决策。这样就把授权逻辑同 Keycloak 中的认证、以及 banking-api-service 中的业务逻辑分离开来。一个简单的理解方式:Keycloak 证明用户是谁,Kong 拦截请求,OPA 回答该用户是否被允许执行该操作。
为什么要拆分 IdP、PEP 与 PDP
把这些角色分开,是因为它们解决的是不同的问题:
Keycloak证明身份。Kong在网关处执行访问控制。OPA判定某个请求是否应被允许。banking-api-service运行业务逻辑并提供纵深防御。
这种分离让系统更易于理解、也更易于修改。
Spring Boot 微服务
本项目使用两个 Spring Boot 服务:
banking-api-serviceidentity-bootstrap-service
为什么用微服务:
banking-api-service对外暴露受保护的银行 API。identity-bootstrap-service负责把演示用户初始化到Keycloak。- 每个服务都有单一、清晰的职责。
概念图
#mermaid-svg-Kir5WyBv2KbJtZYn{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-Kir5WyBv2KbJtZYn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Kir5WyBv2KbJtZYn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Kir5WyBv2KbJtZYn .error-icon{fill:#552222;}#mermaid-svg-Kir5WyBv2KbJtZYn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Kir5WyBv2KbJtZYn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Kir5WyBv2KbJtZYn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Kir5WyBv2KbJtZYn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Kir5WyBv2KbJtZYn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Kir5WyBv2KbJtZYn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Kir5WyBv2KbJtZYn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Kir5WyBv2KbJtZYn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Kir5WyBv2KbJtZYn .marker.cross{stroke:#333333;}#mermaid-svg-Kir5WyBv2KbJtZYn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Kir5WyBv2KbJtZYn p{margin:0;}#mermaid-svg-Kir5WyBv2KbJtZYn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Kir5WyBv2KbJtZYn .cluster-label text{fill:#333;}#mermaid-svg-Kir5WyBv2KbJtZYn .cluster-label span{color:#333;}#mermaid-svg-Kir5WyBv2KbJtZYn .cluster-label span p{background-color:transparent;}#mermaid-svg-Kir5WyBv2KbJtZYn .label text,#mermaid-svg-Kir5WyBv2KbJtZYn span{fill:#333;color:#333;}#mermaid-svg-Kir5WyBv2KbJtZYn .node rect,#mermaid-svg-Kir5WyBv2KbJtZYn .node circle,#mermaid-svg-Kir5WyBv2KbJtZYn .node ellipse,#mermaid-svg-Kir5WyBv2KbJtZYn .node polygon,#mermaid-svg-Kir5WyBv2KbJtZYn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Kir5WyBv2KbJtZYn .rough-node .label text,#mermaid-svg-Kir5WyBv2KbJtZYn .node .label text,#mermaid-svg-Kir5WyBv2KbJtZYn .image-shape .label,#mermaid-svg-Kir5WyBv2KbJtZYn .icon-shape .label{text-anchor:middle;}#mermaid-svg-Kir5WyBv2KbJtZYn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Kir5WyBv2KbJtZYn .rough-node .label,#mermaid-svg-Kir5WyBv2KbJtZYn .node .label,#mermaid-svg-Kir5WyBv2KbJtZYn .image-shape .label,#mermaid-svg-Kir5WyBv2KbJtZYn .icon-shape .label{text-align:center;}#mermaid-svg-Kir5WyBv2KbJtZYn .node.clickable{cursor:pointer;}#mermaid-svg-Kir5WyBv2KbJtZYn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Kir5WyBv2KbJtZYn .arrowheadPath{fill:#333333;}#mermaid-svg-Kir5WyBv2KbJtZYn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Kir5WyBv2KbJtZYn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Kir5WyBv2KbJtZYn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Kir5WyBv2KbJtZYn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Kir5WyBv2KbJtZYn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Kir5WyBv2KbJtZYn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Kir5WyBv2KbJtZYn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Kir5WyBv2KbJtZYn .cluster text{fill:#333;}#mermaid-svg-Kir5WyBv2KbJtZYn .cluster span{color:#333;}#mermaid-svg-Kir5WyBv2KbJtZYn 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-Kir5WyBv2KbJtZYn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Kir5WyBv2KbJtZYn rect.text{fill:none;stroke-width:0;}#mermaid-svg-Kir5WyBv2KbJtZYn .icon-shape,#mermaid-svg-Kir5WyBv2KbJtZYn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Kir5WyBv2KbJtZYn .icon-shape p,#mermaid-svg-Kir5WyBv2KbJtZYn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Kir5WyBv2KbJtZYn .icon-shape .label rect,#mermaid-svg-Kir5WyBv2KbJtZYn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Kir5WyBv2KbJtZYn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Kir5WyBv2KbJtZYn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Kir5WyBv2KbJtZYn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} proves identity
allow or deny
business data
User
IdP: Keycloak
JWT
PEP: Kong
PDP: OPA
Spring Boot Service
最重要的是什么
如果你只记住一件事,就记住这个:
Keycloak说明用户是谁。Kong拦截或转发请求。OPA判定该操作是否被允许。banking-api-service再次校验,并返回银行响应。
Next: 02 --- 本项目架构 →