解析SpringSecurity自定义登录验证成功与失败的结果处理问题

作者:字母哥博客 时间:2021-09-01 16:42:59 

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

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

  • 当我们登录成功的时候,是由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

总结

以上所述是小编给大家介绍的SpringSecurity自定义登录验证成功与失败的结果处理网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

来源:https://www.cnblogs.com/zimug/archive/2019/11/20/11895429.html

标签:spring,security,登录,验证
0
投稿

猜你喜欢

  • java文字转语音播报功能的实现方法

    2022-05-08 18:44:41
  • C#ComboBox控件“设置 DataSource 属性后无法修改项集合”的解决方法

    2021-06-04 20:11:14
  • Unity3D实现物体排成弧行

    2022-10-15 12:23:06
  • JAVA设计模式之责任链模式详解

    2023-10-28 21:54:47
  • 配置Android SDK

    2023-12-05 09:57:29
  • 解决运行jar包出错:ClassNotFoundException问题

    2021-09-09 04:58:41
  • Java 代理(Proxy)的原理及应用

    2023-08-21 08:40:41
  • Android自定义view实现有header和footer作为layout使用的滚动控件

    2023-07-31 19:29:54
  • spring boot中配置hikari连接池属性方式

    2022-11-13 06:06:44
  • Java基于IO流读取文件的方法

    2023-08-11 16:23:57
  • SpringSecurity整合jwt权限认证的全流程讲解

    2022-02-20 09:58:36
  • java实现递归菜单树

    2023-02-01 00:03:06
  • C# 基础入门--常量

    2022-01-29 18:54:53
  • Java继承Thread类创建线程类示例

    2023-08-04 20:27:08
  • springcloud gateway如何实现路由和负载均衡

    2023-01-09 07:13:35
  • MyBatis利用MyCat实现多租户的简单思路分享

    2022-08-16 18:58:33
  • C#如何实现调取钉钉考勤接口的功能

    2023-09-14 17:31:47
  • java发起http请求调用post与get接口的方法实例

    2022-12-28 23:22:58
  • 利用Matlab复刻羊了个羊小游戏

    2021-10-10 17:13:05
  • 浅谈HTTP使用BASIC认证的原理及实现方法

    2021-07-18 01:36:16
  • asp之家 软件编程 m.aspxhome.com