前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >任何 Web 项目都离不开的 Spring Security【原理+实战(前后端分离+无状态)】

任何 Web 项目都离不开的 Spring Security【原理+实战(前后端分离+无状态)】

原创
作者头像
王二蛋
发布2024-07-23 08:30:26
140
发布2024-07-23 08:30:26

前言

大部分系统开发的第一个功能,基本上都是用户注册、登录,这两个看似简单的功能,实则是任何系统安全的基石。Spring Security 想必都很熟悉,作为一个安全管理框架,提供了丰富的认证机制、授权模型以及安全防护措施,极大简化了安全性的开发过程。本文就围绕 Spring Security 的架构原理、配置方法以及高级特性,高效的构建出一个安全的Web应用。

Spring Security 原理

本质

Spring Security 本质上就是一个过滤器链,所有的访问请求都会经过这些过滤器。如下图

Spring Security 过滤器链SecurityFilterChain
Spring Security 过滤器链SecurityFilterChain

不了解过滤器的可以自行前往了解。

图中的 SecurityFilterChain 就是 Spring Security 的过滤器链,认证授权以及安全防护(XSS、CSRF等)都是在这些过滤器中完成的。

当项目中引入 Spring Security 启动后,一些默认的 SecurityFilterChain 过滤器会被装载,如下:

Spring Security 默认加载的过滤器
Spring Security 默认加载的过滤器

其中几个过滤器的命名直接体现了其功能,例如LogoutFilterUsernamePasswordAuthenticationFilterDefaultLoginPageGeneratingFilter等。

DefaultLoginPageGeneratingFilter生成页面就可以得知:Spring Security 默认是前后端不分离的。

所以,对于现在大多数前后端分离的项目,我们可以通过配置自定义需要哪些过滤器以及如何处理该功能,例如如何认证、认证失败、授权失败的响应等。

认证流程

开发者使用 Spring Security 最关心应该就是认证了,默认会提供表单认证,也就是生成一个表单页面,填写用户名和密码。如下图

这一功能就是DefaultLoginPageGeneratingFilter这个过滤器完成的。

用户名和密码默认由InMemoryUserDetailsManager提供,存储在内存中,这里自然需要我们后续去配置自定义实现

输入用户名密码后就可以去执行认证流程了,如下图

Spring Security认证流程
Spring Security认证流程

认证的流程中,我们还需要留意几个接口:

  1. SessionAuthenticationStrategy,认证成功后,会将用户会话存储在HttpSession中,在后续会基于HttpSession进行身份验证,但是对于无状态的应用,这种方式是不可取的。
  2. AuthenticationFailureHandlerAuthenticationSuccessHandler,默认的认证成功和失败后,会重定向跳转到某个页面,对于前后端分离的项目,这种方式时不可取的,依然需要我们后续去配置自定义实现

权限验证

通常,在认证时会将用户的权限信息(GrantedAuthority)加载给UserDetails,在后续的过滤器会对其进行验证,也就是ExceptionTranslationFilterAuthorizationFilter

这两个有什么区别?

Spring Security 支持请求URL和方法两种授权方式,即在配置中设置authorizeHttpRequests以及在方法上面的@PreAuthorize, @PostAuthorize注解。

以下是两者验证权限的流程

Authorize HttpServletRequests
Authorize HttpServletRequests
Method Security
Method Security

自定义配置

Spring Security 如何知道我们想要求所有用户都经过身份认证?如何知道我们想要支持基于表单的身份认证?实际上,全靠一个配置类去自定义设置,也就是上面所说的 SecurityFilterChain

接下来,就基于配置类构建一个前后端分离集成 Spring Security 的Web应用。

SpringBoot 集成 Spring Security

创建脚手架

SpringBoot 集成 Spring Security 很简单,去spring或者阿里脚手架下载一个demo,引入相关依赖就可以了,主要是这两个

项目启动后就会弹出【认证流程】中的登录界面。

如何配置就看自己的需求了,本文就以前后端分离、无状态为需求,结合JWT进行配置并实现。

