3

我正在为自己编写一个小型应用程序,并希望在 Spring Boot 中实现 2 因素身份验证。为此,请遵循本文的提示:https ://www.baeldung.com/spring-security-two-factor-authentication-with-soft-token

面临以下问题: 1)我根据这篇文章编写的代码不起作用。Spring Security 完全忽略 is2FaEnabled == true 并在任何情况下授权用户,即使尚未输入代码。

从这个线程中的日志来看,.authenticationDetailsS​​ource (authenticationDetailsS​​ource) 甚至没有进行验证。

2)如何实现:在授权过程中,首先检查是否启用了2FA,如果是,然后将用户引导到另一个URL或打开一个带有输入的模块,正确输入代码后,授权它?

这是我的源代码:

CustomWebAuthenticationDetailsS​​ource.java

@Component
public class CustomWebAuthenticationDetailsSource implements
        AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {

    @Override
    public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
        return new CustomWebAuthenticationDetails(context);
    }
}

CustomWebAuthenticationDetails.java

public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {

    @Getter
    private String verificationCode;

    public CustomWebAuthenticationDetails(HttpServletRequest request) {
        super(request);
        verificationCode = request.getParameter("code");
    }
}

CustomAuthenticationProvider.java

    public class CustomAuthenticationProvider extends DaoAuthenticationProvider {

        @Autowired
        private UserServiceImpl userServiceImpl;

        private Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);

        @Override
        public Authentication authenticate(Authentication auth)
                throws AuthenticationException {
        User user = userServiceImpl.findUserByEmail(auth.getName());

        String verificationCode
                = ((CustomWebAuthenticationDetails) auth.getDetails())
                .getVerificationCode();
        if ((user == null)) {
            throw new BadCredentialsException("Invalid username or password");
        }

        if (user.getIs2FaEnabled()) {
            Totp totp = new Totp(user.getTwoFaSecret());
            if (!isValidLong(verificationCode) || !totp.verify(verificationCode)) {
                throw new BadCredentialsException("Invalid verfication code");
            }
        }

        Authentication result = super.authenticate(auth);
        return new UsernamePasswordAuthenticationToken(
                user, result.getCredentials(), result.getAuthorities());
    }

    private boolean isValidLong(String code) {
        try {
            Long.parseLong(code);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

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

WebSecurityConfig.java

    @Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {


    // n.b https://stackoverflow.com/questions/1018797/can-you-use-autowired-with-static-fields
    private static UserDetailsServiceImpl userDetailsService;

    @Autowired
    private UserDetailsServiceImpl userDetailsServiceImpl;

    @PostConstruct
    private void init() {
        userDetailsService = this.userDetailsServiceImpl;
    }

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

    @Bean
    public DaoAuthenticationProvider authProvider() {
        CustomAuthenticationProvider authProvider = new CustomAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());
        return authProvider;
    }

    // Backend configuration
    @Configuration
    @Order(1)
    public static class BackendConfigurationAdapter extends WebSecurityConfigurerAdapter {

        /*@Autowired
        private UserDetailsServiceImpl userDetailsService;*/

        @Autowired
        private CustomWebAuthenticationDetailsSource authenticationDetailsSource;

        public BackendConfigurationAdapter() {
            super();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http
                    .antMatcher("/admin/**")
                    .antMatcher("/admin/**/**")
                    .authorizeRequests()
                    .anyRequest()
                    .hasAuthority("ADMIN_PRIVILEGE")


                    .and()
                        .formLogin()
                        .authenticationDetailsSource(authenticationDetailsSource)
                        .loginPage("/admin/login")
                        .loginProcessingUrl("/admin/login")
                        .usernameParameter("email")
                        .passwordParameter("password")
                        .defaultSuccessUrl("/admin/dashboard")
                        .failureUrl("/admin/login?authError")
                        .permitAll()

                    .and()
                        .rememberMe()
                        .rememberMeParameter("remember-me")
                        .tokenValiditySeconds(86400)

                    .and()
                        .logout()
                        .logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout"))
                        .logoutSuccessUrl("/admin/login")
                        .deleteCookies("JSESSIONID")

                    .and()
                        .exceptionHandling()
                        .accessDeniedPage("/403")

                    .and()
                        .csrf()
                        .ignoringAntMatchers("/admin/**");
        }

        @Override
        public void configure(WebSecurity web) {
            web.ignoring().antMatchers(


                    "/backend/css/**",
                    "/backend/js/**",
                    "/backend/fonts/**",
                    "/backend/images/**",
                    "/backend/init/**"

            );
        }


        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService);
        }

    }


    // Frontend Configuration
    @Configuration
    @Order(2)
    public static class FrontendConfigurationAdapter extends WebSecurityConfigurerAdapter {


        @Autowired
        private CustomWebAuthenticationDetailsSource authenticationDetailsSource;

        public FrontendConfigurationAdapter() {
            super();
        }

        protected void configure(HttpSecurity http) throws Exception {

            http
                    .authorizeRequests().mvcMatchers("/robots.txt").permitAll()
                    .antMatchers(
                            "/", "/auth", "/signup", "/restore", "/activation/**",
                            "/admin/login", "/admin_restore",
                            "/attachments/get/**",
                            "/sendMessage",
                            "/error",
                            "/page/**",
                            "/categories", "/categories/**",
                            "/terms/**", "/posts", "/posts/**"
                    ).permitAll()
                    .anyRequest().authenticated()

                    .and()
                        .formLogin()
                        .authenticationDetailsSource(authenticationDetailsSource)
                        .loginPage("/auth")
                        .loginProcessingUrl("/auth")
                        .usernameParameter("email")
                        .passwordParameter("password")
                        .defaultSuccessUrl("/")
                        .failureUrl("/auth?authError")
                        .permitAll()

                    .and()
                        .rememberMe()
                        .rememberMeParameter("remember-me")
                        .tokenValiditySeconds(86400)

                    .and()
                        .oauth2Login().defaultSuccessUrl("/")

                    .and()
                        .logout()
                        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                        .logoutSuccessUrl("/")
                        .deleteCookies("JSESSIONID")

                    .and()
                        .exceptionHandling()
                        .accessDeniedPage("/403")

                    .and()
                        .csrf()

                    .and()
                        .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)

                    .and()
                        .headers().frameOptions().sameOrigin();


        }

        @Override
        public void configure(WebSecurity web) {
            web.ignoring().antMatchers(
                    "/frontend/css/**",
                    "/frontend/js/**",
                    "/frontend/fonts/**",
                    "/frontend/images/**",
                    "/frontend/lib/**",
                    "/frontend/vendor/**"
            );
        }

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService);
        }



    }

}

提前致谢!

4

0 回答 0