spring-boot - 从自定义 WebFlux loginForm 传递额外的登录参数
问题描述
我已经实现了一个自定义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
???
我发现这个示例在实现中看起来很简单,但它适用于 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
的扩展AuthenticationWebFilter
我能够做我想做的事。我现在遇到的问题是我没有默认入口点,而且很难知道我是否错过了该ServerHttpSecurity
课程为我做的其他事情。
解决方案
我试图让它更优雅,但它会做更多的工作。所以我满足于这个insed。你必须像你一样构建你的 SecurityWebFiler 链。但是在你创建它之后你必须发现AuthenticationWebFilter
它是一个负责创建authentication
对象的网络过滤器。并设置您自己的身份验证转换器。
@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;
}
}
推荐阅读
- android - 如何生成不同的调试 sha1-key
- php - 数组中的 Html 代码显示不正确?
- reactjs - 以编程方式附加组件
- python - 设置迷你 Dask 集群
- amazon-web-services - Amazon Corretto 11 不包括 jFX
- discord.js - Discord.js 将人移动到随机 VoiceChannel
- python - 如何在python ffmpeg中组合2个流
- android - Flutter cloud_firestore 包导致应用崩溃
- python - 在远程主机上执行时将标准输出写入文件
- regex - 正则表达式:如何捕获一组括号,而不是下一组