ReactiveSecurityContextHolder 没有 return 认证用户
ReactiveSecurityContextHolder does not return Authenticated User
我正在尝试在反应性 Spring 引导应用程序中配置 Spring 安全性,并包括依赖于新 Spring-安全版本 的父项目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"));
}
}
当我现在在需要经过身份验证的用户的端点上执行调用时。如:
public interface HelloService {
/**
* This method returns just 'Hello, world!'.
*
* @return Return 'Hello, world!'.
*/
@PreAuthorize("isAuthenticated()")
Mono<String> getHelloWorld();
}
我总是收到 401 AccessDenied 异常。
在第 75 行 PrePostAdviceReactiveMethodInterceptor 调试之后
auth -> this.preInvocationAdvice.before(auth, invocation, preAttr)
我看到传递的Authentication对象是匿名用户
现在我的问题是:
我是否忘记为 ReactiveSecurityContext 的使用配置一些东西?
上周我仍然使用以前的 MilestoneRelease M5,其中反应式 Spring-Security 包仍然位于额外的位置,在 Spring-Security-Reactive 下。在这种情况下,身份验证对象被检索并且我的请求可以完成。
如果有人对这个问题感兴趣。
我没有在 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);
}
}
由于设置存储库对我不起作用,我只是将主体添加到我的 REST 函数中:
@GetMapping("/select")
public Mono<String> select(java.security.Principal principal) {
log.debug("Authorities: {}", ((Authentication) principal).getAuthorities());
}
我正在尝试在反应性 Spring 引导应用程序中配置 Spring 安全性,并包括依赖于新 Spring-安全版本 的父项目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"));
}
}
当我现在在需要经过身份验证的用户的端点上执行调用时。如:
public interface HelloService {
/**
* This method returns just 'Hello, world!'.
*
* @return Return 'Hello, world!'.
*/
@PreAuthorize("isAuthenticated()")
Mono<String> getHelloWorld();
}
我总是收到 401 AccessDenied 异常。
在第 75 行 PrePostAdviceReactiveMethodInterceptor 调试之后
auth -> this.preInvocationAdvice.before(auth, invocation, preAttr)
我看到传递的Authentication对象是匿名用户
现在我的问题是: 我是否忘记为 ReactiveSecurityContext 的使用配置一些东西?
上周我仍然使用以前的 MilestoneRelease M5,其中反应式 Spring-Security 包仍然位于额外的位置,在 Spring-Security-Reactive 下。在这种情况下,身份验证对象被检索并且我的请求可以完成。
如果有人对这个问题感兴趣。
我没有在 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);
}
}
由于设置存储库对我不起作用,我只是将主体添加到我的 REST 函数中:
@GetMapping("/select")
public Mono<String> select(java.security.Principal principal) {
log.debug("Authorities: {}", ((Authentication) principal).getAuthorities());
}