当前位置: 首页 > 知识库问答 >
问题:

ReactiveSecurityContextHolder不返回经过身份验证的用户

曹兴贤
2023-03-14

我正在尝试在反应式Spring Boot应用程序中配置Spring Security性,并包括依赖于新的Spring Security版本5.0.0的父项目。RC1:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.M6</version>
</parent>

我将我的Spring WebSecurity配置为使用自定义AuthenticationFilter来检索我的身份验证信息,以及使用我自己的提供者的自定义AuthenticationManager。

配置:

@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebSecurityConfig {

    private ServerAuthenticationEntryPoint entryPoint = new CustomServerAuthenticationEntryPoint();

    @Bean
    SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
        return http
            // we rely on method security
            .authorizeExchange()
                .anyExchange().permitAll()
            .and()
                .logout().disable()
                .authenticationManager(authenticationManager())
                //Override BasicAuthenticationEntryPoint
                .exceptionHandling().serverAuthenticationEntryPoint(this.entryPoint)
            .and()
                .addFilterAt(upmAuthenticationWebFilter(), SecurityWebFiltersOrder.AUTHENTICATION)
            .build();
    }


    private ReactiveAuthenticationManager authenticationManager() {
        return new CustomReactiveAuthenticationManager()
            .authenticationProvider(new CustomAuthenticationProvider());
    }

    private AuthenticationWebFilter upmAuthenticationWebFilter() {
        try {
            AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(authenticationManager());
            authenticationFilter.setServerAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(this.entryPoint));
            authenticationFilter.setAuthenticationConverter(new CustomAuthenticationConverter(););

            return authenticationFilter;
        } catch (Exception e) {
            throw new BeanInitializationException("Could not initialize AuthenticationWebFilter.", e);
        }
    }
}

ReactiveAuthenticationManager:

public class CustomReactiveAuthenticationManager implements ReactiveAuthenticationManager {

    private List<AuthenticationProvider> authenticationProvider = new ArrayList<>();

    public CustomReactiveAuthenticationManager customAuthenticationProvider(
        final AuthenticationProvider customAuthenticationProvider) {
        this.authenticationProvider.add(customAuthenticationProvider);
        return this;
    }

    @Override
    public Mono<Authentication> authenticate(final Authentication authentication) {
        Class<? extends Authentication> toTest = authentication.getClass();
        for(AuthenticationProvider provider: authenticationProvider) {
            if (provider.supports(toTest)) {
                try {

                    //The provider returns a full authenticated Authentication object.
                    //With authentication.setAuthenticated(true);
                    return Mono.just(provider.authenticate(authentication));
                } catch (Exception e) {
                    return Mono.error(new BadCredentialsException("Invalid Credentials"));
                }
            }
        }
        return Mono.error(new ProviderNotFoundException("Unsupported Credentials"));
    }
}

当我现在对需要经过身份验证的用户的endpoint执行调用时。作为:

public interface HelloService {
    /**
     * This method returns just 'Hello, world!'.
     *
     * @return Return 'Hello, world!'.
     */
    @PreAuthorize("isAuthenticated()")
    Mono<String> getHelloWorld();
}

我总是收到401 AccessDenied异常

在PrePostAdviceReactiveMachodInterceptor第75行调试后

 auth -> this.preInvocationAdvice.before(auth, invocation, preAttr)

我看到传递的身份验证对象是匿名用户。

现在我的问题是:我是否忘了为ReactiveSecurityContext的使用配置一些东西?

上周,我仍然使用了之前的Milestonerrelease M5,其中反应式Spring Security包仍然位于额外的Spring Security反应下。在这种情况下,将检索身份验证对象,并可以完成我的请求。

共有2个答案

萧业
2023-03-14

由于设置存储库对我不起作用,我只是将主体添加到我的REST函数中:

@GetMapping("/select")
public Mono<String> select(java.security.Principal principal) {
     log.debug("Authorities: {}", ((Authentication) principal).getAuthorities());
}
唐茂实
2023-03-14

如果有人对问题感兴趣。

我没有在AuthenticationWebFilter中设置serverSecurityContextRepository。

所以设置这个解决了问题。

private AuthenticationWebFilter upmAuthenticationWebFilter() {
    try {
        AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(authenticationManager());
        authenticationFilter.setServerAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler(this.entryPoint));
        authenticationFilter.setAuthenticationConverter(new CustomAuthenticationConverter(););

        //Setting the Context Repo helped
        authenticationFilter.setServerSecurityContextRepository(new WebSessionServerSecurityContextRepository());

        return authenticationFilter;
    } catch (Exception e) {
        throw new BeanInitializationException("Could not initialize AuthenticationWebFilter.", e);
    }
}
 类似资料:
  • 我的代码在这里:代码重新发布是因为我想问一个更直接的问题。如何在未经身份验证的用户和经过身份验证的用户之间切换?我的未经验证的文件似乎已缓存,我使用了以下方法: 在我剩下的api代码之前,它仍然不能工作。谢谢你的帮助 注意:我知道它不起作用,因为我在切换配置/凭据提供程序后立即使用lambda进行调用,并且只有授权用户才能调用此方法。 编辑@behrooziAWS答案: API代码: 完整错误:B

  • 我想在创建新用户时添加用户的DisplayName。当我尝试使用updateProfile方法时,它会发出以下警告 ///更新用户的配置文件数据。 @已弃用('将在版本2.0.0中删除。''改用updatePhotoURL和updateDisplayName。', 你怎么能避开这个?? flutter: User(显示名称:null,电子邮件:test1@gmail.com,emailVerifi

  • 这是关于Flutter Firebase认证插件。< br >我试图在创建新用户后发送验证电子邮件,但sendEmailVerification()在内部使用currentUser()。这在我看来像是一个bug,但为了以防万一,我向stackoverflow提出了一个问题。错误在Android和IOS上是一样的。< br > 前两行返回Firebase User。第三个返回null。第四,如果第三

  • 经过身份验证的请求可用于获取授权代码令牌,以访问系统中的所有者资源。 对授权端点发出的请求会导致用户身份验证,并在向授权端点发送请求时提供明确的凭据。 经过身份验证的请求包含以下参数 - response_type - 这是一个必需参数,用于将值设置为'code',用于请求授权代码。 如果授权请求中没有'response_ type'参数,则授权服务器返回错误响应。 由于无效或不匹配的重定向URI

  • 我有一个Keycloak Cordova本地应用程序,一旦启动,就会正确显示Keycloak的用户名/密码表单,但在成功验证后,当试图重定向到该应用程序时,会显示err_connection_rejection。重定向当前设置为“http://localhost”。 我使用了这个例子https://github.com/keycloak/keycloak/tree/master/examples/

  • 当用户启动应用程序时,他们是一个未经身份验证的用户,并且他们将从iOS应用程序中的DeveloperAuthenticatedIdentityProvider类获得。我可以在cognito控制台中看到。但是,当他们登录时,我调用了我的nodejs后端,其登录映射为: 并使用以下后端代码: