Spring Security的认证和授权(1)(springsecurity认证授权体系)

  本篇文章为你整理了Spring Security的认证和授权(1)(springsecurity认证授权体系)的详细内容,包含有spring security 认证 springsecurity认证授权体系 spring security authority spring security authorization Spring Security的认证和授权(1),希望能帮助你了解 Spring Security的认证和授权(1)。

  1.Spring Security 简介

    Java企业级开发生态丰富,无论你想做哪方面的功能,都有众多的框架和工具可供选择, 以至于SUN公司在早些年不得不制定了很多规范,这些规范在今天依然影响着我们的开发, 安全领域也是如此,然而,不同于其他领域,在Java企业级开发中,安全管理方面的框架非常少,一般来说,主要有三种方案:

  Shiro

  Spring Security

  开发者自己实现

    Shiro本身是一个老牌的安全管理框架,有着众多的优点,例如轻量、简单、易于集成、 可以在JavaSE环境中使用等。不过,在微服务时代,Shiro就显得力不从心了,在微服务面前, 它无法充分展示自己的优势。

    也有开发者选择自己实现安全管理,这一部分人不在少数,但是一个系统 的安全,不仅仅是登录和权限控制这么简单,我们还要考虑各种各样可能存在的网络攻击以及防御策略,从这个角度来说,开发者自己实现安全管理也并非是一件容易的事情,只有大公司才有足够的人力物力去支持这件事情。Spring Security作为Spring家族的一员,在和Spring家族的其他成员如Spring Boot、Spring Cloud等进行整合时,具有其他框架无可比拟的优势,同时对OAuth2有着良好的支持,再加 上 Spring Cloud 对 Spring Security 的不断加持(如推出 Spring Cloud Security),让 Spring Security 不知不觉中成为微服务项目的首选安全管理方案。

  2.Spring Security 核心功能

    对于一个安全管理框架而言,无论是Shiro还是Spring Security,最核心的功能,无非就是如下两方面:

    通俗点说,认证就是身份验证(你是谁?),授权就是访问控制(你可以做什么?)

    2.1 认证

    Spring Security支持多种不同的认证方式,这些认证方式有的是Spring Security自己提供的认证功能,有的是第三方标准组织制订的。Spring Security集成的主流认证机制主要有如下几种:

  OAuth2.0 认证

  SAML2.0 认证

  CAS 认证

  RememberMe 自动认证

  JAAS 认证

  OpenlD 去中心化认证

  Pre-Authentication Scenarios 认证口

  X509认证

  HTTP Basic 认证

  HTTP Digest 认证

    作为一个开放的平台,Spring Security提供的认证机制不仅仅包括上面这些,我们还可以通过引入第三方依赖来支持更多的认证方式,同时,如果这些认证方式无法满足我们的需求, 我们也可以自定义认证逻辑,特别是当我们和一些“老破旧“的系统进行集成时,自定义认证逻辑就显得非常重要了。

    2.2 授权

    无论釆用了上面哪种认证方式,都不影响在Spring Security中使用授权功能。Spring Security支持基于URL的请求授权、支持方法访问授权、支持SpEL访问控制、支持域对象安全(ACL),同时也支持动态权限配置、支持RBAC权限模型等,总之,我们常见的权限管理需求,Spring Security基本上都是支持的。

    2.3 其他

    在认证和授权这两个核心功能之外,Spring Security还提供了很多安全管理的“周边功能”, 这也是一个非常重要的特色。

    大部分Java工程师都不是专业的Web安全工程师,自己开发的安全管理框架可能会存在 大大小小的安全漏洞,而Spring Security的强大之处在于,即使你不了解很多网络攻击,只要使用了 Spring Security,它会帮助我们自动防御很多网络攻击,例如CSRF攻击、会话固定攻击等,同时Spring Security还提供了 HTTP防火墙来拦截大量的非法请求。由此可见,研究Spring Securityr也是研究常见的网络攻击以及防御策略。

    对于大部分的Java项目而言,无论是从经济性还是安全性来考虑,使用Spring Security 无疑是最佳方案。

  3. Spring Security 整体架构

   3.1 认证和授权

    3.1.1 认证
 

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

    在Spring Security中,用户的认证信息主要由Authentication的实现类来保存, 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;

  }

 

  这里接口中定义的方法如下:

  getAuthorities方法:用来获取用户的权限。

  getCredentials方法:用来获取用户凭证,一般来说就是密码。

  getDetails方法:用来获取用户携带的详细信息,可能是当前请求之类等。

  getPrincipal方法:用来获取当前用户,例如是一个用户名或者一个用户对象。

  isAuthenticated:当前用户是否认证成功。

    当用户使用用户名/密码登录或使用Remember-me登录时,都会对应一个不同的 Authentication 实例。Spring Security中的认证工作主要由AuthenticationManager接口来负责,下面来看一下该接口的定义:

  

