How implement Spring security when login page having more field apart from user name and password?

前端 未结 4 2310
后悔当初
后悔当初 2020-12-05 16:34

I have a login page where the user need put the below information VIN number,email, zip code and accessCode which they will get from different application.

So to val

4条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-12-05 17:01

    It is not the responisibility of UserDetailsService to validate the Authentication token. This is what an AuthenticationProvider does.

    So first leave your implementation of UserDetailsService the single responsibility of loading all the data of the user from the database by login:

    @Component
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        private final UserRepository userRepository;
    
        @Autowired
        public UserDetailsServiceImpl(UserRepository userRepository) {
            this.userRepository = userRepository;
        }
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            User user = null;
            try {
                user = userRepository.findByUsername(username);
            } catch (NotFoundException e) {
                throw new UsernameNotFoundException(String.format("No user found for username %s!", username);
            }
            retrun new UserDetailsImpl(user);
        }
    }
    

    Than to intercept additional parameters from a login form you need to implement AuthenticationDetailsSource. It may be a good idea to extend WebAuthenticationDetails, but you can have just any object returned by AuthenticationDetailsSource.

    @Component
    public class WebAuthenticationDetailsSourceImpl implements AuthenticationDetailsSource {
    
        @Override
        public MyWebAuthenticationDetails buildDetails(HttpServletRequest context) {
            // the constructor of MyWebAuthenticationDetails can retrieve
            // all extra parameters given on a login form from the request
            // MyWebAuthenticationDetails is your LoginDetails class
            return new MyWebAuthenticationDetails(context);
        }
    }
    

    And to do the validation implement your own AuthenticationProvider by either implementing the interface itself or extending AbstractUserDetailsAuthenticationProvider or DaoAuthenticationProvider:

    @Component
    public class UserDetailsAuthenticationProviderImpl extends AbstractUserDetailsAuthenticationProvider {
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            MyWebAuthenticationDetails detais = (MyWebAuthenticationDetails) authentication.getDetails();
            // verify the authentication details here !!!
            // and return proper authentication token (see DaoAuthenticationProvider for example)
        }
    }
    

    Than you just need to pass your implementations to AuthenticationManager and UsernamePasswordAuthenticationFilter.

    
        
    
    
    
    
    
    
    
    
        
    
    

    Hope this helps!

    P.S. Consider constructor injection over field injection! It's more testable and states the contract of the class better. See this discussion.

提交回复
热议问题