• spring security 使用自定义AuthenticationFailureHandler无法跳转failureUrl


    默认AuthenticationFailureHandler源码

    • org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer
    protected final void updateAuthenticationDefaults() {
    	if (loginProcessingUrl == null) {
    		loginProcessingUrl(loginPage);
    	}
    	if (failureHandler == null) {
    		// 默认使用/login?error
    		failureUrl(loginPage + "?error");
    	}
    
    	final LogoutConfigurer<B> logoutConfigurer = getBuilder().getConfigurer(
    			LogoutConfigurer.class);
    	if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) {
    		logoutConfigurer.logoutSuccessUrl(loginPage + "?logout");
    	}
    }
    public final T failureUrl(String authenticationFailureUrl) {
    	// 默认使用SimpleUrlAuthenticationFailureHandler
    	T result = failureHandler(new SimpleUrlAuthenticationFailureHandler(
    			authenticationFailureUrl));
    	// 此处保存失败url
    	this.failureUrl = authenticationFailureUrl;
    	return result;
    }
    protected final void updateAccessDefaults(B http) {
    	// 如果设置了permitAll,此处将设置保存的failureUrl为permitAll
    	if (permitAll) {
    		PermitAllSupport.permitAll(http, loginPage, loginProcessingUrl, failureUrl);
    	}
    }
    
    • org.springframework.security.config.annotation.web.configurers.PermitAllSupport
    public static void permitAll(
    	HttpSecurityBuilder<? extends HttpSecurityBuilder<?>> http, String... urls) {
    	for (String url : urls) {
    		if (url != null) {
    			// 此处使用的是完全匹配规则,因此/login与/login?error需要两条匹配规则
    			permitAll(http, new ExactUrlRequestMatcher(url));
    		}
    	}
    }
    private final static class ExactUrlRequestMatcher implements RequestMatcher {
    	private String processUrl;
    
    	private ExactUrlRequestMatcher(String processUrl) {
    		this.processUrl = processUrl;
    	}
    
    	public boolean matches(HttpServletRequest request) {
    		String uri = request.getRequestURI();
    		String query = request.getQueryString();
    
    		if (query != null) {
    			uri += "?" + query;
    		}
    		// 必须uri与query完全匹配
    		if ("".equals(request.getContextPath())) {
    			return uri.equals(processUrl);
    		}
    
    		return uri.equals(request.getContextPath() + processUrl);
    	}
    
    	@Override
    	public String toString() {
    		StringBuilder sb = new StringBuilder();
    		sb.append("ExactUrl [processUrl='").append(processUrl).append("']");
    		return sb.toString();
    	}
    }
    

    使用自定义AuthenticationFailureHandler

    • org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer
    public final T failureHandler(
    		AuthenticationFailureHandler authenticationFailureHandler) {
    	// 此处清空了保存的failureUrl
    	this.failureUrl = null;
    	this.failureHandler = authenticationFailureHandler;
    	return getSelf();
    }
    

    总结

    1. 如果使用自定义AuthenticationFailureHandler继承SimpleUrlAuthenticationFailureHandler或进行类似的页面跳转,
      需在WebSecurityConfigurerAdapter中额外配置失败跳转url的访问控制规则
    http.authorizeRequests().antMatchers("/login?error").permitAll()
    
  • 相关阅读:
    无法在 Web 服务器上启动调试。调试失败,因为没有启用集成 Windows 身份验证。请
    .NET连接各种数据库的字符串
    修改远程桌面端口
    c#获取计算机信息
    ASP.NET 对路径的访问被拒绝
    关于.net 2.0数据库连接出错的一些经验
    Rose启动提示"java.lang.ClassNotFoundException"的解决
    Ext中的get、getDom、getCmp、getBody、getDoc的区别
    action中生成验证码图片
    extjs表格控件
  • 原文地址:https://www.cnblogs.com/luguojun/p/16132756.html
Copyright © 2020-2023  润新知