Spring security 4.1 登录成功后重复进行认证问题

问题场景:

登录成功后,在执行某个功能操作(例如:系统管理模块的删除功能时),会去执行UserDetailsService.loadUserByUsername 再次进行用户认证。

出现问题版本 Spring security 4.04  、 4.10

通过源码分析发现BasicAuthenticationFilter.authenticationIsRequired(username) 一直返回true (true表示需要认证)

org.springframework.security.web.authentication.www.BasicAuthenticationFilter.class

关键代码分析

@Override
	protected void doFilterInternal(HttpServletRequest request,
			HttpServletResponse response, FilterChain chain)
					throws IOException, ServletException {
		...
		try {
			...

			if (<span style="color:#ff0000;"><strong>authenticationIsRequired(username)</strong></span>) {
				UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
						username, tokens[1]);
				authRequest.setDetails(
						this.authenticationDetailsSource.buildDetails(request));
				Authentication authResult = this.authenticationManager
						.authenticate(authRequest);

				if (debug) {
					this.logger.debug("Authentication success: " + authResult);
				}

				SecurityContextHolder.getContext().setAuthentication(authResult);

				this.rememberMeServices.loginSuccess(request, response, authResult);

				onSuccessfulAuthentication(request, response, authResult);
			}

		}
		catch (AuthenticationException failed) {
			...
		}

		chain.doFilter(request, response);
	}

进一步分析authenticationIsRequired(String username),发现问题在existingAuth.getName().equals(username) 每次返回false,导致每次认证不通过。

private boolean authenticationIsRequired(String username) {
		// Only reauthenticate if username doesn't match SecurityContextHolder and user
		// isn't authenticated
		// (see SEC-53)
		Authentication existingAuth = SecurityContextHolder.getContext()
				.getAuthentication();

		if (existingAuth == null || !existingAuth.isAuthenticated()) {
			return true;
		}

		// Limit username comparison to providers which use usernames (ie
		// UsernamePasswordAuthenticationToken)
		// (see SEC-348)

		if (existingAuth instanceof UsernamePasswordAuthenticationToken
				&& !<strong><span style="color:#ff0000;">existingAuth.getName().equals(username)</span></strong>) {
			return true;
		}

		// Handle unusual condition where an AnonymousAuthenticationToken is already
		// present
		// This shouldn't happen very often, as BasicProcessingFitler is meant to be
		// earlier in the filter
		// chain than AnonymousAuthenticationFilter. Nevertheless, presence of both an
		// AnonymousAuthenticationToken
		// together with a BASIC authentication request header should indicate
		// reauthentication using the
		// BASIC protocol is desirable. This behaviour is also consistent with that
		// provided by form and digest,
		// both of which force re-authentication if the respective header is detected (and
		// in doing so replace
		// any existing AnonymousAuthenticationToken). See SEC-610.
		if (existingAuth instanceof AnonymousAuthenticationToken) {
			return true;
		}

		return false;
   }

通过调试后发现,我原先登录账号是大写和数据库一致,第一次登录时账号是大写没有改变,但到了第二次认证后却自动转为小写,所以导致验证不通过。

时间: 2024-08-27 19:05:17

Spring security 4.1 登录成功后重复进行认证问题的相关文章

spring security使用自定义登录界面后,不能返回到之前的请求界面的问题

昨天因为集成spring security oauth2,所以对之前spring security的配置进行了一些修改,然后就导致登录后不能正确跳转回被拦截的页面,而是返回到localhost根目录. 开始以为是被oauth2拦截了导致出了问题,但是security的拦截器是优先起作用的,所以这不可能. 最后实在没法只有打断点调试找毛病(下图为spring security登录后重定向至拦截前访问的url的实现原理流程) 图片是在这里看到的https://blog.csdn.net/zy_coo

Spring Security笔记:登录尝试次数限制

