Springboot实现自定义过滤器

1cklez4t  于 2023-04-19  发布在  Spring
关注(0)|答案(1)|浏览(205)

我需要帮助实现一个自定义过滤器上的Spring.我需要强制密码更改时,需要这样做.基本上用户应该不能去任何地方,除了密码重置页面.然而,我得到:太多的重定向错误消息和密码更改是没有做任何事情。

我的配置类如下:

public class SecurityConfiguration {
    
        @Autowired
        private UserService userService;
    
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        public AuthenticationProvider daoAuthenticationProvider() {
            DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
            provider.setPasswordEncoder(passwordEncoder());
            provider.setUserDetailsService(userDetailsService());
            return provider;
        }
    
        @Bean
        public UserDetailsService userDetailsService() {
            return new AppUserDetailsService();
        }
    
        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    
            http.authorizeHttpRequests(request ->
                            request.requestMatchers("/login", "/", "/css/**", "/login","/login.do", "/api/**").permitAll()
                                    .anyRequest().authenticated()
                    )
                    //.csrf().disable()
                    .formLogin(form -> form
                            .loginPage(LOGIN_URL)
                            .loginProcessingUrl("/login.do")
                            .failureUrl("/login?error")
                            .usernameParameter("username")
                            .passwordParameter("password")
                            .defaultSuccessUrl("/home"))
                    .logout(logout -> logout
                            .permitAll()
                            .logoutUrl("/logout")
                            .invalidateHttpSession(true)
                            .deleteCookies("JSESSIONID")
                            .logoutSuccessUrl("/login?logout"));
                   
            http.addFilterAfter(forcePasswordChangeFilter(), BasicAuthenticationFilter.class);
    
            return http.build();
        }
    
        @Bean
        public WebSecurityCustomizer webSecurityCustomizer() {
            return (web) -> web.ignoring().requestMatchers(
                    "/resources/**",
                    "/static/**",
                    "/css/**",
                    "/js/**",
                    "/assets/**",
                    "/img/**",
                    "/images/**",
                    "/api/**"
            );
        }
    
        @Bean
       public ForcePasswordChangeFilter forcePasswordChangeFilter(){
            return new ForcePasswordChangeFilter(userService);
        }
    
    
    }

我的自定义过滤器类如下:

public class ForcePasswordChangeFilter extends GenericFilter {
    
        private final UserService userService;
    
        public ForcePasswordChangeFilter(UserService userService) {
            this.userService = userService;
        }
    
        @Override
        public void doFilter(ServletRequest request,
                             ServletResponse response,
                             FilterChain chain) throws IOException, ServletException {
            if (userService.isAuthenticated()) {
                User user  = userService.authenticatedUser();
                if (user.getShouldChangePassword()) {
                    var httpResponse = (HttpServletResponse) response;
                    httpResponse.sendRedirect("/change-password");
                    return;
                }
            }
            chain.doFilter(request, response);
        }
    }

这是我的控制器:

@Controller
    public class AuthController {
    
        @Autowired
        private UserService userService;
    
        @GetMapping(value = {"", "/"})
        public String index() {
            return "redirect:login";
        }
    
        @GetMapping(value = {"/login"})
        public String login(HttpServletRequest request, Model model) throws IOException {
            if (userService.isAuthenticated()) {
                return "redirect:/home";
            }
            return "auth/login";
        }
    
        @GetMapping(value = { "/change-password"})
        public String changePassword(Model model) {
            return "auth/change-password";
        }
    
        @PostMapping(value = {"/change-password"})
        public String changePasswordSave(HttpServletRequest request, Model model) throws IOException {
            //validations and save
            return "redirect:/home";
        }
    }

我可能会错过什么?任何帮助都很感激。

6ojccjat

6ojccjat1#

好吧,我想我找到了一个解决方案。我不得不从过滤器本身排除网址。
因此,我的自定义过滤器将更改为:

public class ForcePasswordChangeFilter extends GenericFilter {

    private final UserService userService;

    public ForcePasswordChangeFilter(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        if (userService.isAuthenticated()) {
            User user  = userService.authenticatedUser();
            if (user.getShouldChangePassword()) {

                HttpServletRequest httpServletRequest = (HttpServletRequest) request;
                String path = httpServletRequest.getRequestURI();

                if ("/change-password".equals(path)) {
                    chain.doFilter(request, response);
                    return;
                }

                var httpResponse = (HttpServletResponse) response;
                httpResponse.sendRedirect("/change-password");
                return;
            }
        }
        chain.doFilter(request, response);
    }

}

我希望这将有助于在未来的人!

相关问题