当前位置: 首页 > news >正文

分布式认证中心第一集 引入oauth2授权服务器

前情提要:一个“不雅观”的痛点

在上一季《Security第十六集:引入JWT》中,不知道大家有没有发现一个极其尴尬的画面——

两个微服务里,各自建了一个JwtUtils类,各自定义了一模一样的SECRET_KEY,还必须确保这俩密钥值完全相同。

这画面像什么?像极了异地恋情侣非得约定同一句暗号才能确认“是我本人”。代码冗余不说,只要密钥一换,所有服务都得跟着改,改到天荒地老。

有同学可能会问:“那怎么办?总不能让他们一直这么‘异地’下去吧?”

别急,OAuth2 就是来当这个月老的。今天我们就手把手把Security和OAuth2撮合成一对“认证授权CP”,让它们分工明确、各司其职,彻底终结那段“密钥复制粘贴”的苦日子。

第一幕:认清各自的本职工作

在动手改造之前,咱先把职责掰扯清楚,免得后面迷糊:
Spring Security 认证(Authentication) 验明正身——“你说你是张三,密码拿来我瞅瞅”
OAuth2 授权(Authorization) 发放通行证——“身份没问题,给你发个令牌,拿着它去访问别的服务吧”

简单说就是:Security负责“验人”,OAuth2负责“发牌”。

而我们今天要做的,就是把原来那个单纯的Security认证服务,改造成一个OAuth2授权服务器——让它既能验人,又能发牌,两全其美。

第二幕:动手改造,三步搞定

1.引入pom依赖

<!--OAuth2依赖--><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.3.9.RELEASE</version></dependency>

2.创建 OAuth2AuthorizationServerConfig,配置客户端信息以及授权类型

@Configuration//启用授权服务器功能@EnableAuthorizationServerpublicclassOAuth2AuthorizationServerConfigextendsAuthorizationServerConfigurerAdapter{//用于验证用户的用户名和密码(密码模式需要)@AutowiredprivateAuthenticationManagerauthenticationManager;//用于加密和验证客户端密钥@AutowiredprivatePasswordEncoderpasswordEncoder;//定义令牌的存储方式@BeanpublicTokenStoretokenStore(){// 使用 JWT 方式存储令牌// JWT 是一种自包含的令牌格式,不需要在服务器端存储returnnewJwtTokenStore(accessTokenConverter());}//JWT 令牌转换器@BeanpublicJwtAccessTokenConverteraccessTokenConverter(){JwtAccessTokenConverterconverter=newJwtAccessTokenConverter();// 注意:这里使用的是对称密钥(默认)// 生产环境建议使用非对称密钥(RSA)returnconverter;}//这里定义了哪些应用可以访问 OAuth2 服务@Overridepublicvoidconfigure(ClientDetailsServiceConfigurerclients)throwsException{// inMemory() - 将客户端信息存储在内存中// 生产环境应该使用 .jdbc() 存储在数据库中clients.inMemory()// 配置第一个客户端应用 , 客户端 ID(类似用户名).withClient("client-app")// 客户端密钥(类似密码),需要加密.secret(passwordEncoder.encode("secret123"))// 允许的授权类型(四种模式)授权码模式,密码模式,客户端凭证模式,隐式模式,刷新令牌.authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")// 允许的权限范围.scopes("read","write")// 回调地址.redirectUris("http://localhost:8080/callback")// 自动批准,不需要用户手动确认授权.autoApprove(true)// 访问令牌有效期:3600秒(1小时).accessTokenValiditySeconds(3600)// 刷新令牌有效期:7200秒(2小时).refreshTokenValiditySeconds(7200).and()// 配置下一个客户端.withClient("web-app").secret(passwordEncoder.encode("web-secret")).authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token").scopes("read","write").redirectUris("http://localhost:8080/web/callback").autoApprove(true).accessTokenValiditySeconds(3600).refreshTokenValiditySeconds(7200);}//配置授权服务器端点@Overridepublicvoidconfigure(AuthorizationServerEndpointsConfigurerendpoints)throwsException{endpoints// 设置认证管理器,用于密码模式的用户认证.authenticationManager(authenticationManager)// 设置令牌存储方式(JWT).tokenStore(tokenStore())// 设置令牌转换器(JWT 转换).accessTokenConverter(accessTokenConverter());}//配置授权服务器的安全策略@Overridepublicvoidconfigure(AuthorizationServerSecurityConfigurersecurity)throwsException{security// /oauth/token_key 端点允许所有人访问// 这个端点用于获取 JWT 签名的公钥(如果使用非对称加密).tokenKeyAccess("permitAll()")// /oauth/check_token 端点需要认证后才能访问// 这个端点用于验证令牌的有效性.checkTokenAccess("isAuthenticated()")// 允许客户端通过表单方式提交认证信息// 这样客户端可以在 POST body 中传递 client_id 和 client_secret.allowFormAuthenticationForClients();}}

