纲要
- 微服务工程架构概述
- 授权服务器(
auth-server) - 资源服务器(
todo-service) - 后端客户端(
webclient) - 前端管理应用(
uaa-ui)
- 授权服务器(
- 核心依赖引入
spring-security-oauth2spring-security-oauth2-autoconfigure
- 数据库表结构设计
oauth_client_details表字段详解- 客户端标识、密钥、授权范围、授权类型、回调地址、权限、Token 有效期等
微服务工程架构
在实现 OAuth 2.0 认证体系时,传统单体应用被拆分为多个独立微服务。工程目录中除原有模块外,新增了 todo-service 和 webclient 两个核心工程,其角色分配如下:
- 授权服务器:承担 OAuth 2.0 授权服务器与部分资源服务器角色,管理用户、权限及客户端注册信息。
- 资源服务器 (
todo-service):提供受保护的 REST API(如待办事项列表),供客户端在获得授权后访问。 - 客户端 (
webclient):以不同的 OAuth 2.0 授权流程(授权码模式、客户端凭证模式、密码模式)与授权服务器交互,获取令牌并访问资源。 - 前端管理界面 (
uaa-ui):作为前端客户端,通过浏览器与授权服务器交互,实现用户登录与客户端管理。
项目运行端口配置在各自的 application.yml 中,例如授权服务器使用 8080,资源服务器使用 8082,webclient 使用其他端口,各服务独立启动。
工程结构树示意:
dir
project-root/
├── auth-server/ # 授权服务器 (含资源管理)
│ ├── pom.xml
│ └── src/main/resources/
│ └── application.yml # server.port=8080
├── todo-service/ # 资源服务器
│ ├── pom.xml
│ └── src/main/resources/
│ └── application.yml # server.port=8082
├── webclient/ # 后端客户端
│ ├── pom.xml
│ └── src/main/resources/
│ └── application.yml
└── uaa-ui/ # 前端客户端 (Vue/React)
├── package.json
└── ...
各服务交互流程可用下图表示:
#mermaid-svg-pa4v6Wz2OJlVqsU0{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-pa4v6Wz2OJlVqsU0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .error-icon{fill:#552222;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .marker.cross{stroke:#333333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 p{margin:0;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .cluster-label text{fill:#333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .cluster-label span{color:#333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .cluster-label span p{background-color:transparent;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .label text,#mermaid-svg-pa4v6Wz2OJlVqsU0 span{fill:#333;color:#333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .node rect,#mermaid-svg-pa4v6Wz2OJlVqsU0 .node circle,#mermaid-svg-pa4v6Wz2OJlVqsU0 .node ellipse,#mermaid-svg-pa4v6Wz2OJlVqsU0 .node polygon,#mermaid-svg-pa4v6Wz2OJlVqsU0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .rough-node .label text,#mermaid-svg-pa4v6Wz2OJlVqsU0 .node .label text,#mermaid-svg-pa4v6Wz2OJlVqsU0 .image-shape .label,#mermaid-svg-pa4v6Wz2OJlVqsU0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .rough-node .label,#mermaid-svg-pa4v6Wz2OJlVqsU0 .node .label,#mermaid-svg-pa4v6Wz2OJlVqsU0 .image-shape .label,#mermaid-svg-pa4v6Wz2OJlVqsU0 .icon-shape .label{text-align:center;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .node.clickable{cursor:pointer;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .arrowheadPath{fill:#333333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-pa4v6Wz2OJlVqsU0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pa4v6Wz2OJlVqsU0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-pa4v6Wz2OJlVqsU0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .cluster text{fill:#333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .cluster span{color:#333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 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-pa4v6Wz2OJlVqsU0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-pa4v6Wz2OJlVqsU0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .icon-shape,#mermaid-svg-pa4v6Wz2OJlVqsU0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .icon-shape p,#mermaid-svg-pa4v6Wz2OJlVqsU0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .icon-shape .label rect,#mermaid-svg-pa4v6Wz2OJlVqsU0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-pa4v6Wz2OJlVqsU0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-pa4v6Wz2OJlVqsU0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-pa4v6Wz2OJlVqsU0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 访问
OAuth2 授权请求
返回授权码/令牌
携带令牌
返回受保护资源
管理用户/客户端
OAuth2 登录
用户
webclient 客户端
授权服务器 auth-server
资源服务器 todo-service
数据库
uaa-ui 前端
添加 OAuth2 依赖
在授权服务器模块(auth-server)的 pom.xml 中引入 Spring Security OAuth2 依赖。目前基于 Spring Security OAuth2 的正式发布版本,使用以下两个核心包:
xml
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
说明 :spring-security-oauth2 提供 OAuth2 的核心支持,spring-security-oauth2-autoconfigure 简化自动配置。版本号需与实际 Spring Boot 版本兼容,通常在父 POM 或依赖管理器中统一声明。
刷新 Maven 依赖后,即可开始配置授权服务器。
数据库表结构设计
授权服务器需要持久化客户端信息,因此需在数据库中创建相关表。核心表为 oauth_client_details,它存储每个客户端的注册数据。虽然 Spring Security OAuth2 还支持内存模式,但生产环境推荐使用数据库存储。
建表 SQL 语句如下:
sql
CREATE TABLE `oauth_client_details` (
`client_id` varchar(256) NOT NULL COMMENT '客户端唯一标识',
`resource_ids` varchar(256) DEFAULT NULL COMMENT '可访问的资源ID集合',
`client_secret` varchar(256) DEFAULT NULL COMMENT '客户端密钥(加密)',
`scope` varchar(256) DEFAULT NULL COMMENT '授权范围,如 read,write',
`authorized_grant_types` varchar(256) DEFAULT NULL COMMENT '授权类型,如 authorization_code,password,client_credentials,refresh_token',
`web_server_redirect_uri` varchar(256) DEFAULT NULL COMMENT '授权码模式回调地址',
`authorities` varchar(256) DEFAULT NULL COMMENT '客户端拥有的权限(Spring Security authorities)',
`access_token_validity` int(11) DEFAULT NULL COMMENT '访问令牌有效期(秒)',
`refresh_token_validity` int(11) DEFAULT NULL COMMENT '刷新令牌有效期(秒)',
`additional_information` varchar(4096) DEFAULT NULL COMMENT '附加信息(JSON格式)',
`autoapprove` varchar(256) DEFAULT NULL COMMENT '自动授权范围,true 或 scope 列表',
PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
字段含义详解
| 字段 | 说明 |
|---|---|
client_id |
客户端的唯一标识,如 web-client、app-client |
resource_ids |
客户端可访问的资源服务器 ID 列表(逗号分隔),可用于限制访问特定资源服务,实际项目中更多通过权限控制 |
client_secret |
客户端密钥,需加密存储,用于客户端认证 |
scope |
授权范围,定义客户端能请求的权限粒度,如 read、write,与用户权限形成两层控制 |
authorized_grant_types |
允许的 OAuth2 授权流程,常见值:authorization_code、password、client_credentials、refresh_token、implicit |
web_server_redirect_uri |
授权码模式下的回调地址,授权服务器将授权码或令牌重定向到此 URL |
authorities |
客户端自身的权限(而非用户权限),可用于资源服务器访问控制 |
access_token_validity |
访问令牌的过期时间(秒),为空则使用全局默认值 |
refresh_token_validity |
刷新令牌的过期时间(秒),为空则使用全局默认值 |
additional_information |
自定义附加信息,可存放业务需要的额外字段,JSON 格式 |
autoapprove |
如果设为 true 或具体 scope 列表,则用户授权时不会弹出确认页面,直接自动批准 |
示例插入一条客户端数据:
sql
INSERT INTO `oauth_client_details`
(client_id, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, autoapprove)
VALUES
('web-client', '{noop}secret', 'read,write', 'authorization_code,refresh_token', 'http://localhost:8082/login/oauth2/code/auth-server', 'ROLE_CLIENT', 3600, 7200, 'true');
注:{noop} 表示密钥不加密存储(仅开发测试),生产环境应使用 BCrypt 等加密算法。
后续步骤
本文完成了 OAuth2 授权服务器的初始搭建:明确了工程架构、引入了核心依赖、设计了客户端信息表。
下一篇文章将进入授权服务器的核心配置实现,包括 Spring Security 安全配置、OAuth2 授权服务器端点暴露以及 JWT 令牌的签发。
总结
本文基于实际项目需求,介绍了微服务架构下 OAuth2 授权服务器的前置工作:多服务划分、依赖管理和客户端表结构设计。
这些是后续实现授权码、密码、客户端凭证等授权流程的基础。