​SpringSecurity-5-自定义登录验证

SpringSecurity-5-自定义登录验证

  • 默认登录成功失败跳转页

  • 为什么自定义登录验证结果处理场景

  • 自定义登录成功的结果处理

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

  • 自定义权限访问异常结果处理

默认登录成功失败跳转页

  • 如果我们 登录成功,由接口AuthenticationSuccessHandler进行登录结果处理,默认会使用SimpleUrlAuthenticationSuccessHandler,是AuthenticationSuccessHandler的实现类,SimpleUrlAuthenticationSuccessHandler核心代码如下
public class SimpleUrlAuthenticationSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler
  implements AuthenticationSuccessHandler {
 @Override
 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
   Authentication authentication) throws IOException, ServletException {
  handle(request, response, authentication);
  clearAuthenticationAttributes(request);
 }
}

在抽象类AbstractAuthenticationTargetUrlRequestHandler,我们可以发现,其默认**defaultTargetUrl = /**,核心代码如下

在本例子中我们的**/页面为inxde.html**,实现代码如下

 // 首页
 @RequestMapping({"/index", "/", ""})
 public String index() {
 return "index";
 }

因此登录成功后跳转到http://localhost:8080/,**如果我们不想默认跳转页面为/**,我们可以进行设置,如下图所示

  • 当登录失败的时候,是由AuthenticationfailureHandler进行登录结果处理,默认跳转到failureUrl配置的路径对应的资源页面(一般也是跳转登录页login.html,重新登录)。

为什么自定义登录验证结果处理场景

  • 前后端分离,后端返回结果应该是JSON

  • 实现千人千面(不同的人,登录后向不同的页面跳转)

自定义登录成功的结果处理

AuthenticationSuccessHandler完成登录成功处理
  • 创建MyAuthenticationSuccessHandler类直接实现AuthenticationSuccessHandler接口

注意:实现类上不要少了注解 @Component注解

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    private  static ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request,
                                        HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {

        // 当认证成功后,响应 JSON 数据给前端
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString("test登录成功"));
    }
}

在 LearnSrpingSecurity中注入 和 引用自定义认证成功处理器 MyAuthenticationSuccessHandler,实现代码如下

  • 测试

重启项目,访问http://localhost:8080跳转到登录页面,登录成功后结果为

继承SavedRequestAwareAuthenticationSuccessHandler实现登录成功处理

继承SavedRequestAwareAuthenticationSuccessHandler 类的话,他会记住我们上一次请求的资源路径,比如:用户请求syslog.html,没有登录所以被拦截到了登录页,当你登录成功之后会自动跳转到syslog.html,而不是主页面。代码实现如下

@Component
public class MySavedRequestAwareAuthenticationSuccessHandler  extends SavedRequestAwareAuthenticationSuccessHandler {

    //在application配置文件中配置登录的类型是JSON数据响应还是做页面响应
    @Value("${login.success.type}")
    private String loginType;
    //Jackson JSON数据处理类
    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("test Saved 登录成功"));
        } else {
            // 会帮我们跳转到上一次请求的页面上
            super.onAuthenticationSuccess(request, response, authentication);
        }
    }
}

在application.properties中配置login.success.type

login.success.type=HTML #设置为html或者json,如果为json返回json

  • 测试

使用浏览器访问http://localhost:8080/sysuser,登录成功后,页面显示为

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

AuthenticationFailureHandler实现登录失败验证
  • 创建MyAuthenticationFailureHandler类实现AuthenticationFailureHandler接口

注意:实现类上不要少了注解 @Component注解

@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    private  static ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        // 当认证失败后,响应 JSON 数据给前端
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString("test登录失败"));
    }
}

  • 在 LearnSrpingSecurity中注入 和 引用自定义认证成功处理器 MyAuthenticationFailureHandler,实现代码如下

  • 测试

访问http://localhost:8080/login/form,输入错误的用户名和密码,结果如下

SimpleUrlAuthenticationFailureHandler 实现登录失败处理

继承SimpleUrlAuthenticationFailureHandler 类。该类中默认实现了登录验证失败的跳转逻辑,即登录失败之后回到登录页面。我们可以利用这一点简化我们的代码。实现代码如下

@Component
public class MySimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    
    //在application配置文件中配置登录的类型是JSON数据响应还是做页面响应
    @Value("${login.success.type}")
    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("用户名或密码存在错误,请检查后再次登录"));
        } else {
            response.setContentType("text/html;charset=UTF-8");
            super.onAuthenticationFailure(request, response, exception);
        }

    }
}

其他步骤和AuthenticationFailureHandler实现登录失败验证的步骤一致。

自定义权限访问异常结果处理

除了登录成功、登录失败的结果处理,Spring Security还为我们提供了其他的结果处理类。比如用户未登录就访问系统资源

AuthenticationEntryPoint 用来解决匿名用户访问无权限资源时的异常
  • 代码实现如下

注意:实现类上不要少了注解 @Component注解

@Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {

    //Jackson JSON数据处理类
    private  static ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/javascript;charset=utf-8");
        response.getWriter().print(objectMapper.writeValueAsString("没有访问权限!"));
    }
}


AccessDeniedHandler解决认证用户没有访问权限

注意:实现类上不要少了注解 @Component注解

@Component
public class MyAccessDeineHandler implements AccessDeniedHandler {
    //Jackson JSON数据处理类
    private  static ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/javascript;charset=utf-8");
        response.getWriter().print(objectMapper.writeValueAsString("认证用户没有访问权限!"));
    }
}

在 LearnSrpingSecurity中注入MyAccessDeineHandler和MyAuthenticationEntryPoint实现如下

如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!

原创不易,转载请注明出处,感谢支持!如果本文对您有用,欢迎转发分享!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值