spring boot security 自定义AuthenticationProvider

spring boot security 自定义AuthenticationProvider

基于 spring boot 3.x

场景实现 手机验证码登陆

实现

CaptureCodeAuthenticationFilter

public class CaptureCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final String DEFAULT_LOGIN_URL = "/capture/login";

    private static final String DEFAULT_PHONE_NAME = "phone";
    private static final String DEFAULT_CODE_NAME = "code";

    private String codeParamName = DEFAULT_CODE_NAME;

    private String phoneParamName = DEFAULT_PHONE_NAME;

    public CaptureCodeAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(DEFAULT_LOGIN_URL, authenticationManager);
    }

    public CaptureCodeAuthenticationFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) {
        super(defaultFilterProcessesUrl, authenticationManager);

    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }
        String phone = obtainPhone(request);
        phone = (phone != null) ? phone.trim() : "";
        String code = obtainCaptureCode(request);
        code = (code != null) ? code : "";
        CaptureCodeAuthenticationToken token = new CaptureCodeAuthenticationToken(phone, code);
        return this.getAuthenticationManager().authenticate(token);
    }


    protected String obtainCaptureCode(HttpServletRequest request) {
        return request.getParameter(this.codeParamName);
    }


    protected String obtainPhone(HttpServletRequest request) {
        return request.getParameter(this.phoneParamName);
    }
}

CaptureCodeAuthenticationToken

public class CaptureCodeAuthenticationToken extends UsernamePasswordAuthenticationToken {
    public CaptureCodeAuthenticationToken(Object principal, Object credentials) {
        super(principal, credentials);
    }
}

CaptureCodeAuthenticationProvider

public class CaptureCodeAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

    @Override
    public boolean supports(Class<?> authentication) {
        return (CaptureCodeAuthenticationToken.class.isAssignableFrom(authentication));
    }

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        if (authentication.getPrincipal()==null){
            throw new BadCredentialsException("Bad credentials "+ authentication.getPrincipal().toString());
        }
        if (authentication.getCredentials()==null){
            throw new BadCredentialsException("Bad credentials "+ authentication.getPrincipal().toString());
        }
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        CaptureCodeAuthenticationToken token = (CaptureCodeAuthenticationToken) authentication;
        if (!token.getPrincipal().equals("tom")){
            throw new UsernameNotFoundException("username not fund!");
        }
        UserDetails user = User.withUsername("tom")
                .password("tom")
                .build();
        return user;
    }


}

配置 DefaultSecurityConfig

@Configuration
@EnableWebSecurity
public class DefaultSecurityConfig {

    @Autowired
    private ObjectMapper objectMapper;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(request -> request.anyRequest().authenticated());
        http.formLogin(Customizer.withDefaults());
        http.csrf(AbstractHttpConfigurer::disable);
        http.addFilterBefore(captureCodeAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    public CaptureCodeAuthenticationFilter captureCodeAuthenticationFilter() {
        ProviderManager providerManager = new ProviderManager(new CaptureCodeAuthenticationProvider());
        CaptureCodeAuthenticationFilter filter =
                new CaptureCodeAuthenticationFilter(providerManager);
        filter.setAuthenticationSuccessHandler((request, response, authentication) -> {
            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            response.getWriter().write(objectMapper.writeValueAsString(Result.ok("认证成功")));
            response.getWriter().flush();
        });
        filter.setAuthenticationFailureHandler((request, response, exception) -> {
            response.setStatus(HttpServletResponse.SC_OK);
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            response.getWriter().write(objectMapper.writeValueAsString(Result.ok("认证失败")));
            response.getWriter().flush();
        });
        return filter;
    }

    @Bean
    public UserDetailsService users(PasswordEncoder passwordEncoder) {
        UserDetails user = User.withUsername("admin")
                .password(passwordEncoder.encode("admin"))
                .build();
        return new InMemoryUserDetailsManager(user);
    }


    @Bean
    public PasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }

}

你可能感兴趣的:(spring,boot,spring,boot)