我需要帮助在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";
}
}
我可能在哪里遗漏了它?如有任何帮助,不胜感激。
我想我找到解决办法了。我必须从过滤器本身中排除url。
所以我的自定义过滤器变成:
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);
}
}
我希望这将帮助别人在未来!