热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

爆破专栏丨SpringSecurity系列之前后端分离时的安全处理方案

点击上方蓝字关注我们前言在前面的几个章节中,一一哥带大家学会了如何利用Spring Security来保护我们的Web项目,以及3种认证方式。你可能会觉得,Sp

点击上方蓝字关注我们

前言

在前面的几个章节中,一一哥带大家学会了如何利用Spring Security来保护我们的Web项目,以及3种认证方式。你可能会觉得,Spring Security没啥东西啊,代码也不复杂呀!

别急,我们的学习是渐进的,Spring Security的内容和功能都多着呢,我们要Get的点也多着呢。

今天 一一哥就带大家来学习一下在前后端分离的开发模式下,如何保护我们项目的安全。有的小伙伴会问,啥是前后端分离啊?如果你对此一无所知,只能建议你先查阅一下相关资料,本文只能带你简单了解一下前后端分离的概念,毕竟今天我们是在讲解如何保证安全性的。
还有的小伙伴会说,前后端分离有什么了不起,为啥就需要单独处理?它和前后端不分离时有什么不同?那么就让我们带着这些疑问来开始今天的内容吧!

一. 前后端分离开发模式

1. 前后端分离简介

我们还是先来了解一下前后端分离这种开发模式吧,看看到底什么是前后端分离!

现在企业开发中,前后端分离已成为互联网项目开发的业界标准方式,其核心思想就是前端HTML页面通过AJAX,调用后端的RESTFUL API接口,并使用JSON数据进行交互。

该方式可以有效的在前后端项目之间进行解耦,并且前后端分离会为以后的大型分布式架构、弹性计算架构、微服务架构、多端化服务(多种客户端,例如 浏览器,车载终端,安卓,IOS等)打下坚实的基础。

所以在前后端分离这样的开发模式下,前后端的交互都是通过 JSON 来进行数据传递的,无论登录成功还是失败,都不会有服务端跳转或者客户端跳转之类的操作。

也就是说无论登录成功还是失败,服务端都会返回一段登录成功或失败的 JSON 信息给前端,前端收到JSON之后来决定是该跳转到成功界面还是失败界面,和后端没有关系。

通俗的说,就是在前后端分离模式中,原先的前端页面和Java代码是在一个项目里面,现在分开了!前端项目负责各种页面及前端业务的实现,后端项目负责后端业务的实现,在后端项目中没有任何页面。前后端之间利用JSON作为信息的载体,进行信息的传输和交互。
现在你明白啥是前后端分离了吧?

二. 认证处理时的相关API

我们了解了前后端分离的开发模式之后,接下来我带各位学习一下Spring Security提供了哪些API,可以帮助我们处理前后端分离时的开发。

1. 页面跳转的相关API

1.1 登录成功时的跳转API

我们在之前的章节讲解表单认证时,处理登录成功时,跳转到某个页面的API是如下两个方法:

  • defaultSuccessUrl

  • successForwardUrl

以上两个方法都是用来配置跳转地址的,适用于前后端不分离时的开发。

1.2 登录失败时的跳转API

处理登录失败时,跳转页面的API是如下两个方法:

  • failureUrl()

  • failureForwardUrl()

以上两个方法也是用来配置跳转地址的,同样适用于前后端不分离时的开发.

2. 返回JSON格式的处理器

上面的两类方法,无论是认证成功还是认证失败,都是在前后端不分离时的处理方案,直接从Java后端跳转到某个页面上。那么在前后端分离时,Java后端项目中,根本就没有页面,往哪跳啊?有的小伙伴说,既然没有页面,就不跳了呗。呵呵,那怎么行!

在前后端分离模式下,既然后端没有页面,页面都在前端,那就可以考虑使用JSON来进行信息交互了,我们把认证成功或认证失败的信息,以JSON的格式传递给前端,由前端来决定到底该往哪个页面跳转就好了。

如果我们要返回JSON格式的信息,有如下相关方法:

  • successHandler()

  • failureHandler()

  • logoutSuccessHandler()

  • authenticationEntryPoint()

  • ......

三. 认证成功时的处理方案

接下来 一一哥 先带各位实现认证成功时的处理方案,我们先看看相关的方法及其核心参数,即successHandler()和onAuthenticationSuccess参数。

1. successHandler()方法

successHandler()方法的功能十分强大,甚至也囊括了 defaultSuccessUrl()和 successForwardUrl() 的功能。
successHandler()方法的参数是一个 AuthenticationSuccessHandler 对象,这个对象中我们要实现的方法是 onAuthenticationSuccess()。

2. onAuthenticationSuccess参数

onAuthenticationSuccess() 方法中有三个参数,分别是:

  • HttpServletRequest: 利用该参数我们可以实现服务端的跳转;

  • HttpServletResponse: 利用该参数我们可以做客户端的跳转,也可以返回 JSON 数据;

  • Authentication: 这个参数则保存了我们刚刚登录成功的用户信息。

3. 定义SecurityAuthenticationSuccessHandler类

