【Spring Boot】Spring 的安全框架:Spring Security

打印 上一主题 下一主题

主题 915|帖子 915|积分 2749

1.Spring Security 初识

Spring Security 提供了声明式的安全访问控制解决方案(仅支持基于 Spring 的应用程序),对访问权限进行认证和授权,它基于 Spring AOP 和 Servlet 过滤器,提供了安全性方面的全面解决方案。
除常规的认证和授权外,它还提供了 ACLs、LDAP、JAAS、CAS 等高级特性以满足复杂情况下的安全需求。
1.1 焦点概念

Spring Security 的 3 个焦点概念。


  • Principle:代表用户的对象 Principle(User),不仅指人类,还包罗统统可以用于验证的装备。
  • Authority:代表用户的角色 Authority(Role),每个用户都应该有一种角色,如管理员或是会员。
  • Permission:代表授权,复杂的应用情况必要对角色的权限进行表述。
在 Spring Security 中,Authority 和 Permission 是两个完全独立的概念,两者并没有必然的接洽。它们之间必要通过配置进行关联,可以是自己定义的各种关系。
1.2 认证和授权

安全重要分为 验证(authentication)和 授权(authorization)两个部分。
1.2.1 验证(authentication)

验证 指的是,创建系统使用者信息(Principal)的过程。使用者可以是一个用户、装备,和可以在应用程序中执行某种操作的其他系统。
用户认证一样平常要求用户提供用户名和暗码,系统通过校验用户名和暗码的精确性来完成认证的通过或拒绝过程。
Spring Security 支持主流的认证方式,包罗 HTTP 根本认证、 HTTP 表单验证、HTTP 摘要认证、Open ID 和 LDAP 等。
Spring Security 进行验证的步调如下。


  • 1️⃣ 用户使用用户名和暗码登录。
  • 2️⃣ 过滤器(UsemamePasswordAuthenticationFilter)获取到用户名、暗码,然后封装成 Authentication。
  • 3️⃣ AuthenticationManager 认证 token (Authentication 的实现类通报)。
  • 4️⃣ AuthenticationManager 认证成功,返回一个封装了用户权限信息的 Authentication 对象, 用户的上下文信息(角色列表等)。
  • 5️⃣ Authentication 对象赋值给当前的 SecurityContext,创建这个用户的安全上下文(通过调用 SecurityContextHolder.getContext().setAuthentication())。
  • 6️⃣ 用户进行一些受到访问控制机制保护的操作,访问控制机制会依据当前安全上下文信息检查这个操作所需的权限。
除使用提供的认证外,还可以编写自己的 Filter(过滤器),提供与那些不是基于 Spring Security 的验证系统的操作。
1.2.2 授权(authorization)

在一个系统中,差别用户具有的权限是差别的。一样平常来说,系统会为差别的用户分配差别的角色,而每个角色则对应一系列的权限。
它判定某个 Principal 在应用程序中是否答应执行某个操作。在进行授权判定之前,要求其所要使用到的规则必须在验证过程中已经创建好了。
对 Web 资源的保护,最好的办法是使用过滤器。对方法调用的保护,最好的办法是使用 AOP。
Spring Security 在进行用户认证及授予权限时,也是通过各种拦截器和 AOP 来控制权限访问的,从而实现安全。
1.3 模块

名称模块           表明     焦点模块spring-security-core.jar包罗焦点验证和访问控制类和接口,以及支持远程配置的根本 API。远程调用spring-security-remoting.jar提供与 Spring Remoting 集成。网页spring-security-web.jar包罗网站安全的模块,提供网站认证服务和基于 URL 访问控制。配置spring-security-config.jar包罗安全命令空间解析代码。LDAPspring-security-ldap.jarLDAP 验证和配置。ACLspring-security-acl.jar对 ACL 访问控制表的实现。CASspring-security-cas.jar对 CAS 客户端的安全实现。OpenlDspring-security-openid.jar对 OpenID 网页验证的支持。Testspring-security-test.jar对 Spring Security 的测试的支持。 2.焦点类


2.1 Securitycontext

SecurityContext 中包罗 当前正在访问系统的用户的详细信息,它只有以下两种方法。


  • getAuthentication():获取当前经过身份验证的主体或身份验证的请求令牌。
  • setAuthentication():更改或删除当前已验证的主体身份验证信息。
SecurityContext 的信息是由 SecurityContextHolder 来处理的。
2.2 SecurityContextHolder

