【问题标题】:Webflux with different authentication schemes具有不同身份验证方案的 Webflux
【发布时间】:2022-10-05 15:53:55
【问题描述】:

我刚得到一个需要维护的项目,我需要在资源服务器中添加对额外身份验证方案的支持。除了常规的Authentication: Bearer <jwt.token> 之外,还可以使用自定义的东西:Authentication: Custom <other.jwt.token>。两者都应该以不同的方式工作和处理。

是的,我知道 spring 可以处理多个提供程序,我知道我可以使用 ReactiveAuthenticationManager 但我被困在如何处理不透明令牌的 Custom 前缀。

为了清楚起见,我需要两者都工作 - 当然,需要以不同的方式处理:

GET /
Authorization: Bearer x.y.z

GET /
Authorization: Custom a.b.c

如果可能,我还想在WWW-Authorization 标头(即Bearer, Custom)中返回支持的身份验证协议列表。

有什么提示吗?谷歌搜索只会将我指向常规的东西,使用 Bearer 和无论我尝试什么,spring 都会自动用 401 拒绝我(当然,不处理令牌)。

谢谢。

  • getHeader(\"Authorization\")。检查它是否以Custom 开头,将其切断。与以完全相同的方式完成的 BASIC 或 BEARER 标头实际上没有什么不同。
  • 是的当然。但我的问题是在哪里?我在 spring 源代码或网络上找不到关于如何处理多个此类请求的合理示例。
  • 查看来源以及如何处理基本和承载。您可以创建自己的(并注册它)来处理您的自定义。
  • 好点子。事实上,我希望有一个这样的例子,但你的建议也很好。谢谢。我会这样做并在此处发布更新。

标签: spring authentication flux bearer-token


【解决方案1】:

我做了什么:

  • 我实现了不同的ReactiveAuthenticationManager,一个用于我需要的每个协议。像BearerReactiveAuthenticationManagerCustomReactiveAuthenticationManager 之类的东西,并把它们变成了@Components
  • 我还实现了ServerSecurityContextRepository 并从前一点注入了两个身份验证管理器。在我的身体里,我有类似的东西:
    @Override
    public Mono<SecurityContext> load(ServerWebExchange serverWebExchange) {
        ServerHttpRequest request = serverWebExchange.getRequest();
        String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);

        if (authHeader.startsWith("Bearer ")) {
            String authToken = authHeader.substring(7);
            Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
            return this.bearerReactiveAuthenticationManager.authenticate(auth)
                    .map(SecurityContextImpl::new);
        } else if (authHeader.startsWith("Custom ")) { {
            String authToken = authHeader.substring(7);
            Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
            return this.customReactiveAuthenticationManager.authenticate(auth)
                    .map(SecurityContextImpl::new);
        } else {
            log.debug("Could not identify the authentication header");
            return Mono.empty();
        }
    }

我的 SecurityConfig bean 看起来像这样:

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Slf4j
public class SecurityConfig {

    private final ServerSecurityContextRepository serverSecurityContextRepository;

    @Autowired
    public SecurityConfig(ServerSecurityContextRepository serverSecurityContextRepository) {
        this.serverSecurityContextRepository = serverSecurityContextRepository;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        http
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable()
                .securityContextRepository(serverSecurityContextRepository)
                .exceptionHandling()
                .authenticationEntryPoint((swe, e) -> Mono.fromRunnable(() -> swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED)))
                .accessDeniedHandler((swe, e) -> Mono.fromRunnable(() -> swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN)))

                .and().authorizeExchange();

       return http.build();
   }
}


【讨论】:

    猜你喜欢
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 2021-04-28
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多