Spring security is a large module, and this article only covers the authentication of custom parameters. Spring Security's default validation parameters are only username and password, which is generally not enough. Because of the time too long, some forget, there may be a little omission. All right, no nonsense.
Spring and spring security are configured with Javaconfig, which in turn is 4.2.5,4.0.4
General idea: Custom entrypoint, adding custom parameter extensions Authenticationtoken and authenticationprovider for validation.
First define the EntryPoint:
Import org.springframework.security.core.AuthenticationException;
Import Org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
Import javax.servlet.ServletException;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;
Import java.io.IOException;
public class Myauthenticationentrypoint extends Loginurlauthenticationentrypoint {public
Myauthenticationentrypoint (String loginformurl) {
super (Loginformurl);
}
@Override public
Void commence (HttpServletRequest request, httpservletresponse response, Authenticationexception authexception) throws IOException, servletexception {
super.commence (request, Response, authexception);
}
}
Next, Token,validcode is the CAPTCHA parameter:
Import Org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
public class Myusernamepasswordauthenticationtoken extends Usernamepasswordauthenticationtoken {
private String Validcode;
Public Myusernamepasswordauthenticationtoken (string principal, string credentials, string validcode) {
super ( Principal, credentials);
This.validcode = Validcode;
}
Public String Getvalidcode () {
return validcode;
}
public void Setvalidcode (String validcode) {
this.validcode = Validcode;
}
}
Continue to Processingfilter,
Import Com.core.shared.ValidateCodeHandle;
Import org.springframework.security.core.Authentication;
Import org.springframework.security.core.AuthenticationException;
Import Org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
Import Org.springframework.security.web.util.matcher.AntPathRequestMatcher;
Import javax.servlet.ServletException;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;
Import javax.servlet.http.HttpSession;
Import java.io.IOException; public class Myvalidcodeprocessingfilter extends Abstractauthenticationprocessingfilter {private String Usernamepara
m = "username";
Private String Passwordparam = "password";
Private String Validcodeparam = "Validatecode";
Public Myvalidcodeprocessingfilter () {Super (New Antpathrequestmatcher ("/user/login", "POST")); } @Override Public authentication attemptauthentication (HttpServletRequest request, HttpServletResponse Response) throws Authenticationexception, IOException, servletexception {String username = request.getparameter (
Usernameparam);
String password = request.getparameter (Passwordparam);
String Validcode = Request.getparameter (Validcodeparam);
Valid (Validcode, request.getsession ()); Myusernamepasswordauthenticationtoken token = new Myusernamepasswordauthenticationtoken (username, password,
Validcode);
Return This.getauthenticationmanager (). Authenticate (token); public void valid (String Validcode, HttpSession session) {if (Validcode = = null) {throw new V
Alidcodeerrorexception ("Verification code is empty!"); } if (!
Validatecodehandle.matchcode (Session.getid (), Validcode)) {throw new Validcodeerrorexception ("Wrong captcha!"); }
}
}
The
defines three parameters, which are used to receive the parameters of the login form, which gives the URL of login and the required post method
Next is authentication, here is not the authentication user name and password, only authentication code
Here is validatecodehandle a tool class and validcodeerrorexception:
Import Java.util.concurrent.ConcurrentHashMap;
public class Validatecodehandle {
private static concurrenthashmap Validatecode = new concurrenthashmap<> (); C2/>public static Concurrenthashmap GetCode () {
return validatecode;
}
public static void Save (string sessionId, String code) {
validatecode.put (sessionId, code);
}
public static string Getvalidatecode (String sessionId) {
Object obj = Validatecode.get (sessionId);
if (obj! = null) {
return string.valueof (obj);
}
return null;
}
public static Boolean Matchcode (String sessionId, String inputcode) {
string savecode = Getvalidatecode (sessionId);
if (savecode.equals (Inputcode)) {
return true;
}
return false;
}
}
It is necessary to inherit the authenticationexception to indicate that it is the authentication failure of security, so as to go through the subsequent failure process
Import org.springframework.security.core.AuthenticationException;
public class Validcodeerrorexception extends Authenticationexception {public
validcodeerrorexception (String msg) {
super (msg);
}
Public validcodeerrorexception (String msg, Throwable t) {
super (msg, t);
}
}
Next is provider:
Import org.springframework.security.authentication.BadCredentialsException;
Import Org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
Import Org.springframework.security.authentication.dao.DaoAuthenticationProvider;
Import org.springframework.security.core.AuthenticationException;
Import Org.springframework.security.core.userdetails.UserDetails; public class Myauthenticationprovider extends Daoauthenticationprovider {@Override public boolean supports (class
<?> authentication) {return MyUsernamePasswordAuthenticationToken.class.isAssignableFrom (authentication); } @Override protected void Additionalauthenticationchecks (Userdetails userdetails, Usernamepasswordauthenticat
Iontoken authentication) throws Authenticationexception {Object salt = null;
if (getsaltsource () = null) {salt = Getsaltsource (). GetSalt (Userdetails);
} if (authentication.getcredentials () = = null) { Logger.debug ("Authentication Failed:no credentials provided");
throw new Badcredentialsexception ("User name or password error!");
} String Presentedpassword = Authentication.getcredentials (). toString (); if (!this.getpasswordencoder (). Ispasswordvalid (Userdetails.getpassword (), Presentedpassword, salt)) {LOGGER.D
Ebug ("Authentication Failed:password does not match stored value");
throw new Badcredentialsexception ("User name or password error!"); }
}
}
Where the Supports method specifies that the logic of using the custom Token,additionalauthenticationchecks method and the parent class is exactly the same, I just changed the information returned by the exception.
The next step is to handle the handler of authentication success and authentication failure.
Import org.springframework.security.core.Authentication;
Import Org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
Import javax.servlet.ServletException;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;
Import java.io.IOException;
public class Frontauthenticationsuccesshandler extends Simpleurlauthenticationsuccesshandler {public
Frontauthenticationsuccesshandler (String defaulttargeturl) {
super (Defaulttargeturl);
}
@Override public
void onauthenticationsuccess (HttpServletRequest request, httpservletresponse response, Authentication authentication) throws IOException, servletexception {
super.onauthenticationsuccess (request, Response, authentication);
}
}
Import org.springframework.security.core.AuthenticationException;
Import Org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
Import javax.servlet.ServletException;
Import Javax.servlet.http.HttpServletRequest;
Import Javax.servlet.http.HttpServletResponse;
Import java.io.IOException;
public class Frontauthenticationfailurehandler extends Simpleurlauthenticationfailurehandler {public
Frontauthenticationfailurehandler (String defaultfailureurl) {
super (Defaultfailureurl);
}
@Override public
void Onauthenticationfailure (HttpServletRequest request, httpservletresponse response, Authenticationexception exception) throws IOException, servletexception {
super.onauthenticationfailure ( Request, response, exception);
}
}
Finally, the most important security config is:
Import Com.service.user.CustomerService;
Import Com.web.filter.SiteMeshFilter;
Import com.web.mysecurity.*;
Import org.springframework.beans.factory.annotation.Autowired;
Import Org.springframework.context.annotation.Bean;
Import org.springframework.context.annotation.Configuration;
Import Org.springframework.core.annotation.Order;
Import Org.springframework.security.authentication.AuthenticationManager;
Import Org.springframework.security.authentication.AuthenticationProvider;
Import Org.springframework.security.authentication.ProviderManager;
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.crypto.password.PasswordEncoder;
Import Org.springframework.security.crypto.password.StandardPasswordEncoder; Import org.springframework.seCurity.web.access.ExceptionTranslationFilter;
Import Org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
Import Org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
Import Org.springframework.web.filter.CharacterEncodingFilter;
Import Javax.servlet.DispatcherType;
Import javax.servlet.FilterRegistration;
Import Javax.servlet.ServletContext;
Import java.util.ArrayList;
Import Java.util.EnumSet;
Import java.util.List; @Configuration @EnableWebSecurity public class Securityconfig extends Abstractsecuritywebapplicationinitializer {@Be
A public Passwordencoder Passwordencoder () {return new Standardpasswordencoder ("MD5");
} @Autowired private CustomerService customerservice; @Configuration @Order (1) public static class Frontendwebsecurityconfigureadapter extends Websecurityconfigureradap ter {@Autowired private myvalidcodeprocessingfilter MyvalidcodeprocessingfilteR
@Override protected void Configure (Httpsecurity http) throws Exception {http.csrf (). Disable ()
. Authorizerequests (). Antmatchers ("/user/login", "/user/logout"). Permitall () . Anyrequest (). authenticated (). and (). Addfilterbefore (myvalidcodeprocess Ingfilter, Usernamepasswordauthenticationfilter.class). Formlogin (). LoginPage ("/u
Ser/login "). and (). Logout (). Logouturl ("/user/logout ")
. Logoutsuccessurl ("/user/login"); }} @Bean (name = "Frontauthenticationprovider") Public Myauthenticationprovider Frontauthenticationprovider (
) {Myauthenticationprovider Myauthenticationprovider = new Myauthenticationprovider ();
Myauthenticationprovider.setuserdetailsservice (CustomerService); MyauthenticationprovideR.setpasswordencoder (Passwordencoder ());
return myauthenticationprovider; } @Bean Public AuthenticationManager AuthenticationManager () {list<authenticationprovider> List =
New Arraylist<> ();
List.add (Frontauthenticationprovider ());
AuthenticationManager AuthenticationManager = new Providermanager (list);
return AuthenticationManager; } @Bean Public Myvalidcodeprocessingfilter myvalidcodeprocessingfilter (AuthenticationManager authenticationManage
R) {Myvalidcodeprocessingfilter filter = new Myvalidcodeprocessingfilter ();
Filter.setauthenticationmanager (AuthenticationManager);
Filter.setauthenticationsuccesshandler (Frontauthenticationsuccesshandler ());
Filter.setauthenticationfailurehandler (Frontauthenticationfailurehandler ());
return filter; } @Bean Public Frontauthenticationfailurehandler Frontauthenticationfailurehandler () {return new Frontau ThentIcationfailurehandler ("/user/login"); } @Bean Public Frontauthenticationsuccesshandler Frontauthenticationsuccesshandler () {return new Frontau
Thenticationsuccesshandler ("/front/test"); } @Bean Public Myauthenticationentrypoint Myauthenticationentrypoint () {return new myauthenticationentry
Point ("/user/login"); }
}
First, the bean,customerservice of a cryptographic class is a simple query user
@Service ("CustomerService") Public
class Customerserviceimpl implements CustomerService {
@Autowired
Private Userdao Userdao;
@Override public
userdetails loaduserbyusername (String username) throws Usernamenotfoundexception {
return Userdao.findcustomerbyusername (username);
}
}
Down is frontendwebsecurityconfigureadapter, rewrite the Configure method, first disable CSRF,
Turn on Authorization request authorizerequests (), where "/user/login", "/user/logout" Ignore permission authentication,
Other requests require a login authentication,
and then Addfilterbefore (), add my custom myvalidcodeprocessingfilter to the security default Usernamepasswordauthenticationfilter, That is, I certify my custom parameters first,
Then Formlogin (), configure the login URL and logout URL, login log out URL requires controller mapping, that is, to write your own controller.
Next is Authenticationprovider,authenticationmanager,processingfilter,authenticationfailurehandler, The Authenticationsuccesshandler,entrypoint bean displays the declaration.
Here's login.jsp.
<body> <div class= "Login_div" > <form:form autocomplete= "false" commandName= "Userdto" method= "POST" > <div> <span class= "Error_tips" ><b>${spring_security_last _exception.message}</b></span> </div> username:<form:input path= "username" cssclass= "
Form-control "/><br/> password:<form:password path=" password "cssclass=" Form-control "/><br/> Validatecode:<form:input path= "Validatecode" cssclass= "Form-control"/> <label>${validate_code}& lt;/label> <div class= "checkbox" > <label> <input type= "checkbox" Nam E= "Remember-me"/> Remember me </label> </div> <input type= "Submit" class= "BTN Btn-pri Mary "value=" Submit "/> </form:form> </div> </body>
The validation code fails when it is validcodeerrorexception, because it inherits Authenticationexception, Security at the time of verification encountered Authenticationexception will trigger Authenticationfailurehandler, the above Bean declared authentication failed to jump to the login URL, so login.jsp inside has ${spring_security_last_except