public interface AuthenticationManager {

 

   Authentication authenticate(Authentication authentication)

   throws AuthenticationException;

  }

 

    AuthenticationManager只有一个authenticate方法可以用来做认证,该方法有三个不同的返回值:

  返回Authentication,表示认证成功。

  抛出AuthenticationException异常,表示用户输入了无效的凭证。

  返回null,表示不能断定。

    AuthenticationManager 最主要的实现类是 ProviderManager,PioviderManager 管理了众多的 AuthenticationProvider 实例,AuthenticationProvider 有点类似于 AuthenticationManager,但是它多了一个supports方法用来判断是否支持给定的Authentication类型。

  

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相当于一个备用认证方式,即各个 AuthenticationProvider都无法处理认证问题的时候,就由parent出场收拾残局。

    3.1.2 授权

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

  AccessDecisionManager

  AccessDecisionVoter

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

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

  3.2 Web安全

    在Spring Security中,认证、授权等功能都是基于过滤器来完成的。下表列出了 Spring Security中常见的过滤器,注意这里说的是否默认加载是指引入Spring Security依赖之后,开发者不做任何配置时,会自动加载的过滤器。

    开发者所见到的Spring Security提供的功能,都是通过这些过滤器来实现的,这些过滤器按照既定的优先级排列,最终形成一个过滤器链,开发者也可以自定义过滤器,并通过@Order 注解去调整自定义过滤器在过滤器链中的位置。

    需要注意的是,默认过滤器并不是直接放在Web项目的原生过滤器链中,而是通过一个FilterChainProxy 来统一管理。Spring Security 中的过滤器链通过 FilterChainProxy 嵌入到 Web 项目的原生过滤器链中,如下图所示。

    在Spring Security中,这样的过滤器链不仅仅只有一个,可能会有多个,如下图所示。 当存在多个过滤器链时,多个过滤器链之间要指定优先级,当请求到达后,会从 FilterChainProxy进行分发,先和哪个过滤器链匹配上,就用哪个过滤器链进行处理。当系统中存在多个不同的认证体系时,那么使用多个过滤器链就非常有效。

    FilterChainProxy 作为一个顶层管理者,将统一管理 Security Fliter。 FilterChainProxy 本身将通过Spring框架提供的DelegatingFilterProxy整合到原生过滤器链中,所以还可以做进一步的优化,如下图所示。

  3.3 登录数据保存

    如果不使用Spring Security这一类的安全管理框架,大部分的开发者可能会将登录用户数据保存在Session中,事实上,Spring Security也是这么做的。但是,为了使用方便,Spring Security 在此基础上还做了一些改进,其中最主要的一个变化就是线程绑定,

    当用户登录成功后,Spring Security会将登录成功的用户信息保存到SecurityContextHolder 中。SecurityContextHolder 中的数据保存默认是通过ThreadLocal来实现的,使用ThreadLocal 创建的变量只能被当前线程访问,不能被其他线程访问和修改,也就是用户数据和请求线程绑定在一起。当登录请求处理完毕后,Spring Security会将SecurityContextHolder中的数据拿出来保存到Session中,同时将SecurityContextHolder中的数据清空。以后每当有请求到来时, Spring Security就会先从Session中取出用户登录数据,保存到SecurityContextHolder 中,方便在该请求的后续处理过程中使用,同时在请求结束时将SecurityContextHolder中的数据拿岀来保存到Session中,然后将SecurityContextHolder 中的数据清空。

    这一策略非常方便用户在Controller或者Service层获取当前登录用户数据,但是带来的另外一个问题就是,在子线程中想要获取用户登录数据就比较麻烦。Spring Security对此也提供了相应的解决方案,如果开发者使用@Async注解来开启异步任务的话,那么只需要添加如下配置,使用Spring Security提供的异步任务代理,就可以在异步任务中从SecurityContextHolder里边获取当前登录用户的信息:

  

@Configuration

 

  public class ApplicationConfiguration extends AsyncConfigurerSupport {

   @Override

   public Executor getAsyncExecutor() {

   return new DelegatingSecurityContextExecutorService(Executors.newFixedThreadPool(5));

  }

 

  以上就是Spring Security的认证和授权(1)(springsecurity认证授权体系)的详细内容,想要了解更多 Spring Security的认证和授权(1)的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: