如何在Spring(HTTP Basic认证)场景下禁用浏览器默认登录弹窗
解决方案
核心原因
浏览器触发默认HTTP Basic登录弹窗的条件是:收到响应码为401的请求,且响应头中携带WWW-Authenticate: Basic相关字段。你当前用的Spring Security默认HTTP Basic配置,认证失败时会自动返回该响应头,所以会触发弹窗。
后端配置修改步骤
1. 自定义认证入口点
新增一个自定义认证失败处理器,认证失败时返回401状态码,但不携带WWW-Authenticate头,同时可以返回自定义的JSON提示:
@Component public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write("{\"code\":401,\"message\":\"未登录或凭证已失效\"}"); } }
2. 替换原有Security配置中的HTTP Basic配置
在你的CustomWebSecurityConfigurerAdapter类中注入自定义入口点,修改HTTP相关配置:
@Autowired private CustomAuthenticationEntryPoint customAuthEntryPoint; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable().authorizeRequests() // 原有不需要认证的路径配置保持不变 .antMatchers(HttpMethod.POST, "/demo/users/save").permitAll() .antMatchers(HttpMethod.POST, "/demo/users/**").permitAll() .antMatchers(HttpMethod.POST, "/users/*/save").permitAll() .antMatchers(HttpMethod.DELETE, "/users/**").permitAll() .antMatchers(HttpMethod.POST, "/users/*/verify").permitAll() .antMatchers(HttpMethod.GET,"/users/**").permitAll() .antMatchers(HttpMethod.PUT,"/users/**").permitAll() .antMatchers("/css/**", "/js/**", "/img/**").permitAll() .antMatchers("/signup-page.html").permitAll() .antMatchers("/landing-page.html").permitAll() .anyRequest().authenticated() .and() .formLogin() .disable() .logout() .logoutUrl("/logout") .addLogoutHandler(logoutHandler) .logoutSuccessUrl("/landing-page.html") .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)) .permitAll() .and() // 自定义HTTP Basic的认证入口点 .httpBasic() .authenticationEntryPoint(customAuthEntryPoint) .and() // 全局异常处理也配置自定义入口点,覆盖默认行为 .exceptionHandling() .authenticationEntryPoint(customAuthEntryPoint); }
前端适配调整
Fetch请求可以保持原有逻辑,只需要在响应拦截中判断如果返回状态码为401,直接跳转到你自己的登录页面即可,示例:
fetch('/protected/api', { method: 'GET', credentials: 'same-origin', // 保持携带凭证 headers: { 'Authorization': 'Basic ' + btoa(username + ':' + password) } }).then(res => { if (res.status === 401) { // 跳转到自定义登录页 window.location.href = '/login.html'; return; } // 其他正常逻辑处理 })
修改完成后重启服务,认证失败时不会再返回触发弹窗的响应头,浏览器默认登录窗口就不会再弹出。
内容的提问来源于stack exchange,提问作者Patryk Szymon Młyńczak
相关产品推荐
相关产品推荐

