如何更改标准 spring 逻辑以在我需要的登录页面上显示错误?

问题描述 投票:0回答:1

当我在 loadUserByUsername 方法中抛出自定义异常 (AccountNotActivatedException) 时,Spring 将其包装在 InternalAuthenticationServiceException 中。一般来说,该方法中几乎所有的异常都会被封装到其中。 问题是这样的异常不能使用@ExceptionHandler(或任何其他,因为它包装了所有异常)来处理,并且它有自己的行为。 我需要准确了解用户在身份验证过程中遇到的错误,以便将其显示在视图上。 每种情况都应该有自己的错误文本,以向用户指示到底出了什么问题。

现在,据我了解,如果出现错误,它只是将“error”参数传递给请求并返回登录页面,我无法再与其交互。

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        User user = userRepository.findByUsername(username);

        if(user==null){
            throw  new UsernameNotFoundException("Unable to login. The email or password is incorrect");
        }
        if (!user.isEnabled()) {
            throw new AccountNotActivatedException(
                    "This account is not activated. " +
                            "To complete the registration, follow the link in the letter that was sent to your email address. " +
                            "We also recommend you check the \"Spam\" category."
            );
        }
        return new org.springframework.security.core.userdetails.User(
                user.getUsername(),
                user.getPassword(),
                user.isEnabled(),
                accountNonExpired,
                credentialsNonExpired,
                accountNonLocked,
                Collections.singleton(user.getRole()));
    }

这是我的 Spring 配置

public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
   http
           .anonymous(AbstractHttpConfigurer::disable)
           .authorizeHttpRequests(authorize -> authorize
                   .requestMatchers(PathRequest
                           .toStaticResources()
                           .atCommonLocations())
                   .permitAll()
                   .requestMatchers("/book/{bookId}/testResults")
                   .authenticated()
                   .anyRequest().permitAll())
           .formLogin(login ->login
                   .loginPage("/login")
                   .defaultSuccessUrl("/")
                   .permitAll())
           .logout(logout ->logout
                   .logoutUrl("/logout")
                   .logoutSuccessUrl("/login")
                   .invalidateHttpSession(true)
                   .deleteCookies("JSESSIONID")
                   .permitAll());
                /*.oauth2Login( oauth2->oauth2
                        .loginPage("/login"));*/
                      /*  .defaultSuccessUrl("/")
                        .userInfoEndpoint(userInfo-> userInfo
                                .oidcUserService(oidcUserService())));*/
   return http.build();
}

附注我还想问一下,Spring 本身是否真的在没有我的情况下检查登录名/密码,还是我应该自己检查,接受表单中的数据并访问数据库并使用控制器方法检查此数据。 现在我只是使用 Post 方法将信息传输到 /login 端点,并且没有针对此资源的 PostMapping

spring-boot authentication spring-mvc spring-security
1个回答
0
投票

我更改了此处理程序的行为,一切都按预期工作,但我不确定安全性。这有多允许和安全?

public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    private final RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        String errorMessage = determineErrorMessage(exception);

        redirectStrategy.sendRedirect(request, response, "/login?error=" + errorMessage);
    }

    private String determineErrorMessage(AuthenticationException exception) {
        if (exception instanceof DisabledException) {
            return "This account is not activated. " +
                    "To complete the registration, follow the link in the letter that was sent to your email address. " +
                    "We also recommend checking the 'Spam' category.";
        } else if (exception instanceof BadCredentialsException) {
            return "Invalid username or password.";
        } else {
            return "Authentication failed: " + exception.getMessage();
        }
    }
}


@GetMapping("/login")
    public String loginPage(@RequestParam(name = "error", required = false) String error, Model model) {
        if (error != null) {
            model.addAttribute("errorMessage", error);
        }
        return "login-page";
    }
© www.soinside.com 2019 - 2024. All rights reserved.