Security对接 sso服务总结——思路篇

功能

  1. 自定义登录线便于Oauth2登录服务出错时使用
  2. 自定义认证校验(授权对象存于redis,实现分布式认证)
  3. oauth2授权服务整合
  4. oauth2资源服务整合

代码地址

架构

  1. language:java
  2. framework:springframework + projectreactor + thymeleaf + webjars
  3. Build Tools:gradle

启动

  1. 拉取oauth2单点代码:https://gitee.com/jdw-silky/silky-sso-server.git
  2. 依次启动oauth2授权服务,oauth2资源服务

总结————思路篇

自定义登录实现逻辑

  1. 配置了自定义登录拦截器,
    拦截登录请求生成有效Authentication放入security上下文,redis保存 登录标识——Authentication

  2. 配置了自定义登录校验拦截器
    拦截带有登录标识的请求,通过该标识从redis获取Authentication,获取不到则代表redis已退出,清理security上下文

  3. 将这两个拦截器放到security拦截器链路中,FilterChainProxy

自定义登录+自定义授权实现逻辑

  1. 配置了自定义登录拦截器,
    拦截登录请求生成有效Authentication放入security上下文,redis保存 登录标识——Authentication
  2. 配置了自定义登录校验拦截器
    拦截带有登录标识的请求,通过该标识从redis获取Authentication,获取不到则代表redis已退出,清理security上下文
  3. 自定义访问决策处理器AccessDecisionProcessor,与默认的WebExpressionVoter构建访问决策管理器AccessDecisionManager
  4. 将新构建的访问决策管理器放入security配置中
  5. 将这两个拦截器放到security拦截器链路中,FilterChainProxy

自定义登录+自定义授权+Oauth2客户端登录授权+Oauth2资源服务实现逻辑

需求
自定义登录保留
未登录访问限制资源默认跳转Oauth2登录页面
Oauth2登录回来后需要达到与自定义登录一样的效果

登录授权

  1. 配置了自定义登录拦截器:拦截自定义登录请求生成有效Authentication放入security上下文,redis保存 登录标识——Authentication
  2. 配置了自定义登录校验拦截器:拦截带有登录标识的请求,通过该标识从redis获取Authentication,获取不到则代表redis已退出,清理security上下文
  3. 自定义访问决策处理器AccessDecisionProcessor,与默认的WebExpressionVoter构建访问决策管理器AccessDecisionManager
  4. 将新构建的访问决策管理器放入security配置中
  5. 将这两个拦截器放到security拦截器链路中,FilterChainProxy
  6. security开始Oauth2登录配置
  7. Oauth2登录添加自定义登录成功处理器,开启Oauth2登录
  8. 在Oauth2登录成功后,添加自定义登录成功处理器。进行自定义认证逻辑,合并自定义授权与Oauth2授权等操作

Oauth2服务整合

  1. 配置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"]
}
  1. 为向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却...
image-20211022191835119
image-20211022191914954

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);
}
posted @   临渊不羡渔  阅读(386)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示