> 文档中心 > Spring Security 概述

Spring Security 概述


Spring Security 概述

在这里插入图片描述
官网地址:Spring Security

1、安全框架概述

什么是安全框架?解决系统安全问题的框架。如果没有安全框架,我们需要手动处理每个资源的访问控制,非常麻烦。使用安全框架。我们可以通过配置的方式实现对资源的访问限制。

2、常用安全框架

  • Spring Security: Spring 家族一员。是一个能够为基于 Spring 的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在 Spring 应用上下文中配置的 Bean,充分利用了Spring Ioc,DI(控制反转 Inversion of contro1,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

    Spring技术栈的组成部分。

    • Spring Security 特点:
      • 和Spring无缝整合
      • 专门为Web开发而设计
        • 旧版本不能脱离Web环境使用
        • 新版本对整个框架进行了分层抽取,分成了核心模块和Web模块。单独引入核心模块就可以脱离Web环境。
      • 重量级
  • Apache Shiro:一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理。

    Apache旗下的轻量级权限控制框架

    • Shiro 特点:
      • 轻量级。Shiro主张的理念是把复杂的事情变简单。针对对性能有更高要求的互联网应用有更好表现
      • 通用性
      • 好处:不局限于Web环境,可以脱离Web环境使用
      • 缺陷:在Web环境下一些特定的需求需要手动编写代码定制

总结:

Spring Security是Spring家族中的一个安全管理框架,实际上,在Spring Boot出现之前,Spring Security就已经发展了多年了,但是使用的并不多,安全管理这个领域,一直是Shiro的天下。

相对于Shiro,在SSM中整合Spring Security都是比较麻烦的操作,所以,SpringSecurity虽然功能比Shiro强大,但是使用反而没有Shiro多 ( Shiro虽然功能没有Spring Security多,但是对于大部分项目而言,Shiro 也够用了)。

自从有了Spring Boot之后,Spring Boot对于Spring Security提供了自动化配置方案,可以使用更少的配置来使用Spring Security。

因此,一般来说,常见的安全管理技术栈的组合是这样的:。

  • SSM + Shiro
  • Spring Boot/Spring Cloud + Spring Security-

以上只是一个推荐的组合而已,如果单纯从技术上来说,无论怎么组合,都是可以运行的。

3、Spring Security 简介

概述:

Spring是非常流行和成功的Java应用开发框架,Spring Security正是Spring家族中的成员。Spring Security基于Spring框架,提供了一套Web应用安全性的完整解决方案。·

Spring Security是一个高度自定义的安全框架。利用Spring loC/DI和AoP功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。使用 Spring secruity 的原因有很多,但大部分都是发现了javaEE的 Servlet 规范或EJB规范中的安全功能缺乏典型企业应用场景。同时认识到他们在WAR或EAR级别无法移植。因此如果你更换服务器环境,还有大量工作去重新配置你的应用程序。使用Spring Security解决了这些问题,也为你提供许多其他有用的、可定制的安全功能。

正如我们可能知道的关于安全方面的两个主要区域是“认证”和“授权”(或者访问控制),一般来说,Web应用的安全性包括用户认证(Authentication)和用户授权( Authorization)两个部分,这两点也是Spring Security重要核心功能。

  1. 用户认证指的是︰验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。通俗点说就是系统认为用户是否能登录
  2. 用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。通俗点讲就是系统判断用户是否有权限去做某些事情。。

历史:

Spring Security 开始于2003年年底 ”spring 的acegi安全系统” 。起因是Spring开发者邮件列表中的一个问题有人提问是否考虑提供一个基于spring的安全实现。。

Sping Security以“The Acegi Secutity System for Spring”的名字始于2003年晚些时候。一个问题提交到 Spring开发者的邮件列表,询问是否已经有考虑一个机遇Spring的安全性社区实现。那时候Spring的社区相对较小(相对现在)。实际上Spring自己在2013年只是一个存在于ScourseForge的项目,这个问题的回答是一个值得研究的领域,虽然目前时间的缺乏组织了我们对它的探索。

考虑到这一点,一个简单的安全实现建成但是并没有发布。几周后,Spring社区的其他成员询问了安全性,这次这个代码被发送给他们。其他几个请求也跟随而来。到2014年一月大约有20万人使用了这个代码。这些创业者的人提出一个SourceForge项目加入是为了,这是在2004三月正式成立。

在早些时候,这个项目没有任何自己的验证模块,身份验证过程依赖于容器管理的安全性和Acegi安全性。而不是专注于授权。开始的时候这很适合,但是越来越多的用户请求额外的容器支持。容器特定的认证领域接口的基本限制变得清晰。还有一个相关的问题增加新的容器的路径,这是最终用户的困惑和错误配置的常见问题。

Acegi安全特定的认证服务介绍。大约一年后,Acegi安全正式成为了Spring框架的子项目。1.0.0最终版本是出版于2006-在超过两年半的大量生产的软件项目和数以百计的改进和积极利用社区的贡献。

Acegi安全2007年底正式成为了Spring组合项目,更名为"Spring Security"

Spring Security 的核心功能主要包括:

  1. 认证 (你是谁)
  2. 授权 (你能干什么)
  3. 攻击防护 (防止伪造身份)

认证

认证
在SpringSecurity的架构设计中,认证(Authentication)和授权(Authorization)是分开的,无论使用什么样的认证方式,都不会影响授权,这是两个独立的存在,这种独立带来的好处之一,就是可以非常方便地整合一些外部地认证方案。

在SpringScuerity中,用户地认证信息主要是由Authentication的实现类来保存,接口定义如下:

public interface Authentication extends Principal, Serializable {    //用来获取用户的权限Collection<? extends GrantedAuthority> getAuthorities();//用来获取用户凭证,一般来说是密码Object getCredentials();//用来获取用户携带的详细信息,可能是当前请求之类等Object getDetails();//用来获取当前用户,例如是一个用户或一个用户对象Object getPrincipal();//当前用户是否认证成功。boolean isAuthenticated();void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;    }

当用户使用用 户名/密码 登录或者使用 Remember-me 登录时,都会对于一个不同的 Authentication 实例。

SpringSecurity 中的认证工作主要由 AuthenticationManager 接口负责

public interface AuthenticationManager {Authentication authenticate(Authentication authentication) throws AuthenticationException;}

尝试对传递的 Authentication 对象进行身份验证,如果成功,则返回完全填充的 Authentication 对象(包括授予的权限)。
AuthenticationManager 必须遵守以下关于异常的约定:
如果帐户被禁用并且 AuthenticationManager 可以测试此状态,则必须抛出 DisabledException。
如果帐户被锁定并且 AuthenticationManager 可以测试帐户锁定,则必须抛出 LockedException。
如果提供了不正确的凭据,则必须抛出 BadCredentialsException。虽然上述例外是可选的,但 AuthenticationManager 必须始终测试凭据。
应测试异常,如果适用,则按上述顺序抛出(即如果帐户被禁用或锁定,则立即拒绝身份验证请求并且不执行凭据测试过程)。这可以防止针对禁用或锁定的帐户测试凭据。

AuthenticationManager 接口只有一个authenticate方法可以用来做认证

  1. 返回 Authentication : 表示认证成功
  2. 抛出 AuthenticationException 异常:表示用户输入了无效的凭证

AuthenticationManager 最主要的实现类是 ProviderManager,ProviderManager 管理了众多的 AuthenticationProvider 实例

AuthenticationProvider 有点类似于 AuthenticationManager,但是它多了一个 supports 方法用来短评是否指出给定的 Authenticaion 类型

supports 方法:

如果此 AuthenticationProvider 支持指示的 Authentication 对象,则返回 true。
返回 true 并不能保证 AuthenticationProvider 将能够对 Authentication 类的呈现实例进行身份验证。它只是表明它可以支持对其进行更仔细的评估。 AuthenticationProvider 仍然可以从 authenticate(Authentication) 方法返回 null 以指示应该尝试另一个 AuthenticationProvider。
能够执行身份验证的 AuthenticationProvider 的选择是在 ProviderManager 运行时进行的。

public interface AuthenticationProvider {Authentication authenticate(Authentication authentication) throws AuthenticationException;boolean supports(Class<?> authentication);}

由于 Authentication 拥有众多不同的实现类,这些不同的实现类又由不能的 AuthenticationProvider 来处理,所以 AuthenticationProvider 会有一个 supports方法,来判断当前的 AuthenticationProvider 是否支持对应的 Authentication

在一次完整的认证流程中,可能会存在多个 AuthenticationProvider(例如,项目同时支持form表单登录和短信验证码登录),多个 AuthenticationProvider 统一由 ProviderManager 管理,同时 ProviderManager 具有一个可选的parent,如果所有的 AuthenticationProvider 都认证失败,那么就算调用 parent 进行认证。parent 相当于一个备用认证方式,即各个 AuthenticationProvide r都无法处理认证问题的时候,就由它来收拾。

授权

当认证完成后,接下来就是授权了。在SpringSecurity的授权体系中,有两个关键接口:

  1. AccessDecisionManager
  2. AccessDecisionVoter

AccessDecisionVoter 是一个投票器,拉票器会检查用户是否具备应有的角色,进而投出赞成、反对或者弃权票,AccessDecisionManager 则是一个决策器,来决定此次访问是否被允许。AccessDecisionVoter和AccessDecisionManager都有众多的实现类,在AccessDecisionManager中会挨个遍历 AccessDecisionVoter,进而决定是否允许用户访问,因为 AccessDecisionVoter 和 AccessDecisionManager 两者的关系类似于 AuthenticationProvider 和 ProviderManager 的关系。

在 SpringSecurity 中,用户请求一个资源(通常是一个接口或者一个java方法)所需要的角色会被封装成一个 ConfigAttribute 对象,在 ConfigAttribute 中只有一个 getAttribute 方法,该方法返回一个 Stirng 字符串,就是角色名称。一般来说,角色名称都带有一个 ROLE_ 前缀,投票器 AccessDecisionVoter 所做的事情,其实就算比较用户所具备的角色和请求某个资源所需要的ConfigAttribute之间的关系