Spring Security系列教程07--前后端分离时的安全处理方案

简介: 前言在前面的几个章节中,一一哥 带大家学会了如何利用Spring Security来保护我们的Web项目,以及3种认证方式。你可能会觉得,Spring Security没啥东西啊,代码也不复杂呀!别急,我们的学习是渐进的,Spring Security的内容和功能都多着呢,我们要Get的点也多着呢。今天 一一哥 就带大家来学习一下在前后端分离的开发模式下,如何保护我们项目的安全。有的小伙伴会问,啥是前后端分离啊?如果你对此一无所知,一一哥 只能建议你先查阅一下相关资料,本文 一一哥 只能带你简单了解一下前后端分离的概念,毕竟今天我们是在讲解如何保证安全性的。还有的小伙伴会说,前后端分离有

前言

在前面的几个章节中,一一哥 带大家学会了如何利用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接口。

核心代码如下:

/*** 处理登录成功时的业务逻辑*/publicclassSecurityAuthenticationSuccessHandlerextendsSavedRequestAwareAuthenticationSuccessHandler {
/*** Authentication:携带登录的用户名及角色等信息*/@OverridepublicvoidonAuthenticationSuccess(HttpServletRequestrequest, HttpServletResponseresponse, Authenticationauthentication) throwsServletException, IOException {
//直接输出json格式的响应信息Objectprincipal=authentication.getPrincipal();
response.setContentType("application/json;charset=utf-8");
PrintWriterout=response.getWriter();
//以json格式对外输出身份信息out.write(newObjectMapper().writeValueAsString(principal));
out.flush();
out.close();
    }
}

4. 配置successHandler

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

核心代码如下:

/*** @Author: 一一哥* @Blame: yyg* @Since: Created in 2021/4/14** 前后端分离时处理json响应信息*/@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
//认证成功时的处理器                .successHandler(newSecurityAuthenticationSuccessHandler())
                .and()
                .csrf()
                .disable();
    }
}

5. 验证结果

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

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

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

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

1. failureHandler()

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

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

  • HttpServletRequest: 利用该参数我们可以实现服务端的跳转;
  • HttpServletResponse: 利用该参数我们可以做客户端的跳转,也可以返回 JSON 数据;
  • AuthenticationException: 这个参数则保存了登录失败的原因。

2. 代码实现

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

核心代码如下:

/*** 处理登录失败时的业务逻辑*/publicclassSecurityAuthenticationFailureHandlerextendsExceptionMappingAuthenticationFailureHandler {
/*** AuthenticationException:异常信息*/@OverridepublicvoidonAuthenticationFailure(HttpServletRequestrequest, HttpServletResponseresponse, AuthenticationExceptione) throwsIOException, ServletException {
//直接输出json格式的响应信息response.setContentType("application/json;charset=utf-8");
PrintWriterout=response.getWriter();
out.write(e.getMessage());
out.flush();
out.close();
    }
}

3. 配置failureHandler

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

核心代码如下:

@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
//认证成功时的处理器                .successHandler(newSecurityAuthenticationSuccessHandler())
//认证失败时的处理器                .failureHandler(newSecurityAuthenticationFailureHandler())
                .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** 处理退出登录时的响应信息*/publicclassSecurityLogoutSuccessHandlerimplementsLogoutSuccessHandler {
@OverridepublicvoidonLogoutSuccess(HttpServletRequestrequest, HttpServletResponseresponse, Authenticationauthentication) throwsIOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriterout=response.getWriter();
out.write("注销成功");
out.flush();
out.close();
    }
}

3. 配置logoutSuccessHandler

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

核心代码如下:

/*** @Author: 一一哥* @Blame: yyg* @Since: Created in 2021/4/14** 前后端分离时处理json响应信息*/@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
//认证成功时的处理器                .successHandler(newSecurityAuthenticationSuccessHandler())
//认证失败时的处理器                .failureHandler(newSecurityAuthenticationFailureHandler())
                .and()
                .logout()
//退出登录时的处理器                .logoutSuccessHandler(newSecurityLogoutSuccessHandler())
                .and()
                .csrf()
                .disable();
    }
}

4. 验证结果

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

六. 未认证时的处理方案

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

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

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

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

1. authenticationEntryPoint()

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

2. 定义SecurityAuthenticationEntryPoint类

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

/*** @Author: 一一哥* @Blame: yyg* @Since: Created in 2021/5/26** 处理未登录认证时的响应信息*/publicclassSecurityAuthenticationEntryPointimplementsAuthenticationEntryPoint {
@Overridepublicvoidcommence(HttpServletRequestrequest, HttpServletResponseresponse, AuthenticationExceptionauthException) throwsIOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriterout=response.getWriter();
out.write("尚未登录,请先登录");
out.flush();
out.close();
    }
}

3. 配置authenticationEntryPoint

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

核心代码如下:

@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter {
@Overrideprotectedvoidconfigure(HttpSecurityhttp) throwsException {
http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll()
//认证成功时的处理器                .successHandler(newSecurityAuthenticationSuccessHandler())
//认证失败时的处理器                .failureHandler(newSecurityAuthenticationFailureHandler())
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
//未登录时的处理器                .authenticationEntryPoint(newSecurityAuthenticationEntryPoint());
    }
}

4. 验证结果

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

七. 整体项目代码结构

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

各位小伙伴,今天的内容你学会了吗?有不明白的地方,在评论区留言diss吧!

相关文章
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
158 1
|
25天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
97 62
|
18天前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
23天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
41 2
|
1月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
73 2
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
44 3
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第7天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建 Spring Boot 项目并配置 Spring Security。接着,实现后端 API 以提供菜单数据。在前端部分,使用 Ant Design Pro Vue 脚手架创建项目,并配置动态路由和菜单。最后,启动前后端服务,实现高效、美观且功能强大的应用框架。
45 2
|
21天前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
34 0
|
2月前
|
XML JavaScript Java
Spring Retry 教程
Spring Retry 是 Spring 提供的用于处理方法重试的库,通过 AOP 提供声明式重试机制,不侵入业务逻辑代码。主要步骤包括:添加依赖、启用重试机制、设置重试策略(如异常类型、重试次数、延迟策略等),并可定义重试失败后的回调方法。适用于因瞬时故障导致的操作失败场景。
Spring Retry 教程
|
1月前
|
安全 Java 对象存储
安全性考量:Spring Security与Netflix OSS在微服务安全中的作用
安全性考量:Spring Security与Netflix OSS在微服务安全中的作用
43 1
下一篇
无影云桌面