SecurityContextHolder 用来保存 SecurityContext。最常用的是 getContext() 方法,用来得到当前 SecurityContext。

SecurityContextHolder 中定义了一系列的静态方法,而这些静态方法的内部逻辑是通过 SecurityContextHolder 持有的 SecurityContextHolderStrategy 实现的,如 clearContext()、getContext()、setContext()、createEmptyContext()。
SecurityContextHolderStrategy 的关键代码如下:
  1. public interface SecurityContextHolderStrategy {
  2.   void clearContext();
  3.   Securitycontext getContext();
  4.   void setContext(SecurityContext context);
  5.   Securitycontext createEmptyContext();
  6. }
复制代码
2.2.1 strategy 实现

默认使用的 strategy 就是基于ThreadLocal 的 ThreadLocalSecurityContextHolderStrategy 来实现的。
除了上述提到的,Spring Security 还提供了 3 种范例的 strategy 来实现。


  • GlobalSecurityContextHolderStrategy:表示全局使用同一个 SecurityContext,如 C/S 布局的客户端。
  • InheritableThreadLocalSecurityContextHolderStrategy:使用 InheritableThreadLocal 来存放 Securitycontext,即子线程可以使用父线程中存放的变量。
  • ThreadLocalSecurityContextHolderStrategy: 使用 ThreadLocal 来存放 SecurityContext。
—般情况下,使用默认的 strategy 即可。但是,假如要改变默认的 strategy,Spring Security 提供了两种方法来改变 strategyName。
SecurityContextHolder 类中有 3 种差别范例的 strategy, 分别为 MODE_THREADLOCAL、MODE_INHERITABLETHREADLOCAL 和 MODE_GLOBAL,关键代码如下:
  1. public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";
  2. public static final String MODEJNHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";
  3. public static final String MODE_GLOBAL = "MODE_GLOBAL";
  4. public static final String SYSTEM_PROPERTY = "spring.security.strategy";
  5. private static String strategyName = System.getProperty(SYSTEM_PROPERTY);
  6. private static SecurityContextHolderStrategy strategy;
复制代码
MODE_THREADLOCAL 是默认的方法。
假如要改变 strategy,则有下面两种方法:


  • 通过 SecurityContextHolder 的静态方法 setStrategyName(java.lang.String strategyName) 来改变必要使用的 strategy。
  • 通过系统属性(SYSTEM_PROPERTY)行指定,此中属性名默认为 spring.security. strategy,属性值为对应 strategy 的名称。
2.2.2 获取当前用户的 SecurityContext

Spring Security 使用一个 Authentication 对象来形貌当前用户的相干信息。SecurityContextHolder 中持有的是当前用户的Securitycontext,而 SecurityContext 持有的是代表当前用户相干信息的 Authentication 的引用。
这个 Authentication 对象不必要自己创建,Spring Security 会主动创建相应的 Authentication 对象,然后赋值给当前的 SecurityContext。但是,每每必要在程序中获取当前用户的相干信息,比如最常见的是获取当前登录用户的用户名。在程序的任何地方,可以通过如下方式获取到当前用 户的用户名。
  1. public String getCurrentUsername() {
  2.   Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  3.   if (principal instanceof UserDetails){
  4.     return ((UserDetails) principal).getUsermame();
  5.   }
  6.   if (principal instanceof Principal) {
  7.     return ((Principal) principal).getName();
  8.   }
  9.   return String.valueOf(principal);
  10. }
复制代码


  • getAuthentication() 方法会返回认证信息。
  • getPrincipal() 方法返回身份信息,它是 UserDetails 对身份信息的封装。
获取当前用户的用户名,最简单的方式如下:
  1. public String getCurrentUsername() (
  2.   return SecurityContextHolder.getContext().getAuthentication().getName();
  3. )
复制代码
在调用 SecurityContextHolder.getContext() 获取 Securitycontext 时,假如对应的 Securitycontext 不存在,则返回空的 SecurityContext。
2.3 ProviderManager

ProviderManager 会维护 一个认证的列表,以便处理差别认证方式的认证,因为系统可能会存在多种认证方式,比如手机号、用户名暗码、邮箱方式。
在认证时,假如 ProviderManager 的认证结果不是 null,则阐明认证成功,不再进行其他方式的认证,并且作为认证的结果保存在 SecurityContext 中。假如不成功,则抛堕落误信息 ProviderNotFoundException。
2.4 DaoAuthenticationProvider

