如何使用 Oauth2 使 API Gateway 的身份验证/授权过程无状态?

2023-12-07

在我的设计中,我有一个API网关(spring cloud api gateway)、授权服务器(Oauth2)和资源服务器(微服务)。 (我还有一个 CAS 服务器,但现在为了简单起见可以忽略它)

我只是想使用API​​网关来重定向客户端请求。

  • 如果用户未经过身份验证,则应将请求发送给授权 服务器以及经过身份验证和授权的过程是 完成后,授权服务器应返回 JSESSION 和 JWT access_token 标头。之后API网关应该返回JSESSION 并将 JWT 发送给客户端。
  • 如果用户经过身份验证,则应将请求发送到资源服务器。

所以API网关是无国籍的仅用于请求重定向。但是当我成功登录时,会设置 JSESSION 和 SESSION cookie,并且 JWT 不会发送到客户端。 (据日志了解,API Gateway有JWT,但不是简单地将其发送到客户端,而是将其与SESSION key一起存储并发送SESSION key)

如何使我的 API 网关无状态并将 access_token 标头中的 JWT 发送给客户端?

这是我的代码:

授权服务器:

@EnableWebSecurity
@Order(1)
public class MySecurityConfigurationDev extends WebSecurityConfigurerAdapter {

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/login/**", "/oauth/**", "/userinfo")
                .permitAll()
                .and()
                .formLogin().permitAll().and()
                .authorizeRequests().anyRequest().authenticated();
        http.csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("{noop}pass").roles("ADMIN");
    }
}

@Configuration
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Bean
    public KeyPair keyPair() {
        return new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "mystorepass".toCharArray()).getKeyPair("mytestkey");
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setKeyPair(keyPair());
        return converter;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager).accessTokenConverter(accessTokenConverter());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()").
                checkTokenAccess("permitAll()").
                allowFormAuthenticationForClients();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("first-client").secret("{noop}noonewilleverguess")
                .authorities("ADMIN")
                .authorizedGrantTypes("client_credentials", "password", "authorization_code", "refresh_token")
                .scopes("custom_mod")
                .accessTokenValiditySeconds(60*30)
                .refreshTokenValiditySeconds(60*60)
                .autoApprove(true)
                .redirectUris("http://localhost:8085/login/oauth2/code/login-client");
    }
}

API网关:

@EnableWebFluxSecurity
public class MySecurityConfiguration {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http, ReactiveClientRegistrationRepository clientRegistrationRepository) {
        http.authorizeExchange().anyExchange().authenticated().and().oauth2Login();
        return http.build();
    }
}

logging:
  level:
    root: TRACE
    org.springframework.cloud.gateway: DEBUG
    reactor.netty.http.client: DEBUG
    com.netflix.discovery.DiscoveryClient: error
    org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator: error
    com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver: error

server:
  port: 8085

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8010/eureka

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      default-filters:
      - RemoveRequestHeader=Cookie
      - TokenRelay=
      routes:
      - id: user_route
        predicates:
          - Path=/gateway-user/**
        filters:
          - RewritePath=/gateway-user/(?<segment>.*), /user/$\{segment}
          - RemoveRequestHeader=Cookie
          - name: Hystrix
            args:
              name: fallbackCommand
              fallbackUri: forward:/fallback/error
        uri: "lb://USER-RESOURCE-SERVER"
      - id: address_route
        predicates:
          - Path=/gateway-address/**
        filters:
          - RewritePath=/gateway-address/(?<segment>.*), /address/$\{segment}
        uri: "lb://ADDRESS-RESOURCE-SERVER"
  security:
    oauth2:
      client:
        registration:
          login-client:
            provider: uaa
            client-id: first-client
            client-secret: noonewilleverguess

            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
            scope: custom_mod
        provider:
          uaa:
            authorization-uri: http://localhost:8094/oauth/authorize
            token-uri: http://localhost:8094/oauth/token
            user-info-uri: http://localhost:8094/userinfo
            user-name-attribute: user_name
            user-info-authentication-method: form

**两台服务器的 Spring Boot 版本均为 2.1.6-RELEASE。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Oauth2 使 API Gateway 的身份验证/授权过程无状态? 的相关文章

随机推荐

  • 如何将操作栏选项卡向右对齐?

    我以编程方式添加了操作栏选项卡 我不知道如何将操作栏选项卡向右对齐 ActionBar bar getActionBar bar setNavigationMode ActionBar NAVIGATION MODE TABS instan
  • Google Apps 脚本中的 Cookie 处理 - 如何在标头中发送 Cookie?

    我正在尝试编写一个简单的脚本 从网页中获取文本并处理该字符串 但是 该网站要求我登录 我成功登录该网站 这是我登录的方式 var payload name1 val1 name2 val2 var opt payload payload m
  • 如何格式化 Winform 中 LostFocus 事件的所有文本框值

    我需要在失去焦点事件时向任何相关文本框值中每个数值的千位添加逗号 我创建了以下函数 public static void FormatNumerical this Control control if control is TextBox
  • 递归函数的复杂性 - 时间和空间

    我有兴趣知道如何计算递归函数的时间和空间复杂度 如排列 斐波那契 描述here 一般来说 我们可以在很多地方进行递归 而不仅仅是排列或递归 所以我正在寻找通常遵循的方法来计算时间和空间复杂度 谢谢 看一眼http www cs duke e
  • 带有 if 语句的函数中的全局变量

    好吧 我目前正在做一个用 python 制作二十一点游戏的项目 但遇到了一些麻烦 我的问题之一是我不知道何时将变量定义为全局变量 特别是在带有 if 语句的函数中 如果我在 if 语句之外有一个全局变量 我是否必须声明该变量在 if 语句内
  • 使用“import __main__”是个好习惯吗?

    我正在开发一个相对较大的 Python 应用程序 并且我希望将一些资源保留为可在多个不同模块中访问的全局变量 这些值包括版本号 版本日期 全局配置和一些资源的静态路径 我还包括了一个DEBUG由命令行选项设置的标志 以便我可以在调试模式下运
  • 需要有关流程的帮助

    当我开始像这样的过程时process Runtime getRuntime exec gnome terminal 它启动 shell 执行 我想停止 shell 执行并想从进程重定向 I O 有人能告诉我如何做到这一点吗 我的代码是 pu
  • 从 MFC 应用程序连接到 SQL Server Compact Edition (.sdf)

    我正在 Visual Studio 2008 中构建一个对纹理进行分类的 MFC 应用程序 我需要某种轻量级数据库来保存特征 只是一些双精度和字符串 这些特征可以是 在不同的计算机上携带该应用程序 能够从应用程序对其执行查询 搜索 更新 插
  • Cygwin 看到一个 Windows 看不到的文件——我想从 python 访问这个文件

    我有一个连接到 USB 的设备 它创建一个名为 Tpolling log 的日志文件 我可以通过 Cygwin 看到它 但通过 Windows 看不到它 隐藏文件设置为始终显示 我也无法从 python 访问它 我希望能够在 python
  • 在 GWT Web 应用程序中调用外部应用程序(即 Windows 计算器)

    当用户单击 GWT Web 应用程序中的按钮时 我尝试调用外部 Windows 应用程序 即 calc exe 有没有办法如何做到这一点 以下是我迄今为止已经尝试过的 1 尝试了 Runtime exec 和 ProcessBuilder
  • 使用 OpenMP 进行缩减:线性合并或日志(线程数)合并

    我有一个关于 OpenMP 缩减的一般性问题 这个问题困扰了我一段时间 我的问题是关于将部分金额合并到归约中 它可以线性地完成 也可以作为线程数的对数完成 假设我想减少一些功能double foo int i 有了 OpenMP 我就可以这
  • 是否可以覆盖表单助手?

    使用文档 我可以为我的字段的布局设置自己的助手 但我也想个性化游戏给出的一些字段 主要原因是 Twitter Bootstrap 2 我需要更改 在 checkbox scala html 中 input field args id nam
  • ReplayKit:从未进入 startRecording() 完成处理程序

    问题描述 尽管显示了 允许在 AppName 中进行屏幕录制 弹出窗口 但永远不会输入 startRecording 完成处理程序 偶尔会出现 允许在 AppName 中进行屏幕录制 弹出窗口 当我删除应用程序 重新启动设备并对项目进行清理
  • Oracle SQL - 回合 - 半场

    Oracle ROUND 函数默认 向上舍入 select 3 674 my number round 3 674 2 round on number from dual union select 3 675 my number round
  • Excel VBA 中 ExportAsFixedFormat 的 PDF 输出大小错误

    我使用 Excel 2010 和 VBA 我有以下代码 mySh PageSetup PaperSize xlPaperLetter mySh ExportAsFixedFormat Type xlTypePDF Filename file
  • 如何修复“ConnectionString 属性尚未初始化”

    当我开始我的应用程序时 我得到 ConnectionString 属性尚未初始化 网页配置
  • Phonegap Build:将图像下载到应用程序的文件夹之一

    如果我直接指定路径 我就可以下载图像 文件 存储 sdcard0 如何将图像保存到应用程序中的文件夹之一 我试过this设置应用程序路径的方法 但它对我不起作用 这是我到目前为止所使用的 如果您想将图像保存到 SD 卡 它可以工作 var
  • 有没有一种惯用的方法来缓存 Spark 数据帧?

    我有一个大型镶木地板数据集 正在使用 Spark 读取 读取后 我会筛选行的子集 这些行在应用不同转换的许多函数中使用 以下与我想要完成的逻辑相似但不完全逻辑 df spark read parquet file special rows
  • 强制/保护 POST 参数

    我的标题可能含糊不清 所以请检查下面我的情况 我有一个网络应用程序来管理员工列表 该应用程序采用中心辐射模式设置 单击员工列表中的员工会重定向到一个新窗口 显示所选员工的个人详细信息以进行可能的更新 该应用程序使用 HTTPS 通过 GET
  • 如何使用 Oauth2 使 API Gateway 的身份验证/授权过程无状态?

    在我的设计中 我有一个API网关 spring cloud api gateway 授权服务器 Oauth2 和资源服务器 微服务 我还有一个 CAS 服务器 但现在为了简单起见可以忽略它 我只是想使用API 网关来重定向客户端请求 如果用