Security对接 sso服务总结——思路篇
功能
- 自定义登录线便于Oauth2登录服务出错时使用
- 自定义认证校验(授权对象存于redis,实现分布式认证)
- oauth2授权服务整合
- oauth2资源服务整合
代码地址
- sso服务:https://gitee.com/jdw-silky/silky-sso-server.git
- client-web:https://gitee.com/security-demo/oauth2-client-web-login.git
架构
- language:java
- framework:springframework + projectreactor + thymeleaf + webjars
- Build Tools:gradle
启动
- 拉取oauth2单点代码:https://gitee.com/jdw-silky/silky-sso-server.git
- 依次启动oauth2授权服务,oauth2资源服务
总结————思路篇
自定义登录实现逻辑
-
配置了自定义登录拦截器,
拦截登录请求生成有效Authentication
放入security上下文
,redis保存登录标识
——Authentication
-
配置了自定义登录校验拦截器
拦截带有登录标识
的请求,通过该标识从redis获取Authentication
,获取不到则代表redis已退出,清理security上下文
-
将这两个拦截器放到security拦截器链路中,FilterChainProxy
自定义登录+自定义授权实现逻辑
- 配置了自定义登录拦截器,
拦截登录请求生成有效Authentication
放入security上下文
,redis保存登录标识
——Authentication
- 配置了自定义登录校验拦截器
拦截带有登录标识
的请求,通过该标识从redis获取Authentication
,获取不到则代表redis已退出,清理security上下文
- 自定义访问决策处理器
AccessDecisionProcessor
,与默认的WebExpressionVoter
构建访问决策管理器AccessDecisionManager
- 将新构建的访问决策管理器放入security配置中
- 将这两个拦截器放到security拦截器链路中,FilterChainProxy
自定义登录+自定义授权+Oauth2客户端登录授权+Oauth2资源服务实现逻辑
需求
自定义登录保留
未登录访问限制资源默认跳转Oauth2登录页面
Oauth2登录回来后需要达到与自定义登录一样的效果
登录授权
- 配置了自定义登录拦截器:拦截自定义登录请求生成有效
Authentication
放入security上下文
,redis保存登录标识
——Authentication
- 配置了自定义登录校验拦截器:拦截带有
登录标识
的请求,通过该标识从redis获取Authentication
,获取不到则代表redis已退出,清理security上下文
- 自定义访问决策处理器
AccessDecisionProcessor
,与默认的WebExpressionVoter
构建访问决策管理器AccessDecisionManager
- 将新构建的访问决策管理器放入security配置中
- 将这两个拦截器放到security拦截器链路中,FilterChainProxy
- security开始Oauth2登录配置
- Oauth2登录添加自定义登录成功处理器,开启Oauth2登录
- 在Oauth2登录成功后,添加自定义登录成功处理器。进行自定义认证逻辑,合并自定义授权与Oauth2授权等操作
Oauth2服务整合
- 配置
spring.security.oauth2.client.provider
地址,该地址拼接/.well-known/openid-configuration
组成实际Oauth2对接相关信息获取地址
{ "issuer": "http://192.168.137.139:9000", "authorization_endpoint": "http://192.168.137.139:9000/oauth2/authorize", "token_endpoint": "http://192.168.137.139:9000/oauth2/token", "token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"], "jwks_uri": "http://192.168.137.139:9000/oauth2/jwks", "response_types_supported": ["code"], "grant_types_supported": ["authorization_code", "client_credentials", "refresh_token"], "subject_types_supported": ["public"], "id_token_signing_alg_values_supported": ["RS256"], "scopes_supported": ["openid"] }
- 为向
Oauth2资源服务
发起的请求添加Oauth2授权
,此处重点就是确保授权码默认认证获得的Oauth2授权
@GetMapping(value = "/authorize", params = "grant_type=authorization_code") public String authorizationCodeGrant(Model model, @RegisteredOAuth2AuthorizedClient("messaging-client-authorization-code") OAuth2AuthorizedClient authorizedClient) { String[] messages = this.webClient .get() .uri(this.messagesBaseUri) .attributes(oauth2AuthorizedClient(authorizedClient)) .retrieve() .bodyToMono(String[].class) .block(); model.addAttribute("messages", messages); return "index"; } @GetMapping(value = "/authorize", params = "grant_type=client_credentials") public String clientCredentialsGrant(Model model) { String[] messages = this.webClient .get() .uri(this.messagesBaseUri) .attributes(clientRegistrationId("messaging-client-client-credentials")) .retrieve() .bodyToMono(String[].class) .block(); model.addAttribute("messages", messages); return "index"; }
重点
当使用oauth2登录的时候,redis里面修改为存oauth2认证成功的
OAuth2AuthenticationToken
,
不然会导致确实oauth2登录状态丢失,后面无法退出;无法获取oauth2资源服务的资源
注意点
问题:项目重启后,使用旧有存于redis的自定义token。无法访问Oauth2资源,可以访问本系统资源
原因:我们采用InMemoryOAuth2AuthorizedClientService
保存Oauth2的已登录客户端,当我们服务器访问oauth2资源的时候需要通过当前token解析获得的Oauth-registerId来获取该客户端。
解决方案:使用JdbcOAuth2AuthorizedClientService
吐槽:该表的创建sql,用百度搜索是想都不要想,不可能找得到的。然而google却...
CREATE TABLE oauth2_authorized_client ( client_registration_id varchar(100) NOT NULL, principal_name varchar(200) NOT NULL, access_token_type varchar(100) NOT NULL, access_token_value blob NOT NULL, access_token_issued_at timestamp NOT NULL, access_token_expires_at timestamp NOT NULL, access_token_scopes varchar(1000) DEFAULT NULL, refresh_token_value blob DEFAULT NULL, refresh_token_issued_at timestamp DEFAULT NULL, created_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, PRIMARY KEY (client_registration_id, principal_name) );
/** * 自定义OAuth2已授权客户端服务 */ @Bean public JdbcOAuth2AuthorizedClientService jdbcOAuth2AuthorizedClientService(JdbcTemplate jdbcTemplate, ClientRegistrationRepository clientRegistrationRepository) { return new JdbcOAuth2AuthorizedClientService(jdbcTemplate, clientRegistrationRepository); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律