Spring Cloud OAuth 微服务内部Token传递的源码实现解析

简介: 背景分析1.客户端携带认证中心发放的token,请求资源服务器A(Spring Security OAuth 发放Token 源码解析)2.客户端携带令牌直接访问资源服务器,资源服务器通过对token 的校验 ([Spring Cloud OAuth2 资源服务器CheckToken 源码解析](https://my.

背景分析

  • 1.客户端携带认证中心发放的token,请求资源服务器A(Spring Security OAuth 发放Token 源码解析)
  • 2.客户端携带令牌直接访问资源服务器,资源服务器通过对token 的校验 ([Spring Cloud OAuth2 资源服务器CheckToken 源码解析
    ](https://my.oschina.net/giegie/blog/3005999)) 判断用户的合法性,并保存到上下文中
  • 3.A服务接口接收到请求,需要通过Feign或者其他RPC框架调用B服务来组装返回数据

本文主要来探讨第三部 A --> B ,token 自定维护的源码实现

如何实现token 传递

配置OAuth2FeignRequestInterceptor 即可

  • 此类是Feign 的拦截器实现

@Bean
@ConditionalOnProperty("security.oauth2.client.client-id")
public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext,
                                                        OAuth2ProtectedResourceDetails resource,) {
    return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, resource);
}

源码解析

  • 获取上下文中的token ,组装到请求头
public class OAuth2FeignRequestInterceptor implements RequestInterceptor {
    // 给请求增加 token
    @Override
    public void apply(RequestTemplate template) {
        template.header(header, extract(tokenType));
    }
    
    protected String extract(String tokenType) {
        OAuth2AccessToken accessToken = getToken();
        return String.format("%s %s", tokenType, accessToken.getValue());
    }

    // 从spring security 上下文中获取token
    public OAuth2AccessToken getToken() {

        OAuth2AccessToken accessToken = oAuth2ClientContext.getAccessToken();
        if (accessToken == null || accessToken.isExpired()) {
            try {
                accessToken = acquireAccessToken();
            }
        }
        return accessToken;
    }

}
  • 再来看AccessTokenContextRelay, 上下文token 中转器.非常简单从上下文获取认证信息得到把 token 放到上下文
public class AccessTokenContextRelay {

    private OAuth2ClientContext context;

    public AccessTokenContextRelay(OAuth2ClientContext context) {
        this.context = context;
    }
    
    public boolean copyToken() {
        if (context.getAccessToken() == null) {
            Authentication authentication = SecurityContextHolder.getContext()
                    .getAuthentication();
            if (authentication != null) {
                Object details = authentication.getDetails();
                if (details instanceof OAuth2AuthenticationDetails) {
                    OAuth2AuthenticationDetails holder = (OAuth2AuthenticationDetails) details;
                    String token = holder.getTokenValue();
                    DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(
                            token);
                    String tokenType = holder.getTokenType();
                    if (tokenType != null) {
                        accessToken.setTokenType(tokenType);
                    }
                    context.setAccessToken(accessToken);
                    return true;
                }
            }
        }
        return false;
    }

}
  • 什么时候执行中转,oauth2 资源服务器非常简单暴力,加了个拦截器给转发。

源码非常简单

谈谈spring security oauth 实现的问题

  1. 当请求上线文没有Token,如果调用feign 会直接,这个OAuth2FeignRequestInterceptor 肯定会报错,因为上下文copy 失败
  2. 如果设置线程隔离,这里也会报错。导致安全上下问题传递不到子线程中。
  3. 强制使用拦截器去处理 token 转发到这里上下文,使用的业务场景只有这里,影响性能高

这三个问题,大家在使用的过程中一定会遇到

自定义OAuth2FeignRequestInterceptor

  • 通过外部条件是否执行token中转
public void apply(RequestTemplate template) {
    Collection<String> fromHeader = template.headers().get(SecurityConstants.FROM);
    if (CollUtil.isNotEmpty(fromHeader) && fromHeader.contains(SecurityConstants.FROM_IN)) {
        return;
    }

    accessTokenContextRelay.copyToken();
    if (oAuth2ClientContext != null
        && oAuth2ClientContext.getAccessToken() != null) {
        super.apply(template);
    }
}
  • 手动调用accessTokenContextRelay的copy,当然需要覆盖原生oauth 客户端的配置
目录
相关文章
|
算法 Java 微服务
【SpringCloud(1)】初识微服务架构:创建一个简单的微服务;java与Spring与微服务;初入RestTemplate
微服务架构是What?? 微服务架构是一种架构模式,它提出将单一应用程序划分为一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。 每个服务允许在其独立的进程中,服务于服务间采用轻量级的通信机制互相协作(通常是Http协议的RESTful API或RPC协议)。 每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据上下文,选择合适的语言、工具对其进行构建
876 126
|
负载均衡 算法 Java
【SpringCloud(2)】微服务注册中心:Eureka、Zookeeper;CAP分析;服务注册与服务发现;单机/集群部署Eureka;连接注册中心
1. 什么是服务治理? SpringCloud封装了Netfix开发的Eureka模块来实现服务治理 在传统pc的远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
626 0
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1711 3
|
监控 Java 数据库
从零学 Dropwizard:手把手搭轻量 Java 微服务,告别 Spring 臃肿
Dropwizard 整合 Jetty、Jersey 等成熟组件,开箱即用,无需复杂配置。轻量高效,启动快,资源占用少,内置监控、健康检查与安全防护,搭配 Docker 部署便捷,是构建生产级 Java 微服务的极简利器。
1285 117
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
760 1
|
jenkins Java 持续交付
使用 Jenkins 和 Spring Cloud 自动化微服务部署
随着单体应用逐渐被微服务架构取代,企业对快速发布、可扩展性和高可用性的需求日益增长。Jenkins 作为领先的持续集成与部署工具,结合 Spring Cloud 提供的云原生解决方案,能够有效简化微服务的开发、测试与部署流程。本文介绍了如何通过 Jenkins 实现微服务的自动化构建与部署,并结合 Spring Cloud 的配置管理、服务发现等功能,打造高效、稳定的微服务交付流程。
1348 0
使用 Jenkins 和 Spring Cloud 自动化微服务部署
|
Kubernetes Java 微服务
Spring Cloud 微服务架构技术解析与实践指南
本文档全面介绍 Spring Cloud 微服务架构的核心组件、设计理念和实现方案。作为构建分布式系统的综合工具箱,Spring Cloud 为微服务架构提供了服务发现、配置管理、负载均衡、熔断器等关键功能的标准化实现。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
1056 0

推荐镜像

更多
  • DNS