Problem Scenario:
After successful login, when performing a function operation (for example: System Management module Delete function), will go to perform userdetailsservice.loaduserbyusername again user authentication.
Problem version Spring security 4.04, 4.10
Source analysis found that basicauthenticationfilter.authenticationisrequired (username) always returns True (true means authentication is required)
Org.springframework.security.web.authentication.www.BasicAuthenticationFilter.class
Critical Code Analysis
@Overrideprotected 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);}
Further analysis of authenticationisrequired (String username), found that the problem in Existingauth.getname (). Equals (username) returns false each time, resulting in each authentication not passing.
Private Boolean authenticationisrequired (String username) {//Only reauthenticate if username doesn ' t match securityconte Xtholder 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 are 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 was 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; }
After debugging, I found that my original login account is uppercase and database consistent, the first time the account is capitalized unchanged, but after the second certification is automatically converted to lowercase, so that the verification does not pass.
Spring Security 4.1 Re-authentication issues after successful login