3.改造一下 MyWebSecurityConfigAdapter,放行 oauth2自带的接口,并创建一个AuthenticationManager对象

@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{http.csrf().disable().httpBasic();http.authorizeRequests().antMatchers("/oauth/**").permitAll().anyRequest().authenticated();}@Override@BeanpublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}

第三幕:实战测试,看看效果

先来测试一下密码模式

本服务端口 8129,用post请求 http://localhost:8129/oauth/token
Authorization 中 选择 Basic Auth 并 填入 用户名 client-app, 密码 secret123,注意 这个用户名密码 是

.withClient("client-app")// 客户端密钥(类似密码),需要加密.secret(passwordEncoder.encode("secret123"))

不是users表中 的 用户名密码

然后在 body中添加参数,注意选择 x-www-form-urlencoded

grant_type是

.authorizedGrantTypes("authorization_code","password","client_credentials","implicit","refresh_token")

哪个模式访问就写哪个
这里的 username 和 password 才是 数据库中 users表的 用户名密码

scope的值是

// 允许的权限范围.scopes("read","write")

现在我们来 send 一下

返回的这一大串json,就是 oauth2的令牌。

客户端凭证模式

这个跟密码模式的区别
1,无需提供 users 的用户名密码
2,grant_type 的值 变成 client_credentials

这个模式通常用于服务与服务之间的内部调用,比如定时任务、微服务互相拉取数据等场景——没有真人用户,只有机器在互相对话。

下集预告

这一集我们把Security认证服务成功改造为OAuth2授权服务器,跑通了密码模式和客户端凭证模式。

下一集,我们将真正创建一个前端应用,完整跑通密码模式和授权码模式的登录流程。至于隐式模式没啥卵用,可以忘掉它

http://www.jsqmd.com/news/1054128/

相关文章:

  • 2026江阴装修施工质量怎么挑?尚城绿园业主实测:自有精工团队,工地管理确实严 - 装企自媒体训练营辉哥
  • 2026 北京闲置钻石回收深度测评:海淀区 7 家专业机构甄选,高价变现不踩雷 - 薛定谔的梨花猫
  • AI全栈开发实战:Next.js+dbx构建可调试可恢复的GPT-5.5链路
  • 北京奢侈品包包回收哪家靠谱?2026 实测 7 家门店,报价透明不压价 - 薛定谔的梨花猫
  • Claude Opus实测:5类高价值任务的提示结构与国内稳定调用指南
  • CentOS 8服务器初始配置:安全基线与生产就绪实践
  • 从SCF5250实战解析芯片Datasheet:电气特性与封装规格设计指南
  • 2026年6月最新万国中国官方售后服务中心网点地址与客服电话 - 亨得利官方服务中心
  • 人形机器人敏捷技能切换:基于技能图与强化学习的决策框架
  • DVWA文件包含漏洞实战:从LFI到RFI的四种安全等级绕过技巧
  • 2026年6月知名的展台搭建全包服务推荐,样品展台搭建/展馆/活动庆典/展台展厅搭建/商务活动庆典,展台搭建品牌选哪家 - 品牌推荐师
  • L2(第二阶段)真题参考代码 + 注释解释
  • 图像篡改检测与定位:从传统方法到深度学习实战
  • PHP CMS安全加固实战:从SQL注入与XSS防御到WAF部署
  • 淘宝商品SKU图自动分类技术深度解析:从DOM容器定位到智能属性识别的完整实现
  • [IOI 2000] 邮局原始版、加强版、加强加强版
  • 怎样轻松配置B站会员购抢票工具:新手友好的完整方案
  • 人形机器人敏捷技能切换:基于技能图与分层强化学习的决策框架
  • 英雄联盟战绩查询终极指南:3步安全使用Seraphine保护你的账号
  • AI数据伦理:算法偏见、版权争议与边缘群体赋权的实践指南
  • 英雄联盟智能管家:如何用自动化工具提升你的游戏体验?
  • WELearn开源工具:智能解析引擎与多课程适配的在线学习解决方案
  • Ubuntu 20.04 APT 部署 Elasticsearch 实战指南
  • 基于IGH EtherCAT与real-time-edge-servo的实时伺服控制实践
  • 深圳信息流广告服务商哪家好:排名前五深度测评 - 服务品牌热点
  • 从8位到32位MCU:QE128系列核心架构对比与嵌入式开发实战
  • 2025-2026年北投和璟联系电话:预约前请核实项目信息与周边规划 - 品牌推荐
  • 北京黄金回收避坑指南 2026:对标大盘实时金价,朝阳区正规门店无隐形扣费 - 薛定谔的梨花猫
  • 闲置钻石变现指南:2026 东莞 7 家直营门店实地走访,估值精准更安心 - 薛定谔的梨花猫
  • 纯正公办!淮南职业技术学院中专部 2026 招生启动 - 我叫小周