我已经实现了自定义ReactiveAuthenticationManager
以便与我的formLogin
一起使用。
@Bean
public ReactiveAuthenticationManager reactiveAuthenticationManager() {
return new ReactiveAuthenticationManagerAdapter(this::authenticate);
}
private Authentication authenticate(Authentication authentication) throws AuthenticationException {
return new UsernamePasswordAuthenticationToken(
userId, password, authorities);
}
这很好,可以在适当的时候调用authenticate
函数。但是,我现在必须从登录表单中发送一个附加参数。我已经能够创建一个自定义登录表单,该表单将多余的参数发送到端点,但是如何将其包含在我从Authentication
获得的authenticate
对象中?
我发现this的示例在实现中看起来很直接,但是对于Spring MVC来说,我需要在WebFlux中进行。
更新:@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
http.csrf()
.disable()
.authorizeExchange()
.pathMatchers("/login/**")
.permitAll()
.pathMatchers("/**")
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.authenticationSuccessHandler(new RedirectServerAuthenticationSuccessHandler("/"))
.authenticationFailureHandler(this::onAuthenticationFailure)
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(logoutSuccessHandler("/bye"));
return http.build();
}
我现在有一些进步。通过不使用formLogin
上的默认ServerHttpSecurity
而是使用我自己的扩展WebFilter
的{{1}}不能执行我想要的事情。我现在遇到的问题是,我没有默认的入口点,也很难知道我是否会神奇地缺少AuthenticationWebFilter
类对我有用的其他东西。
答案 0 :(得分:0)
我尝试使它更优雅,但这将需要更多工作。因此,我为此受助了。您必须像构建一样构建SecurityWebFiler链。但是创建它之后,您必须找到此AuthenticationWebFilter
,它是一个负责创建authentication
对象的Web过滤器。并设置自己的身份验证转换器。
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange()
.anyExchange().authenticated()
.and()
.formLogin()
;
final SecurityWebFilterChain build = http.build();
build.getWebFilters().collectList().subscribe(
webFilters -> {
for (WebFilter filter : webFilters){
if(filter instanceof AuthenticationWebFilter){
AuthenticationWebFilter awf = (AuthenticationWebFilter) filter;
awf.setAuthenticationConverter(new CustomHttpBasicAuthenticationConverter());
}
}
}
);
return build;
}
HttpBasicAuthenticationConverter
的示例。老实说,我只是从spring源复制而来。希望有帮助。
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.function.Function;
public class CustomHttpBasicAuthenticationConverter implements Function<ServerWebExchange, Mono<Authentication>> {
private String usernameParameter = "username";
private String passwordParameter = "password";
@Override
public Mono<Authentication> apply(ServerWebExchange exchange) {
return exchange.getFormData()
.map( data -> createAuthentication(data));
}
private UsernamePasswordAuthenticationToken createAuthentication(
MultiValueMap<String, String> data) {
String username = data.getFirst(this.usernameParameter);
String password = data.getFirst(this.passwordParameter);
return new UsernamePasswordAuthenticationToken(username, password);
}
public void setUsernameParameter(String usernameParameter) {
Assert.notNull(usernameParameter, "usernameParameter cannot be null");
this.usernameParameter = usernameParameter;
}
public void setPasswordParameter(String passwordParameter) {
Assert.notNull(passwordParameter, "passwordParameter cannot be null");
this.passwordParameter = passwordParameter;
}
}