它是 AuthenticationProvider 最常用的实现,用来获取用户提交的用户名和暗码,并进行精确性比对。假如精确,则返回一个数据库中的用户信息。
当用户在前台提交了用户名和暗码后,就会被封装成 UsemamePasswordAuthenticationToken。
然后,DaoAuthenticationProvider 根据 retrieveUser 方法,交给 additionalAuthenticationChecks 方法完成 UsemamePasswordAuthenticationToken 和 UserDetails 暗码的比对。假如这个方法没有抛出非常,则认为比对成功。
比对暗码必要用到 PasswordEncoderSaltSource
2.5 UserDetails

UserDetails 是 Spring Security 的 用户实体类,包罗用户名、暗码、权限等信息。Spring Security 默认实现了内置的 User 类,供 Spring Security 安全认证使用。固然,也可以自己实现。
UserDetails 接口和 Authentication 接口很雷同,都拥有 username 和 authorities。肯定要区分清楚 Authentication 的 getCredentials() 与 UserDetails 中的 getPassword()。前者用户提交的暗码凭证,不愿定是精确的,或数据库不愿定存在;后者用户精确的暗码,认证器要进行比对的就是两者是否相同。
Authentication 中的 getAuthorities() 方法是由 UserDetails 的 getAuthorities() 通报而形成的。UserDetails 的用户信息是经过 AuthenticationProvider 认证之后被填充的。
UserDetails 中提供了以下几种方法。


  • String getPassword():返回验证用户暗码,无法返回则显示为 null。
  • String getUsername():返回验证用户名,无法返回则显示为 null。
  • boolean isAccountNonExpired():账户是否逾期,逾期无法验证。
  • boolean isAccountNonLocked():指定用户是否被锁定或解锁,锁定的用户无法逬行身份验证。
  • boolean isCredentialsNonExpired():指定是否已逾期的用户的根据(暗码),逾期的根据无法认证。
  • boolean isEnabled():是否被禁用。禁用的用户不能进行身份验证。

2.6 UserDetailsService

用户相干的信息是通过 UserDetailsService 接口来加载的。该接口的唯一方法是 loadUserByUsername(String username),用来 根据用户名加载相干信息
这个方法的返回值是 UserDetails 接口,此中包罗了用户的信息,包罗用户名、暗码、权限、是否启用、是否被锁定、是否逾期等。
2.7 GrantedAuthority

GrantedAuthority 中只定义了一个 getAuthority() 方法。该方法返回一个字符串,表示对应权限的字符串。假如对应权限不能用字符串表示,则返回 null。
GrantedAuthority 接口通过 UserDetailsService 进行加载,然后赋予 UserDetails。
Authentication 的 getAuthorities() 方法可以返回当前 Authentication 对象拥有的权限,其返回值是一个 GrantedAuthority 范例的数组。每一个 GrantedAuthority 对象代表赋予当前用户的一种权限。
2.8 Filter

            Filter 范例                阐明     SecurityContextPersistenceFilter它从 SecurityContextRepository 中取出用户认证信息。为了提高效率,制止每次请求都要查询认证信息,它会从 Session 中取出已认证的用户信息,然后将其放入 SecurityContextHolder 中,以便其他 Filter 使用。WebAsyncManagerlntegrationFilter集成了 SecurityContext 和 WebAsyncManager,把 SecurityContext 设置到异步线程,使其也能获取到用户上下文认证信息。HeaderWriterFilter它对请求的 Header 添加相应的信息。CsrfFilter跨域请求伪造过滤器。通过客户端传过来的 token 与服务器端存储的 token 进行对比,来判定请求的正当性。LogoutFilter匹配登出 URL。匹配成功后,退出用户,并清除认证信息。UsernamePasswordAuthenticationFilter登录认证过滤器,默认是对 /login 的 POST 请求进行认证。该方法会调用 attemptAuthentication,实验获取一个 Authentication 认证对象,以保存认证信息,然后转向下一个 Filter,末了调用 successfulAuthentication 执行认证后的事件。AnonymousAuthenticationFilter假如 SecurityContextHolder 中的认证信息为空,则会创建一个匿名用户到 SecurityContextHolder 中。SessionManagementFilter长期化登录的用户信息。用户信息会被保存到 Session、Cookie 或 Redis 中。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表