对于Sping Boot 与htmx的集成,如果传入的请求是由htmx完成的,并且用户不再登录,我需要一种方法来添加一个标头。
在正常的流程中,用户被重定向到登录页面。但是,当有一个由htmx完成的请求时,这是一个 AJAX 请求,重定向不会发生。
建议的解决方案是,如果请求中有HX-Request
标头,服务器应该在响应中放置一个HX-Refresh: true
标头,这将使htmx进行一次完整的页面刷新。
我的安全配置如下所示:
@Configuration
public class WebSecurityConfiguration {
private final ClientRegistrationRepository clientRegistrationRepository;
public WebSecurityConfiguration(ClientRegistrationRepository clientRegistrationRepository) {
this.clientRegistrationRepository = clientRegistrationRepository;
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(registry -> {
registry.mvcMatchers("/actuator/info", "/actuator/health").permitAll();
registry.mvcMatchers("/**").hasAuthority(Roles.ADMIN);
registry.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll();
registry.anyRequest().authenticated();
});
http.oauth2Client();
http.oauth2Login();
http.logout(logout -> logout.logoutSuccessHandler(oidcLogoutSuccessHandler()));
return http.build();
}
private LogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedLogoutSuccessHandler logoutSuccessHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
// Sets the location that the End-User's User Agent will be redirected to
// after the logout has been performed at the Provider
logoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}");
return logoutSuccessHandler;
}
}
我尝试使用筛选器:
public Filter htmxFilter() {
return new Filter() {
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
filterChain.doFilter(servletRequest, servletResponse);
String htmxRequestHeader = request.getHeader("HX-Request");
System.out.println("htmxRequestHeader = " + htmxRequestHeader);
System.out.println(response.getStatus());
if (htmxRequestHeader != null
&& response.getStatus() == 302) {
System.out.println("XXXXXXXXXXX");
response.setHeader("HX-Refresh", "true");
}
}
};
}
但是response.getStatus()
从来都不是302
(尽管我可以在Chrome中看到302响应状态)。
我也试过拦截器:
@Bean
public HandlerInterceptor htmxHandlerInterceptor() {
return new HandlerInterceptor() {
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
boolean htmxRequest = request.getHeader("HX-Request") != null;
String htmxRequestHeader = request.getHeader("HX-Request");
System.out.println("htmxRequestHeader = " + htmxRequestHeader);
System.out.println(response.getStatus());
if( htmxRequest && response.getStatus() == 302) {
response.setHeader("HX-Refresh", "true");
}
}
};
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeInterceptor());
registry.addInterceptor(htmxHandlerInterceptor());//.order(Ordered.HIGHEST_PRECEDENCE);
}
其中也不起作用,没有302响应状态。
我也尝试了注解掉的order(Ordered.HIGHEST_PRECEDENCE)
,但这并没有任何区别。
还有其他选择吗?
2条答案
按热度按时间vsaztqbk1#
当一个请求到达一个受保护的端点并且它没有被验证时,SpringSecurity执行它的
AuthenticationEntryPoint
s接口来开始一个验证方案。您可以建立自己的
AuthenticationEntryPoint
,将信头和委派加入到LoginUrlAuthenticationEntryPoint
(或您正在使用的其他实作)。noj0wjuj2#
您需要确保您的过滤器在任何Spring Security过滤器之前运行。请参见
SecurityProperties.DEFAULT_FILTER_ORDER
或HttpSecurity#addFilterBefore