Java框架快速入门: Spring Security+OAuth2之搭建授权服务器(依赖与表结构)

纲要

  • 微服务工程架构概述
    • 授权服务器(auth-server)
    • 资源服务器(todo-service)
    • 后端客户端(webclient)
    • 前端管理应用(uaa-ui)
  • 核心依赖引入
    • spring-security-oauth2
    • spring-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 授权服务器的前置工作:多服务划分、依赖管理和客户端表结构设计。

这些是后续实现授权码、密码、客户端凭证等授权流程的基础。

相关推荐
Ruiery9 分钟前
Linux 6.6内核 CPU 深度解析(七):调度器启动 — 从单核到多核,调度器分阶段点亮
linux·运维·服务器
50万马克的面包12 分钟前
CSDN-栈队列数组-知识点整理
linux·运维·服务器
谢亮_vipxieliang31 分钟前
Spring Cloud 服务治理入门:注册发现、配置中心、网关限流、熔断降级与分布式一致性方案
分布式·spring·spring cloud
Wang's Blog36 分钟前
Java 项目实战: 外卖平台优化-Nginx配置文件结构与块层级
java·开发语言·nginx
\光辉岁月/2 小时前
5.java-数组
java·开发语言
谢亮_vipxieliang2 小时前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
郑州光合科技余经理3 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
2601_962071573 小时前
类变量和全局变量的生命周期有什么区别?
java·开发语言·jvm
code2cat3 小时前
Java进阶篇之AtomicReference:一次替换引用,读到一份完整状态
java·并发编程·不可变对象·atomicreference
91刘仁德3 小时前
HTTP协议详解:从URL到HTTP服务器的完整实战
服务器·网络·笔记·网络协议·http