Spring Security 如何配置

梳理下前后端分离、无状态以及结合JWT,应该如何配置Spring Security。

  1. 前后端分离需要配置以下几项:
    • 访问失败、认证失败、授权失败等响应改为json格式。
    • 由于是前后端分离,所以允许跨域请求。
  2. 无状态需要配置以下几项:
    • 对session的管理要设置为无状态。
    • 因为没有session,所以关闭csrf。
    • 在JWT中解析安全上下文(SecurityContext)验证,而不是在ThreadLocal中。

前后端分离&无状态配置

以上有几个事项直接配置即可,例如cors、csrf、session无状态、自定义登录等。

需要自定义实现的配置事项如下:

  1. 自定义登录配置后,需要自己写登录认证接口。
  2. 未认证时访问接口,默认会由 LoginUrlAuthenticationEntryPoint 处理,会重定向到某个URL,需要配置自定义为json响应。
  3. 认证失败后,默认会由SimpleUrlAuthenticationFailureHandler处理,会重定向到某个URL,需要配置自定义为json响应。
  4. 认证成功后,默认会由SavedRequestAwareAuthenticationSuccessHandler处理,会重定向到某个URL,需要配置自定义为json响应。
  5. 认证成功后,请求未授权的接口,默认会由AccessDeniedHandlerImpl处理,会重定向到某个URL,需要配置自定义为json响应。
  6. 注销成功后,默认会由SimpleUrlAuthenticationSuccessHandler,会重定向到某个URL,需要配置自定义为json响应。
  7. 整个流程中涉及到的安全上下文(SecurityContext),通过自定义过滤器,在token中解析并设置到当前请求的上下文。

整个配置大概是这样

自定义认证逻辑

通过以上简单的配置,就已经实现了前后端分离架构和无状态会话管理。除此之外,项目中还需要实现自定义认证逻辑。

以上的配置来看,当post请求/login,传入usernamepassword就会执行认证流程,不需要写/login接口。

那我们需要写哪些代码实现自定义认证逻辑?

认证流程(看图)中的AuthenticationManager,会调用 UserDetailsService 接口中的loadUserByUsername(),最终返回UserDetails对象交给Spring Security管理。

具体来说,我们需要创建两个类,一个实现UserDetailsService 接口,重写loadUserByUsername()加载用户信息,一个实现UserDetails,定义业务中的用户信息。

loadUserByUsername()中,我们只需要做几件事:

  1. 根据username获取用户信息,包括密码、角色和权限什么的,获取来源自定义,通常是关系型数据库,例如MySql。
  2. 如果该用户不存在,抛出异常即可。
  3. 将用户信息封装到UserDetails中,返回。

注意,这里不需要多此一举校验密码,认证流程中会有这一步骤。你只需将数据库中加密的密码交个UserDetails即可。

不需要写/login接口,认证成功后我想返回token怎么办?

如果有这样的疑问,那你一定是没好好看上面认证流程以及配置:代码中的formConfig.successHandler配置就是用来响应数据的。

完整的代码

为了方便大家观看,我将所有的代码放在一个文件中,如下图

注意:这只是一个示例代码,供大家学习了解Spring Security,可以参考,不建议直接在项目中使用。有任何问题可以随时交流。

总结

Spring Security 本质上就是一连串的过滤器,当一个请求来临时,这些过滤器会对该请求一一处理,包括登录认证、权限验证以及其他安全防护。也因其灵活性,我们只需有简单的配置加上一些代码就可以快速构建出一个安全性极高的Web应用。对于每次集成Spring Security都需要百度的开发者,希望在看完这篇文章的原理+实战后,可以让你摆脱此烦恼。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Spring Security 原理
    • 本质
      • 认证流程
        • 权限验证
          • 自定义配置
          • SpringBoot 集成 Spring Security
            • 创建脚手架
              • Spring Security 如何配置
                • 前后端分离&无状态配置
                  • 自定义认证逻辑
                    • 完整的代码
                    • 总结
                    相关产品与服务
                    关系型数据库
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档