Springsecurity-7 – Custom AuthenticationProvider implements the graphic verification code

In the previous chapter, we showed you how to use filters to implement graph validation, which is at the Servlet level and easy to understand. So this time we will introduce another high-level implementation of graphical captcha provided by SpringSecurity, which is custom AuthenticationProvider.

The certification process

  • Filter Implements the graphical verification code

We are in

  • SpringSecurity authentication process source code analysis is introduced in the SpringSecurity authentication process

This describes the user information for the system, which is stored in the Principal of SpringSecurity. The body contains the permissions, details, and so on of all authenticated users. Encapsulate it in Authentication in SpringSecurity as follows

Public interface Authentication extends Principal, Serializable {/** * Get user permission * @return */ Collection<? extends GrantedAuthority> getAuthorities(); /** * Get the credentials used for the user password * @return */ Object getCredentials(); /** * user details * @return */ Object getDetails(); /** * user credential, usually the user name * @return */ Object getPrincipal(); /** * if user authenticated * @return */ Boolean isAuthenticated(); void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException; }Copy the code

Description:

  • Authentication contains the list of subject permissions, subject credentials, subject details, and whether the Authentication is successful, etc.

  • The AuthenticationProvider is defined by SpringSecurity as an authentication procedure

  • ProviderManager manages multiple AuthenticationProviders

UsernamePasswordAuthenticationFilter

We see UsernamePasswordAuthenticationFilter class found ways to set user information setDetails method

We can see from source authenticationDetailsSource is provided by AbstractAuthenticationProcessingFilter AbstractAuthenticationProcessingFilter part of the source Code is as follows

public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean implements ApplicationEventPublisherAware, MessageSourceAware { protected ApplicationEventPublisher eventPublisher; protected AuthenticationDetailsSource<HttpServletRequest, ? > authenticationDetailsSource = new WebAuthenticationDetailsSource(); . }Copy the code

WebAuthenticationDetailsSource

Used in UsernamePasswordAuthenticationFilter AuthenticationDetailsSource is a standard Web authentication source, carrying the user sessionId and IP address. The source code is shown below

Custom WebAuthenticationDetails

With HttpServletRequest, everything will be very smooth. For scenarios based on graphic captcha, we can inherit WebAuthenticationDetails and extend the required information. So we can customize WebAuthenticationDetails to store additional information.

/ * * * custom WebAuthenticationDetails store additional graphics validation information * / public class ImageCodeWebAuthenticationDetails extends WebAuthenticationDetails {/** * Whether the graphic information was successfully authenticated */ private Boolean imageCodeIsRight; public boolean getImageCodeIsRight(){ return imageCodeIsRight; } public ImageCodeWebAuthenticationDetails(HttpServletRequest request) { super(request); HttpSession session = request.getSession(); String sessionCode = (String) session.getAttribute(CaptchaController.SESSION_KEY); String inpuCode = request.getParameter("code"); if(! Stringutils. isEmpty(inpuCode)){// Clear the verification code. The verification code must be cleared whether the verification succeeds or fails, and the verification code session.removeAttribute("code") must be refreshed if the verification fails. if(! StringUtils.isEmpty(sessionCode)&& inpuCode.equalsIgnoreCase(sessionCode) ){ this.imageCodeIsRight=true; }}}}Copy the code

Custom AuthenticationDetailsSource.

@Component("imageCodeWebAuthenticationDetailsSource") public class ImageCodeWebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> { @Override public ImageCodeWebAuthenticationDetails buildDetails(HttpServletRequest context) { return new ImageCodeWebAuthenticationDetails(context); }}Copy the code

Customize the AuthenticationProvider.

@Component("imageCodeAuthenticationProvider") public class ImageCodeAuthenticationProvider extends DaoAuthenticationProvider { public ImageCodeAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { this.setUserDetailsService(userDetailsService); this.setPasswordEncoder(passwordEncoder); } @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {/ / for details ImageCodeWebAuthenticationDetails details = (ImageCodeWebAuthenticationDetails)authentication.getDetails(); // If the verification code is incorrect, throw an exception if(! The getImageCodeIsRight ()) {throw new ValidateCodeException (" captcha input error "); } super.additionalAuthenticationChecks(userDetails, authentication); }}Copy the code

Modifying configuration Classes

Want to apply custom AuthenticationProvider and AuthenticationDetailsSource, still have to finish the remaining in LearnSrpingSecurity configuration.

/ * * * security configuration class * / @ EnableWebSecurity public class LearnSrpingSecurity extends WebSecurityConfigurerAdapter {@autowired @Qualifier("imageCodeWebAuthenticationDetailsSource") private AuthenticationDetailsSource<HttpServletRequest,WebAuthenticationDetails> imageCodeWebAuthenticationDetailsSource; @Autowired @Qualifier("imageCodeAuthenticationProvider") private AuthenticationProvider imageCodeAuthenticationProvider;  /** * Authentication manager * 1. Authentication information provision mode (user name, password, and resource permission of the current user) * 2. Memory storage can be used, Also can use the database mode * @ param auth * @ throws the Exception * / @ Override protected void the configure (AuthenticationManagerBuilder auth) throws Exception { //super.configure(auth); auth.authenticationProvider(imageCodeAuthenticationProvider); } /** * Resource permission configuration (filter chain) : * 1. Blocked resources * 2. Role permissions corresponding to resources * 3. Customizing the login page, login request address, and error handling * 5. Customizing spring Security filters * @param HTTP * @throws Exception */ @Override Protected void configure(HttpSecurity HTTP) throws Exception {http.csrf().disable() // Disables cross-site CSRF attack defense, Later chapters will specifically explained. FormLogin () authenticationDetailsSource (imageCodeWebAuthenticationDetailsSource) .loginPage("/login/page")// Jump to this page once the user's request has no permission. LoginProcessingUrl ("/login/form")// The address of the action in the login form, UsernameParameter ("username")/// the name of the username input box in the login form, PasswordParameter ("password")// The name of the password input box in the form. Default password //. DefaultSuccessUrl ("/syslog")// Default path to hop after login authentication is successful //.failureHandler(failureHandler).and() .authorizerequests ().antmatchers ("/login/page","/code/image").permitall ()// Resource paths that can be accessed without login authentication .anyRequest().authenticated(); }}Copy the code

Main modifications as shown in figure

test


We use the browser to browse http://localhost:8888, enter the wrong verification code, the result is

If you think this article is good, welcome to pay attention to, like, collect support, your attention is my motivation!

Springboot sunflower treasure book

It mainly shares JAVA technology, including SpringBoot, SpingCloud, Docker, middleware and other technologies, as well as Github open source project

70 original articles

The public,

Original is not easy, reproduced please indicate the source, thank you for your support! If this article is useful to you, please forward and share!

This article uses the article synchronization assistant to synchronize