别再死记硬背流程图了!用Spring Security OAuth2手把手实现一个授权码登录(附完整代码) 📅 发布时间:2026/7/13 11:03:02 👁️ 浏览次数: Spring Security OAuth2实战从零构建授权码登录系统每次看到OAuth2授权码模式的流程图那些密密麻麻的箭头和方框总让人望而生畏。作为开发者我们需要的不是纸上谈兵的理论而是能直接运行的代码和清晰的实现路径。本文将带你用Spring Security OAuth2完整实现一个授权码登录系统从数据库表设计到自定义授权页面再到生成Token的每个环节我都会用可运行的代码片段展示关键实现。1. 环境准备与基础配置在开始编码前我们需要搭建好基础环境。假设你已有一个Spring Boot 2.7.x项目以下是必须的依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency dependency groupIdorg.springframework.security.oauth.boot/groupId artifactIdspring-security-oauth2-autoconfigure/artifactId version2.6.8/version /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency /dependencies接下来创建OAuth2所需的数据库表。核心表oauth_client_details存储客户端信息CREATE TABLE oauth_client_details ( client_id varchar(256) NOT NULL, resource_ids varchar(256) DEFAULT NULL, client_secret varchar(256) DEFAULT NULL, scope varchar(256) DEFAULT NULL, authorized_grant_types varchar(256) DEFAULT NULL, web_server_redirect_uri varchar(256) DEFAULT NULL, authorities varchar(256) DEFAULT NULL, access_token_validity int(11) DEFAULT NULL, refresh_token_validity int(11) DEFAULT NULL, additional_information varchar(4096) DEFAULT NULL, autoapprove varchar(256) DEFAULT NULL, PRIMARY KEY (client_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;插入一个测试客户端INSERT INTO oauth_client_details VALUES (test-client, null, {bcrypt}$2a$10$NlBC84MVb7F95EXYTXwLneXgCca6/GipyWR5NHm8K0203bSQMLpvm, read,write, authorization_code,refresh_token, http://localhost:8081/login/oauth2/code/test, null, 3600, 86400, null, false);2. 认证服务器配置认证服务器是OAuth2的核心我们需要配置AuthorizationServerConfigConfiguration EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { Autowired private AuthenticationManager authenticationManager; Autowired private DataSource dataSource; Autowired private UserDetailsService userDetailsService; Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource); } Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { endpoints .authenticationManager(authenticationManager) .userDetailsService(userDetailsService) .tokenStore(tokenStore()) .authorizationCodeServices(authorizationCodeServices()) .pathMapping(/oauth/confirm_access, /custom/confirm); } Bean public TokenStore tokenStore() { return new JdbcTokenStore(dataSource); } Bean public AuthorizationCodeServices authorizationCodeServices() { return new JdbcAuthorizationCodeServices(dataSource); } }关键点说明EnableAuthorizationServer启用OAuth2认证服务器功能clients.jdbc(dataSource)从数据库读取客户端配置pathMapping自定义授权确认页面的路径3. 自定义登录与授权页面默认的OAuth2登录和授权页面非常简陋我们需要替换它们。首先配置Spring SecurityConfiguration Order(1) public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http .requestMatchers() .antMatchers(/login, /oauth/authorize) .and() .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage(/login) // 自定义登录页 .permitAll(); } Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser(user) .password({bcrypt}$2a$10$NlBC84MVb7F95EXYTXwLneXgCca6/GipyWR5NHm8K0203bSQMLpvm) .roles(USER); } }创建自定义授权确认页面控制器Controller SessionAttributes(authorizationRequest) public class GrantController { GetMapping(/custom/confirm) public ModelAndView getAccessConfirmation( RequestParam MapString, String parameters, Model model) { AuthorizationRequest authorizationRequest (AuthorizationRequest) model.asMap().get(authorizationRequest); ModelAndView view new ModelAndView(grant); view.addObject(clientId, authorizationRequest.getClientId()); view.addObject(scopes, authorizationRequest.getScope()); return view; } }对应的Thymeleaf模板grant.html:!DOCTYPE html html xmlns:thhttp://www.thymeleaf.org head title授权确认/title /head body h2授权请求/h2 p客户端 strong th:text${clientId}/strong 请求以下权限/p ul li th:eachscope : ${scopes} th:text${scope}/li /ul form methodpost action/oauth/authorize input typehidden nameuser_oauth_approval valuetrue/ button typesubmit授权/button /form /body /html4. 令牌生成与验证令牌生成是OAuth2流程的最后一步。我们可以自定义令牌的生成规则和存储方式Configuration EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { Override public void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers(/api/**).authenticated(); } }自定义令牌增强器在令牌中添加额外信息public class CustomTokenEnhancer implements TokenEnhancer { Override public OAuth2AccessToken enhance( OAuth2AccessToken accessToken, OAuth2Authentication authentication) { MapString, Object additionalInfo new HashMap(); additionalInfo.put(organization, example-org); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); return accessToken; } }在认证服务器配置中添加令牌增强器Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { TokenEnhancerChain tokenEnhancerChain new TokenEnhancerChain(); tokenEnhancerChain.setTokenEnhancers(Arrays.asList(new CustomTokenEnhancer())); endpoints .tokenEnhancer(tokenEnhancerChain) // 其他配置... }5. 常见问题与解决方案在实际开发中你可能会遇到以下问题配置优先级冲突解决方案确保认证服务器配置的Order值高于资源服务器自定义页面不生效检查点是否配置了pathMapping控制器是否添加了SessionAttributes(authorizationRequest)令牌存储问题如果使用Redis存储令牌Bean public TokenStore tokenStore() { return new RedisTokenStore(redisConnectionFactory); }跨域问题在资源服务器配置中添加Override public void configure(HttpSecurity http) throws Exception { http.cors(); }6. 完整流程测试让我们测试整个授权码流程访问授权端点替换client_id和redirect_urihttp://localhost:8080/oauth/authorize?response_typecodeclient_idtest-clientredirect_urihttp://localhost:8081/login/oauth2/code/testscoperead登录后跳转到自定义授权页面同意授权后会重定向到http://localhost:8081/login/oauth2/code/test?code生成的授权码使用授权码获取令牌curl -X POST \ http://localhost:8080/oauth/token \ -H Authorization: Basic dGVzdC1jbGllbnQ6c2VjcmV0 \ -d grant_typeauthorization_codecode生成的授权码redirect_urihttp://localhost:8081/login/oauth2/code/test返回的令牌示例{ access_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..., token_type: bearer, refresh_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..., expires_in: 3599, scope: read, organization: example-org, jti: 6d0ad5e5-3a3e-4b5a-8b8e-5e5e5e5e5e5e }在实现过程中我发现最容易被忽视的是Order注解的配置。当认证服务器和资源服务器的安全配置冲突时正确的优先级设置可以避免很多莫名其妙的错误。另外自定义授权页面时确保表单中包含user_oauth_approval参数否则授权操作不会被正确处理。
3大核心功能揭秘:WaveTools鸣潮工具箱完全指南 3大核心功能揭秘:WaveTools鸣潮工具箱完全指南 【免费下载链接】WaveTools 🧰鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 你是否曾经在《鸣潮》游戏中遭遇过帧率限制的困扰?是否因为多个账号切换繁琐而烦恼&a… 2026/5/17 6:25:01
从采集到标注:手把手教你用ObjectDatasetTools和Meshlab处理Realsense数据,打造6D位姿估计专属数据集 从采集到标注:手把手教你用ObjectDatasetTools和Meshlab处理Realsense数据,打造6D位姿估计专属数据集 在计算机视觉领域,6D位姿估计(即物体在三维空间中的位置和姿态估计)是机器人抓取、增强现实等应用的核心技术。而高… 2026/5/5 11:15:05
网盘直链下载助手:3分钟掌握浏览器下载网盘文件的终极指南 网盘直链下载助手:3分钟掌握浏览器下载网盘文件的终极指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / … 2026/5/17 4:37:24
魔兽争霸III终极优化方案:WarcraftHelper深度配置指南 魔兽争霸III终极优化方案:WarcraftHelper深度配置指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款免费开源的魔兽… 2026/7/13 10:59:08
Java Swing开发的葫芦娃横版闯关游戏完整工程包,含源码、资源、演示视频与运行日志 本文还有配套的精品资源,点击获取 简介:这个资源包提供了一个基于Java SE和Swing实现的横版动作闯关小游戏,主角为七个葫芦娃,玩家可操作不同娃对抗蛇精、蝎子精、喽啰等经典反派角色。项目采用标准Maven结构,包含可… 2026/7/13 10:57:08
GTA5线上小助手:一站式开源游戏增强工具完全指南 GTA5线上小助手:一站式开源游戏增强工具完全指南 【免费下载链接】GTA5OnlineTools GTA5线上小助手 项目地址: https://gitcode.com/gh_mirrors/gt/GTA5OnlineTools 在《侠盗猎车手5》线上模式中,玩家们常常面临角色外观定制繁琐、载具升级昂贵、… 2026/7/13 10:57:08
算法分析与设计 4次上机实战:渗透/排序/路由/索引问题 Java 源码解析 算法分析与设计四次上机实战:从渗透问题到文本索引的Java实现精要 1. 课程实验概览与开发环境配置 西电《算法分析与设计》课程的四次上机实验涵盖了算法领域的核心问题,这些实验不仅是普林斯顿大学的经典练习题,更是检验学生算法实现能力的… 2026/7/13 10:55:07
蓝牙5.4 LE Audio硬件选型与优化实践 1. 蓝牙5.4 LE Audio技术现状与硬件选型考量在2023年蓝牙技术联盟正式发布LE Audio标准后,采用LC3编解码器的低功耗音频方案开始快速普及。IDC777-1作为高通平台的双模蓝牙模块,其最大特点是同时支持传统A2DP协议和LE Audio标准,这为开发者提… 2026/7/13 10:53:06
1995年7月13日:佳士得拍卖行失窃乌龙——当高雅现代艺术遭遇保洁大妈的“强力垃圾回收协议” 在软件工程与数据中台的日常运维中,我们经常会提到一个经典的策略:垃圾回收(Garbage Collection, GC)。为了防止内存泄漏或磁盘空间过载,系统通常会挂载一个具备高优先级的后台守护进程,专门负责扫描那些失… 2026/7/13 10:53:06
HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70+个痛点 HS2-HF Patch终极指南:如何用3步解决Honey Select 2的70个痛点 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否曾经在Honey Select 2中遇到过… 2026/7/13 0:01:19
语音转文字工具AsrTools:让音频整理变得简单高效 语音转文字工具AsrTools:让音频整理变得简单高效 【免费下载链接】AsrTools ✨ AsrTools: Smart Voice-to-Text Tool | Efficient Batch Processing | User-Friendly Interface | No GPU Required | Supports SRT/TXT Output | Turn your audio into accurate text … 2026/7/13 0:03:19
基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_ 基于深度学习的蘑菇或花卉或动漫人物或中草药货水果蔬菜等识别系统31(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ 独家界面!不会重复,此项目属于本人原创,若有雷同,均是盗卖,各位买… 2026/7/13 0:05:20
Git reset 与 revert 深度对比:5个关键差异与 3 种典型应用场景 Git Reset 与 Revert 深度对比:5个关键差异与3种典型应用场景在团队协作开发中,代码版本管理如同行走钢丝——一步失误可能导致整个项目陷入混乱。作为Git进阶用户,你是否曾在深夜面对错误的提交束手无策?是否在强制推送后收到同事… 2026/7/13 8:31:55
GitHub 学生包申请避坑:5个常见失败原因与开发者工具调试方案 GitHub 学生包申请技术排障指南:5个高频失败场景与开发者工具实战方案第一次尝试申请GitHub学生包时,我盯着屏幕上那个不断转圈的加载动画整整15分钟,最终只等来了一行冰冷的错误提示。这可能是许多开发者共同的经历——明明按照教程操作&… 2026/7/13 9:31:08
冒烟测试用例设计规范:5%-10%覆盖率下的3类核心场景与执行标准 冒烟测试用例设计的黄金法则:5%-10%覆盖率下的精准筛选策略在快节奏的敏捷开发环境中,冒烟测试作为质量保障的第一道防线,其重要性不言而喻。当测试资源有限而时间紧迫时,如何从海量测试用例中精准筛选出那关键的5%-10%࿰… 2026/7/13 2:34:55