今天在前面一节的基础之上,再增加一点新内容,默认情况下Spring Security不会对登录错误的尝试次数做限制,也就是说允许暴力尝试,这显然不够安全,下面的内容将带着大家一起学习如何限制登录尝试次数. 首先对之前创建的数据库表做点小调整 一.表结构调整 T_USERS增加了如下3个字段: D_ACCOUNTNONEXPIRED,NUMBER(1) -- 表示帐号是否未过期D_ACCOUNTNONLOCKED,NUMBER(1), -- 表示帐号是否未锁定D_CREDENTIALSNONEXP

IdentityServer4 登录成功后,跳转到原来页面

IdentityServer4 登录成功后,默认会跳转到Config.Client配置的RedirectUris地址http://localhost:5003/callback.html,用于获取 Token,比如跳转后的地址: http://localhost:5003/callback.html#id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjkwYWRmOTliMDhmODExMjBiMzdlMWI1NzVmMDliODcwIiwidHlwIjoiSldUIn

使用Shiro登录成功后,跳转到之前访问的页面实现

转:http://blog.csdn.net/lhacker/article/details/20450855 很多时候,我们需要做到,当用户登录成功后,跳转回登录前的页面.如果用户是点击"登录"链接去到登录页面进行登录的,我们很容易跟踪用户的登录前的页面.比如,在"登录"链接后加一个url参数,如:http://www.xxx.com/login.html?url=http://www.xxx.com/xx.html,这个url就是当前页面.用户浏览不同页面,&q

spring boot系列--spring security (基于数据库)登录和权限控制

先说一下AuthConfig.java Spring Security的主要配置文件之一 AuthConfig 1 @Configuration 2 @EnableWebSecurity 3 public class AuthConfig extends WebSecurityConfigurerAdapter { 4 @Override 5 protected void configure(HttpSecurity httpSecurity) throws Exception { 6 http

为什么Spring Security看不见登录失败或者注销的提示

有很多人在利用Spring Security进行角色权限设计开发时,一般发现正常登录时没问题,但是注销.或者用户名时,直接就回到登录页面了,在登录页面上看不见任何提示信息,如"用户名/密码有误"或"注销成功". 那么如何做呢?很简单. 1.自定义安全配置类(继承自WebSecurityConfigurerAdapter) 在我们的自定义安全配置类中,需要做必要的设置,如下图: 上图中标红框的部分很关键: failureUrl("/login?error=t

spring security实现限制登录次数功能

本节是在基于注解方式进行的,后面的例子都会基于注解形式,不再实现XML配置形式,毕竟注解才是趋势嘛! 关键在于实现自定义的UserDetailsService和AuthenticationProvider 项目结构如下: 查看spring security的源代码可以发现默认security已经定义的user中的一些变量,鉴于此创建users表如下: CREATE TABLE users ( username VARCHAR(45) NOT NULL, password VARCHAR(45)

Spring Security 4 自定义登录表单 注解和XML例子(带源码)

上一篇文章: Spring Security 4 Hello World 基于注解 和 XML 例子 下一篇:Spring Security 4 退出 示例 原文地址:http://websystique.com/spring-security/spring-security-4-custom-login-form-annotation-example/ [已翻译文章,点击分类里面的spring security 4查看.] [ 翻译by 明明如月 QQ 605283073] 本文演示Sprin

jfianl 登录状态验证,未登录打开登录页面,登录成功后跳转到请求页面

项目中的一个需求,1.当用户提交预约信息时,如果未登录跳装到用户登录(注册)界面. 2.当登录(注册)成功后,跳转到请求页面 思路:1.增加登录状态验证拦截器,验证登录状态,如果未登录,获取请求路径,并保存在requset中,跳转登录(注册)页面 2.前台form中 增加 hiddent  input  .value为request中的请求路径 3.后台登录controller中验证,如登录(注册)成功则跳转到 请求路径 代码:1. public class LoginInterceptor i