了解完主要的方法和参数之后,我们先来编写一个处理器类,该类需要实现SavedRequestAwareAuthenticationSuccessHandler接口。

核心代码如下:

/**
 * 处理登录成功时的业务逻辑
 */

public class SecurityAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
    /**
     * Authentication:携带登录的用户名及角色等信息
     */

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
        //直接输出json格式的响应信息
        Object principal = authentication.getPrincipal();
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        //以json格式对外输出身份信息
        out.write(new ObjectMapper().writeValueAsString(principal));
        out.flush();
        out.close();
    }
}

4. 配置successHandler

然后我们在SecurityConfig配置类中,调用successHandler()方法,把前面定义的SecurityAuthenticationSuccessHandler类关联进来。

核心代码如下:

/**
 * @Author: 一一哥
 * @Blame: yyg
 * @Since: Created in 2021/4/14
 *
 * 前后端分离时处理json响应信息
 */

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
                //认证成功时的处理器
                .successHandler(new SecurityAuthenticationSuccessHandler())
                .and()
                .csrf()
                .disable();
    }
}

5. 验证结果

配置完成后,我们进行登录验证,在认证成功后,就可以看到登录成功的用户信息是通过 JSON 返回到前端的,如下图所示:

在认证成功后,Spring Security会把认证的用户信息以JSON格式展示出来,比如我们的用户名、密码、角色等信息。

四. 认证失败时的处理方案

接下来请各位小伙伴再跟着 一一哥 来学习如何实现认证失败时的处理方案,同样的,我们先看看相关的API方法及参数。

1. failureHandler()

failureHandler()方法的参数是一个 AuthenticationFailureHandler 对象,这个对象中我们要实现的方法是 onAuthenticationFailure()。

onAuthenticationFailure()方法有三个参数,分别是:

  • HttpServletRequest: 利用该参数我们可以实现服务端的跳转;

  • HttpServletResponse: 利用该参数我们可以做客户端的跳转,也可以返回 JSON 数据;

  • AuthenticationException: 这个参数则保存了登录失败的原因。

2. 代码实现

同样,我们也要编写一个类SecurityAuthenticationFailureHandler,实现ExceptionMappingAuthenticationFailureHandler接口,来专门处理认证失败时的返回结果。

核心代码如下:

/**
 * 处理登录失败时的业务逻辑
 */

public class SecurityAuthenticationFailureHandler extends ExceptionMappingAuthenticationFailureHandler {
    /**
     * AuthenticationException:异常信息
     */

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        //直接输出json格式的响应信息
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(e.getMessage());
        out.flush();
        out.close();
    }
}

3. 配置failureHandler

接着我们在SecurityConfig配置类中,调用failureHandler()方法来关联上面定义的SecurityAuthenticationFailureHandler类对象。

核心代码如下:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
                //认证成功时的处理器
                .successHandler(new SecurityAuthenticationSuccessHandler())
                //认证失败时的处理器
                .failureHandler(new SecurityAuthenticationFailureHandler())
                .and()
                .csrf()
                .disable();
    }

4. 验证结果

配置完成后,我们再去登录,在认证失败时,就可以看到登录失败的用户信息通过 JSON 返回到前端了,如下图所示:

五. 退出登录时的处理方案

实现了认证成功和认证失败后的处理方案后,接下来 一一哥 再带大家看看如何处理退出登录,毕竟我们不能只会登录,不会退出登录,有吃有拉才正常嘛。

1. logoutSuccessHandler()

负责退出登录的方法是logoutSuccessHandler(),这个方法中需要一个参数LogoutSuccessHandler;在LogoutSuccessHandler类中有一个方法 onLogoutSuccess(),该方法中的参数与登录成功时的参数一样。

2. 定义SecurityLogoutSuccessHandler类

我们先来定义一个SecurityLogoutSuccessHandler类,实现LogoutSuccessHandler接口,在这里负责输出退出登录时的JSON结果。

/**
 * @Author: 一一哥
 * @Blame: yyg
 * @Since: Created in 2021/5/26
 *
 * 处理退出登录时的响应信息
 */

public class SecurityLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("注销成功");
        out.flush();
        out.close();
    }
}

3. 配置logoutSuccessHandler

然后我们在SecurityConfig配置类中,调用logoutSuccessHandler()方法来关联上面定义的SecurityLogoutSuccessHandler对象。

核心代码如下:

/**
 * @Author: 一一哥
 * @Blame: yyg
 * @Since: Created in 2021/5/26
 *
 * 处理退出登录时的响应信息
 */

public class SecurityLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("注销成功");
        out.flush();
        out.close();
    }
}

4. 验证结果

配置完成后,我们去访问/logout接口,退出登录成功,会有如下所示结果:

六. 未认证时的处理方案

我们上面讲解了认证成功、认证失败及退出登录时的处理方案,但还有一个未认证时的处理方案。

一般在我们没有认证时,会直接重定向到登录页面。但是在前后端分离中,这个逻辑是有问题的:

