【Spring Security】AuthenticationFailureHandler 用户认证失败后处理

文章目录

前言

AuthenticationFailureHandler 主要是做用户认证失败后调用的处理器,这里的失败一般是指用户名或密码错误。当出现错误后,该处理器就会被调用,一般在开发中,会自己实现一个处理器,用来给前端返回一些已经商量好的异常码,下面分成两大块,先简单介绍一下官方给的一些用户失败后的处理器,再介绍我们自己实现的自定义处理器。

简单介绍官方默认用户认证失败后处理器

SimpleUrlAuthenticationFailureHandler

当认证失败后,重定向到一个指定的URL。

java 复制代码
@Override
protected void configure(HttpSecurity http) throws Exception {
	CorsConfiguration configuration = new CorsConfiguration();
	configuration.setAllowCredentials(true);
	http
		// 登录
		.formLogin()
			// 认证失败后处理器
			.failureHandler(authenticationFailureHandler());
}

@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
	SimpleUrlAuthenticationFailureHandler handler = new SimpleUrlAuthenticationFailureHandler();
	// 认证失败后重定向的URL
	handler.setDefaultFailureUrl("/login?error=true");
	return handler;
}

ForwardAuthenticationFailureHandler

认证失败后转发到一个指定的URL。

java 复制代码
@Override
protected void configure(HttpSecurity http) throws Exception {
	CorsConfiguration configuration = new CorsConfiguration();
	configuration.setAllowCredentials(true);
	http
		// 登录
		.formLogin()
			// 认证失败后处理器
			.failureHandler(authenticationFailureHandler());
}

@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
	// 认证失败后转发的URL
	return new ForwardAuthenticationFailureHandler("/login-error");
}

ExceptionMappingAuthenticationFailureHandler

认证失败中根据发生的异常类型映射到不同的处理逻辑或URL。

java 复制代码
@Override
protected void configure(HttpSecurity http) throws Exception {
	CorsConfiguration configuration = new CorsConfiguration();
	configuration.setAllowCredentials(true);
	http
		// 登录
		.formLogin()
			// 认证失败后处理器
			.failureHandler(authenticationFailureHandler());
}

@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
	ExceptionMappingAuthenticationFailureHandler handler = new ExceptionMappingAuthenticationFailureHandler();
	
	// 定义异常到URL的映射
	Map<String, String> exceptionMappings = new HashMap<>();
	exceptionMappings.put(IOException.class.getName(), "/login?error=io");
	exceptionMappings.put(RuntimeException.class.getName(), "/login?error=runtime");
	// 更多映射...
	
	handler.setExceptionMappings(exceptionMappings);
	// 当找不到映射时默认的URL
	handler.setDefaultFailureUrl("/login?error=def");
	
	return handler;
}

DelegatingAuthenticationFailureHandler

认证过程中发生的异常来委派给不同的 AuthenticationFailureHandler 实现。

java 复制代码
@Override
protected void configure(HttpSecurity http) throws Exception {
	CorsConfiguration configuration = new CorsConfiguration();
	configuration.setAllowCredentials(true);
	http
		// 登录
		.formLogin()
			// 认证失败后处理器
			.failureHandler(authenticationFailureHandler());
}

@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
	LinkedHashMap<Class<? extends AuthenticationException>, AuthenticationFailureHandler> failureHandlers = new LinkedHashMap<>();
	// 使用重定向
	failureHandlers.put(BadCredentialsException.class, new SimpleUrlAuthenticationFailureHandler("/login?error=bad_credentials"));
	// 使用转发
	failureHandlers.put(LockedException.class, new ForwardAuthenticationFailureHandler("/login-error"));
	// 更多映射...
	        
	return new DelegatingAuthenticationFailureHandler(
                failureHandlers,
                // 默认策略
                new SimpleUrlAuthenticationFailureHandler("/login?error=def"));
}

自定义使用

java 复制代码
package com.security.handler.auth;

import com.alibaba.fastjson2.JSON;
import com.security.controller.vo.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
@Slf4j
public class AuthenticationFailureHandlerImpl implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        log.info("AuthenticationFailureHandlerImpl 登录认证失败时调用 ...");
        
        /**
         * 设置响应状态值
         */
        response.setStatus(402);
        response.setContentType("application/json");
        response.setCharacterEncoding("utf-8");
        String json = JSON.toJSONString(
                ResponseResult.builder()
                        .code(402)
                        .message("认证失败!")
                        .build());

        // JSON信息
        response.getWriter().println(json);
    }

}

SecurityConfiguration 配置

java 复制代码
package com.security.config;

import com.security.handler.auth.AuthenticationFailureHandlerImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.web.cors.CorsConfiguration;

@Configuration
@EnableWebSecurity
// 开启限制访问资源所需权限
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfigurationTest extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        http
                // 登录
                .formLogin()
                // 认证失败后处理器
                .failureHandler(authenticationFailureHandler());
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
    	// 自定义的失败后的处理器
        return new AuthenticationFailureHandlerImpl();
    }
}

End

相关推荐
BD_Marathon2 小时前
【Flink】部署模式
java·数据库·flink
鼠鼠我捏,要死了捏5 小时前
深入解析Java NIO多路复用原理与性能优化实践指南
java·性能优化·nio
ningqw5 小时前
SpringBoot 常用跨域处理方案
java·后端·springboot
你的人类朋友5 小时前
vi编辑器命令常用操作整理(持续更新)
后端
superlls5 小时前
(Redis)主从哨兵模式与集群模式
java·开发语言·redis
胡gh5 小时前
简单又复杂,难道只能说一个有箭头一个没箭头?这种问题该怎么回答?
javascript·后端·面试
一只叫煤球的猫6 小时前
看到同事设计的表结构我人麻了!聊聊怎么更好去设计数据库表
后端·mysql·面试
uzong6 小时前
技术人如何对客做好沟通(上篇)
后端
叫我阿柒啊7 小时前
Java全栈工程师面试实战:从基础到微服务的深度解析
java·redis·微服务·node.js·vue3·全栈开发·电商平台
颜如玉7 小时前
Redis scan高位进位加法机制浅析
redis·后端·开源