87 lines
7.4 KiB
XML
87 lines
7.4 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="680" height="1225" viewBox="0 0 680 1225" role="img" aria-labelledby="diagram-title diagram-description">
|
|
<title id="diagram-title">쿠키에 담으면 공유할 것이 없다</title>
|
|
<desc id="diagram-description">cookie-only 모드에서는 세션 전체가 쿠키에 있어 replica가 같은 secret만 읽으면 된다. Redis session store를 켜면 쿠키에는 ticket만 남고 실제 session은 Redis에 생긴다. secret을 바꾸면 ticket을 풀 수 없어 어느 Redis key를 지울지 알 수 없고 고아 session이 남는다. refresh:disabled에서는 TTL이 생성 시각의 함수라 회전 시각과 비교해 고아를 골라낼 수 있지만 --cookie-refresh를 켜면 이 역산은 성립하지 않는다.</desc>
|
|
<metadata>{"techviz":{"spec_version":"1.1","id":"b7-cookie-session-tradeoff","profile":"component-flow"},"source_context":{"document":"docs/keycloak-session-store/final/document.md","document_sha256":"28aef96a2bbb94fbb10ade26a71238fee62a5a4d9fa6e7749ae98cfd0a65e560","anchor":{"kind":"heading","value":"B-7 · B-7a — 쿠키에 담는 세션, 그리고 그 대가","line":884}},"evidence_policy":"Each factual element cites source lines or is marked assumption.","diagram_only":true}</metadata>
|
|
<defs>
|
|
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
<path d="M 0 0 L 10 5 L 0 10 z" />
|
|
</marker>
|
|
<style>
|
|
:root { color-scheme: light; }
|
|
text { font-family: Inter, Pretendard, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #111827; }
|
|
.canvas { fill: #ffffff; }
|
|
.group-box { fill: #ffffff; stroke: #9ca3af; stroke-width: 1.4; stroke-dasharray: 7 5; }
|
|
.group-label-bg { fill: #ffffff; }
|
|
.group-label { font-size: 13px; font-weight: 650; fill: #374151; }
|
|
.edge { fill: none; stroke: #374151; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; marker-end: url(#arrow); }
|
|
.edge.style-dashed, .edge.semantic-dashed, .edge.assumption { stroke-dasharray: 7 5; }
|
|
.edge.style-dotted { stroke-dasharray: 2 5; }
|
|
.edge.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
|
.edge.emphasis-muted { stroke: #9ca3af; }
|
|
.edge.emphasis-warning, .edge.kind-failure, .edge.kind-error { stroke: #dc2626; stroke-width: 2.2; }
|
|
.edge-label-bg { fill: #ffffff; }
|
|
.edge-label { font-size: 12px; font-weight: 560; text-anchor: middle; }
|
|
.node-shape { fill: #ffffff; stroke: #4b5563; stroke-width: 1.7; }
|
|
.node-shape.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
|
.node-shape.emphasis-muted { stroke: #9ca3af; fill: #f9fafb; }
|
|
.node-shape.emphasis-warning { stroke: #d97706; stroke-width: 2; fill: #fffdf5; }
|
|
.node-shape.kind-database, .node-shape.kind-datastore, .node-shape.kind-storage { fill: #f8fafc; }
|
|
.node-shape.kind-queue, .node-shape.kind-event, .node-shape.kind-topic { fill: #fafafa; }
|
|
.node-shape.assumption { stroke-dasharray: 4 4; }
|
|
.storage-bottom, .controller-divider { fill: none; stroke: #4b5563; stroke-width: 1.4; }
|
|
.controller-led { fill: #4b5563; }
|
|
.actor-symbol { fill: none; stroke: #4b5563; stroke-width: 1.8; stroke-linecap: round; }
|
|
.actor-symbol.emphasis-primary { stroke: #2563eb; stroke-width: 2.2; }
|
|
.node-label { font-size: 14px; font-weight: 650; text-anchor: middle; }
|
|
.node-role { font-size: 10px; letter-spacing: 0.04em; text-anchor: middle; fill: #6b7280; }
|
|
.node-detail-divider { stroke: #d1d5db; stroke-width: 1; }
|
|
.node-detail { font-size: 11px; fill: #374151; }
|
|
.assumption-badge { font-size: 9px; font-weight: 700; fill: #92400e; }
|
|
.failure-mark { stroke: #dc2626; stroke-width: 4; stroke-linecap: round; }
|
|
.lifeline { stroke: #9ca3af; stroke-width: 1.2; stroke-dasharray: 5 5; }
|
|
.timeline-axis { stroke: #374151; stroke-width: 1.8; marker-end: url(#arrow); }
|
|
.timeline-stem { stroke: #6b7280; stroke-width: 1.3; }
|
|
.timeline-marker { fill: #ffffff; stroke: #374151; stroke-width: 1.7; }
|
|
.timeline-marker.primary { fill: #2563eb; stroke: #2563eb; }
|
|
.timeline-marker.warning { fill: #dc2626; stroke: #dc2626; }
|
|
.timeline-label { font-size: 13px; font-weight: 650; text-anchor: middle; }
|
|
.timeline-detail { font-size: 11px; fill: #4b5563; text-anchor: middle; }
|
|
</style>
|
|
</defs>
|
|
<rect class="canvas" width="680" height="1225" />
|
|
<polyline class="edge kind-read style-solid emphasis-normal" points="110.0,870.0 110.0,989.5 110.0,989.5 110.0,1109.0" data-evidence="935-946" />
|
|
<rect class="edge-label-bg" x="108.2" y="975.5" width="51.5" height="22" rx="3" />
|
|
<text class="edge-label" x="134.0" y="990.5">생성 시각</text>
|
|
<polyline class="edge kind-write style-solid emphasis-normal" points="122.0,216.0 122.0,347.5 115.0,347.5 115.0,479.0" data-evidence="919-925" />
|
|
<rect class="edge-label-bg" x="89.4" y="305.5" width="58.2" height="22" rx="3" />
|
|
<text class="edge-label" x="118.5" y="320.5">티켓 암호화</text>
|
|
<polyline class="edge kind-read style-solid emphasis-normal" points="115.0,550.0 115.0,674.5 110.0,674.5 110.0,799.0" data-evidence="923-932" />
|
|
<rect class="edge-label-bg" x="80.0" y="632.5" width="64.9" height="22" rx="3" />
|
|
<text class="edge-label" x="112.5" y="647.5">키 이름 생성</text>
|
|
<g id="node-secret">
|
|
<rect class="node-shape kind-datastore emphasis-primary role-source" data-evidence="863-867" x="35.0" y="156.8" width="174.0" height="47.3" /><ellipse class="node-shape kind-datastore emphasis-primary role-source" cx="122.0" cy="156.8" rx="87.0" ry="11.8" /><path class="storage-bottom" d="M 35.0 204.2 A 87.0 11.8 0 0 0 209.0 204.2" />
|
|
<text class="node-label" x="122.0" y="172.0">k8s Secret</text>
|
|
<line class="node-detail-divider" x1="49.0" y1="193.0" x2="195.0" y2="193.0" />
|
|
<text class="node-detail" x="51.0" y="210.0">--cookie-secret 은 단수</text>
|
|
</g>
|
|
<g id="node-ticket">
|
|
<rect class="node-shape kind-component emphasis-warning role-control" data-evidence="923-932" x="35.0" y="479.0" width="160.0" height="71.0" rx="7" />
|
|
<text class="node-label" x="115.0" y="506.0">쿠키의 티켓</text>
|
|
<line class="node-detail-divider" x1="49.0" y1="527.0" x2="181.0" y2="527.0" />
|
|
<text class="node-detail" x="51.0" y="544.0">secret 교체 시 복호화 불가</text>
|
|
</g>
|
|
<g id="node-redis-session">
|
|
<rect class="node-shape kind-datastore emphasis-warning role-target" data-evidence="923-932" x="35.0" y="810.8" width="150.0" height="47.3" /><ellipse class="node-shape kind-datastore emphasis-warning role-target" cx="110.0" cy="810.8" rx="75.0" ry="11.8" /><path class="storage-bottom" d="M 35.0 858.2 A 75.0 11.8 0 0 0 185.0 858.2" />
|
|
<text class="node-label" x="110.0" y="826.0">Redis 의 세션</text>
|
|
<line class="node-detail-divider" x1="49.0" y1="847.0" x2="171.0" y2="847.0" />
|
|
<text class="node-detail" x="51.0" y="864.0">고아 세션</text>
|
|
</g>
|
|
<g id="node-ttl">
|
|
<rect class="node-shape kind-component emphasis-primary role-target" data-evidence="935-946" x="35.0" y="1109.0" width="150.0" height="71.0" rx="7" />
|
|
<text class="node-label" x="110.0" y="1136.0">TTL</text>
|
|
<line class="node-detail-divider" x1="49.0" y1="1157.0" x2="171.0" y2="1157.0" />
|
|
<text class="node-detail" x="51.0" y="1174.0">생성 시각 역산</text>
|
|
</g>
|
|
</svg>
|