You need to add a custom filter to inherit Usernamepasswordauthenticationfilter or Abstractauthenticationprocessingfilter.
Then specify the URL of the login in the custom filter. When setting a filter, you must specify a AuthenticationManager for the filter, and when the constructor is initialized, it is passed to the manager.
Write a provider and pass the custom Userdetailservice to the provider.
The specific implementation process is as follows:
To add a configuration:
@Override protected void Configure (Authenticationmanagerbuilder auth) { // Add custom userdetailservice Userdetailsauthenticationprovider.setuserdetailsservice (Userdetailsservice); // set up a provider Auth.authenticationprovider (userdetailsauthenticationprovider); }
Key configuration:
@Overrideprotected voidConfigure (Httpsecurity http)throwsException {//manually implemented rights validation managermovieauthorizeconfigprovidermanager.configure (Http.authorizerequests ()); //Add foreground login verification filter and Userdetailservice, different login processing URLs need to be specified in filterUserauthenticationfilter Userauthenticationfilter =NewUserauthenticationfilter (); //Each filter must specify a AuthenticationManagerUserauthenticationfilter.setauthenticationmanager (AuthenticationManager ()); //Set Logon success handling eventsUserauthenticationfilter.setauthenticationsuccesshandler (Movieauthenticationsuccesshandler); //set Logon failure handling eventsUserauthenticationfilter.setauthenticationfailurehandler (Movieauthenticationfailurehandler); Http.addfilterbefore (Userauthenticationfilter, Usernamepasswordauthenticationfilter.class);
}
Full configuration:
Custom filters:
Public classMyauthenticationfilterextendsUsernamepasswordauthenticationfilter { Public Static FinalString post = "POST"; PublicMyauthenticationfilter () { This. Setrequiresauthenticationrequestmatcher (NewAntpathrequestmatcher ("/user/login/check", "POST")); This. Setauthenticationmanager (Getauthenticationmanager ()); } @Override PublicAuthentication Attemptauthentication (HttpServletRequest request, httpservletresponse response)throwsauthenticationexception {if(!Request.getmethod (). Equals (POST)) { Throw NewAuthenticationserviceexception ("Authentication Method Not supported:" +Request.getmethod ()); } String username=Obtainusername (Request); String Password=Obtainpassword (Request); if(Username = =NULL) {username= ""; } if(Password = =NULL) {Password= ""; } username=Username.trim (); Usernamepasswordauthenticationtoken authrequest=Newusernamepasswordauthenticationtoken (username, password); //Allow subclasses to set the ' Details ' propertysetdetails (Request, authrequest); return This. Getauthenticationmanager (). Authenticate (Authrequest); }}
Provider:
@Component Public classUserdetailsauthenticationproviderextendsAbstractuserdetailsauthenticationprovider {Private volatileString Usernotfoundencodedpassword; Private Static FinalString User_not_found_password = "Usernotfoundpassword"; @AutowiredPrivatePasswordencoder Passwordencoder; PrivateUserdetailsservice Userdetailsservice; @Overrideprotected voidAdditionalauthenticationchecks (Userdetails userdetails, Usernamepasswordauthenticationtoken authentication)throwsauthenticationexception {if(authentication.getcredentials () = =NULL) { Throw Newbadcredentialsexception (Messages.getmessage ("Abstractuserdetailsauthenticationprovider.badcredentials", "Bad Credentials")); } String Presentedpassword=authentication.getcredentials (). toString (); if(!passwordencoder.matches (Presentedpassword, Userdetails.getpassword ())) {Logger.debug ("Authentication Failed:password does not match stored value"); Throw Newbadcredentialsexception (Messages.getmessage ("Abstractuserdetailsauthenticationprovider.badcredentials", "Bad Credentials")); }} @OverrideprotectedUserdetails Retrieveuser (String username, usernamepasswordauthenticationtoken authentication)throwsauthenticationexception {preparetimingattackprotection (); Try{userdetails Loadeduser= This. Getuserdetailsservice (). Loaduserbyusername (username); if(Loadeduser = =NULL) { Throw NewInternalauthenticationserviceexception ("Userdetailsservice returned null, which is an interface contract violation"); } returnLoadeduser; } Catch(Usernamenotfoundexception ex) {Mitigateagainsttimingattack (authentication); Throwex; } Catch(Internalauthenticationserviceexception ex) {Throwex; } Catch(Exception ex) {Throw Newinternalauthenticationserviceexception (Ex.getmessage (), ex); } } Private voidpreparetimingattackprotection () {if( This. Usernotfoundencodedpassword = =NULL) { This. Usernotfoundencodedpassword = This. Passwordencoder.encode (User_not_found_password); } } Private voidMitigateagainsttimingattack (Usernamepasswordauthenticationtoken authentication) {if(Authentication.getcredentials ()! =NULL) {String Presentedpassword=authentication.getcredentials (). toString (); This. Passwordencoder.matches (Presentedpassword, This. Usernotfoundencodedpassword); } } PublicUserdetailsservice Getuserdetailsservice () {returnUserdetailsservice; } Public voidSetuserdetailsservice (Userdetailsservice userdetailsservice) { This. Userdetailsservice =Userdetailsservice; }}
Userdetailservice:
@Component @slf4j@qualifier ("Normaluserdetailservice") Public classUserdetailserviceimplImplementsUserdetailsservice {Private FinalIuserdao Userdao; PublicUserdetailserviceimpl (Iuserdao Userdao) { This. Userdao =Userdao; } @Override PublicUserdetails Loaduserbyusername (String username)throwsusernamenotfoundexception {club.cearnach.movie.entity.User User=Userdao.findbyaccount (username). Orelsethrow (()-NewUsernamenotfoundexception ("The specified user cannot be found")); List<GrantedAuthority> authorities =authorityutils. Commaseparatedstringtoauthoritylist (Moviesecurityconstants.rol E_prefix.concat (User.getrole (). GetName ())); return NewUser (User.getaccount (), User.getpassword (), authorities); }}
Implementation of the second Userdetailservice:
@Component @qualifier ("Admindetailservice") Public classAdminuserdetailserviceimplImplementsUserdetailsservice {Private FinalIadminservice Adminservice; PublicAdminuserdetailserviceimpl (Iadminservice adminservice) { This. Adminservice =Adminservice; } @Override PublicUserdetails Loaduserbyusername (String username)throwsusernamenotfoundexception {Admin admin=Adminservice.findbyaccount (username). Orelsethrow (()-Newusernamenotfoundexception (Adminexception.admin_can_not_fount)); List<GrantedAuthority> authorities =authorityutils.commaseparatedstringtoauthoritylist (MovieSecurityConstants.ROLE_PREFIX.concat (admin.ge Trole (). GetName ()); return NewUser (Admin.getaccount (), Admin.getpassword (), authorities); }}
Spring Security multiple sign-in implementation