即如果用户没有登录,就访问一个需要认证后才能访问的页面,这个时候,我们不应该让用户重定向到登录页面,而是给用户一个尚未登录的提示,前端收到提示之后,再自行决定页面跳转。因为在前后端分离时,后端没有页面,未认证时也没办法直接重定向到登录页面啊!

接下来跟我来实现一下吧!也挺容易的,Lets go!

1. authenticationEntryPoint()

未认证时,同样有个专门的方法来处理,即authenticationEntryPoint()方法,这个方法中需要一个参数LoginUrlAuthenticationEntryPoint,在LoginUrlAuthenticationEntryPoint类中有一个方法 commence()。

2. 定义SecurityAuthenticationEntryPoint类

我们定义一个SecurityAuthenticationEntryPoint类,实现AuthenticationEntryPoint接口,在这里负责输出未认证时的JSON结果。

/**
 * @Author: 一一哥
 * @Blame: yyg
 * @Since: Created in 2021/5/26
 *
 * 处理未登录认证时的响应信息
 */

public class SecurityAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("尚未登录,请先登录");
        out.flush();
        out.close();
    }
}

3. 配置authenticationEntryPoint

然后我们在SecurityConfig配置类中,调用authenticationEntryPoint()方法来关联上面定义的SecurityAuthenticationEntryPoint对象。

核心代码如下:

/**
 * @Author: 一一哥
 * @Blame: yyg
 * @Since: Created in 2021/4/14
 *
 * 前后端分离时处理json响应信息
 */

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
                //认证成功时的处理器
                .successHandler(new SecurityAuthenticationSuccessHandler())
                //认证失败时的处理器
                .failureHandler(new SecurityAuthenticationFailureHandler())
                .and()
                .logout()
                //退出登录时的处理器
                .logoutSuccessHandler(new SecurityLogoutSuccessHandler())
                .and()
                .csrf()
                .disable();
    }
}

4. 验证结果

配置完成后,我们在未登录时,直接去访问项目中的某个接口,就会看到未登录时返回的JSON信息,如下图所示:

七. 整体项目代码结构

到此为止,我就实现了今天所有的内容,以上所有代码配置,请各位参考如下代码结构:

往期精彩

HarmonyOS版锋迷商城APP更新

Spring Security开发第一章!

Spring Security系列之实现HTTP摘要认证

Spring Security系列教程之实现Form表单认证

Spring Security系列教程之实现HTTP基本认证

Spring Security系列教程之创建项目

文末福利

留言评论,今天的内容你学会了吗?

点赞最多的同学获得水杯一个!

关注公众号,回复【SS】获取专栏大纲脑图

点击【阅读全文】,从零开始学Java



推荐阅读
  • Framework7:构建跨平台移动应用的高效框架
    Framework7 是一个开源免费的框架,适用于开发混合移动应用(原生与HTML混合)或iOS&Android风格的Web应用。此外,它还可以作为原型开发工具,帮助开发者快速创建应用原型。 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 基于Net Core 3.0与Web API的前后端分离开发:Vue.js在前端的应用
    本文介绍了如何使用Net Core 3.0和Web API进行前后端分离开发,并重点探讨了Vue.js在前端的应用。后端采用MySQL数据库和EF Core框架进行数据操作,开发环境为Windows 10和Visual Studio 2019,MySQL服务器版本为8.0.16。文章详细描述了API项目的创建过程、启动步骤以及必要的插件安装,为开发者提供了一套完整的开发指南。 ... [详细]
  • 使用ArcGIS for Java和Flex浏览自定义ArcGIS Server 9.3地图
    本文介绍了如何在Flex应用程序中实现浏览自定义ArcGIS Server 9.3发布的地图。这是一个基本的入门示例,适用于初学者。 ... [详细]
  • 本文最初发表在Thorben Janssen的Java EE博客上,每周都会分享最新的Java新闻和动态。 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 本教程详细介绍了如何使用 Spring Boot 创建一个简单的 Hello World 应用程序。适合初学者快速上手。 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • MySQL的查询执行流程涉及多个关键组件,包括连接器、查询缓存、分析器和优化器。在服务层,连接器负责建立与客户端的连接,查询缓存用于存储和检索常用查询结果,以提高性能。分析器则解析SQL语句,生成语法树,而优化器负责选择最优的查询执行计划。这一流程确保了MySQL能够高效地处理各种复杂的查询请求。 ... [详细]
  • 技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统
    技术分享:使用 Flask、AngularJS 和 Jinja2 构建高效前后端交互系统 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 在处理大规模数据数组时,优化分页组件对于提高页面加载速度和用户体验至关重要。本文探讨了如何通过高效的分页策略,减少数据渲染的负担,提升应用性能。具体方法包括懒加载、虚拟滚动和数据预取等技术,这些技术能够显著降低内存占用和提升响应速度。通过实际案例分析,展示了这些优化措施的有效性和可行性。 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
author-avatar
mobiledu2502872907
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有