SpringSecurity系列之自定义登录验证成功与失败的结果处理

40次阅读

共计 3353 个字符,预计需要花费 9 分钟才能阅读完成。

一、需要自定义登录结果的场景

在我之前的文章中,做过登录验证流程的源码解析。其中比较重要的就是

  • 当我们登录成功的时候,是由 AuthenticationSuccessHandler 进行登录结果处理,默认跳转到 defaultSuccessUrl 配置的路径对应的资源页面(一般是首页 index.html)。
  • 当我们登录失败的时候,是由 AuthenticationfailureHandler 进行登录结果处理,默认跳转到 failureUrl 配置的路径对应的资源页面(一般是登录页 login.html)。

但是在 web 应用开发过程中需求是千变万化的,有时需要我们针对登录结果做个性化处理,比如:

  • 我们希望不同的人登陆之后,看到不同的首页
  • 我们应用是前后端分离的,验证响应结果是 JSON 格式数据,而不是页面跳转

以上的这些情况,使用 Spring Security 作为安全框架的时候,都需要我们使用本节学到的知识进行自定义的登录验证结果处理。

二、自定义登陆成功的结果处理

为了满足上面的需求,我们该如何去做呢?下面一小节我们来说明一下。AuthenticationSuccessHandler 接口是 Security 提供的认证成功处理器接口,我们只需要去实现它即可。但是通常来说,我们不会直接去实现 AuthenticationSuccessHandler 接口,而是继承 SavedRequestAwareAuthenticationSuccessHandler 类,这个类会记住用户上一次请求的资源路径,比如:用户请求 books.html,没有登陆所以被拦截到了登录页,当你万成登陆之后会自动跳转到 books.html,而不是主页面。

@Component
public class MyAuthenticationSuccessHandler 
                        extends SavedRequestAwareAuthenticationSuccessHandler {

    // 在 application 配置文件中配置登陆的类型是 JSON 数据响应还是做页面响应
    @Value("${spring.security.logintype}")
    private String loginType;

    private  static ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, 
                                        HttpServletResponse response, 
                                        Authentication authentication) 
                                        throws ServletException, IOException {if (loginType.equalsIgnoreCase("JSON")) {response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(objectMapper.writeValueAsString(AjaxResponse.success()));
        } else {
            // 会帮我们跳转到上一次请求的页面上
            super.onAuthenticationSuccess(request, response, authentication);
        }
    }
}
  • 在上面的自定义登陆成功处理中,既适应 JSON 前后端分离的应用登录结果处理,也适用于模板页面跳转应用的登录结果处理
  • ObjectMapper 是 Spring Boot 默认集成的 JSON 数据处理类库 Jackson 中的类。
  • AjaxResponse 是一个自定义的通用的 JSON 数据接口响应类。

三、自定义登录失败的结果处理

这里我们同样没有直接实现 AuthenticationFailureHandler 接口,而是继承 SimpleUrlAuthenticationFailureHandler 类。该类中默认实现了登录验证失败的跳转逻辑,即登陆失败之后回到登录页面。我们可以利用这一点简化我们的代码。

@Component
public class MyAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    // 在 application 配置文件中配置登陆的类型是 JSON 数据响应还是做页面响应
    @Value("${spring.security.logintype}")
    private String loginType;

    private  static ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void onAuthenticationFailure(HttpServletRequest request,
                                        HttpServletResponse response, 
                                        AuthenticationException exception) 
                                        throws IOException, ServletException {if (loginType.equalsIgnoreCase("JSON")) {response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(
                    objectMapper.writeValueAsString(
                            AjaxResponse.error(
                                    new CustomException(
                                        CustomExceptionType.USER_INPUT_ERROR,
                                        "用户名或密码存在错误,请检查后再次登录"))));
        } else {response.setContentType("text/html;charset=UTF-8");
            super.onAuthenticationFailure(request, response, exception);
        }

    }
}
  • 在上面的自定义登陆失败处理中,既适应 JSON 前后端分离的应用登录失败结果处理,也适用于模板页面跳转应用的登录失败结果处理
  • 登陆失败之后,将默认跳转到默认的 failureUrl,即登录界面。

四、配置 SecurityConfig

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

   @Override
   protected void configure(HttpSecurity http) throws Exception {http.csrf().disable() // 禁用跨站 csrf 攻击防御,后面的章节会专门讲解
           .formLogin()
           .successHandler(myAuthenticationSuccessHandler)
           .failureHandler(myAuthenticationFailureHandler)
           .defaultSuccessUrl("/index")// 登录认证成功后默认转跳的路径
           .failureUrl("/login.html") // 登录认证是被跳转页面
}
  • 将自定义的 AuthenticationSuccessHandler 和 AuthenticationFailureHandler 注入到 Spring Security 配置类中
  • 使用 fromlogin 模式,配置 successHandler 和 failureHandler。
  • 并且配置 defaultSuccessUrl 和 failureUrl

期待您的关注

  • 博主最近新写了一本书:《手摸手教您学习 SpringBoot 系列 -16 章 97 节》
  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

正文完
 0