Spring Security详解

认识Spring Security

基于SpringAOP和Servlet过滤器,除了常规的认证和授权外,还提供了ACLs,LDAP,JAAS,CAS等高级特性以满足复杂环境下的安全需求
Spring Security的三个核心概念

  • Principle:代表用户的对象Princple(User) 不仅指人类,还包括一切可以用于验证的设备
  • Authority:代表用户的角色Authority(Role),每个用户都应该有一种角色,如管理员或会员
  • Permission:代表授权,复杂的应用环境需要对角色的权限进行表述

Spring Security的认证和授权

  • 验证指的是,建立系统使用者信息(Principal)的过程,用户认证一般要求用户提供用户名和密码,系统通过校验用户名和密码的正确性来完成认证的通过或拒绝过程,支持主流的认证方式,包括HTTP基本认证,HTTP表单验证,HTTP摘要认证,OpenID和LDAP等

验证的步骤:

  1. 用户使用用户名和密码登录
  2. 过滤器获取到用户名,密码人后封装成Authentication
  3. AuthenticationManager认证Token
  4. AuthenticationManager认证成功,返回一个封装了用户权限信息的Authentication对象,用户的上下文信息
  5. Authentication对象赋值给当前的SecurityContext,建立这个用户的安全上下文
  6. 用户进行一些受到访问控制机制保护的操作,访问控制机制会依据当前安全上下文信息检查这个操作所需的权限
  • 授权指的是,判断某个principal在应用程序中是否允许执行某个操作,在进行授权判断前,要求其所要使用到的规则必须在验证过程中已经建立好了,Spring Security在进行用户认证及授予权限时,也是通过各种拦截器和AOP来控制访问,从而实现安全

Spring Security的核心类

  1. SecurityContext
    SecurityContext中包含当前正在访问系统的用户的详细信息,有两种方法
  • getAuthentication():获取当前经过身份验证的主体或身份验证的请求令牌
  • SetAuthentication():更改或删除当前已验证的主体身份验证信息
    SecurityContext的信息是由SecurityContextHolder来处理的
  1. SecurityContextHolder
    SecurityContextHolder用来保存SecurityContext,最常用的是getContext()方法,用于获取当前的SecurityContext
    SecurityContextHolderStrategy接口的关键代码
public interface SecurityContextHolderStrategy{
	void clearContext();
	SecurityContext getContext();
	void setContext(SecurityContext context);
	SecurityContext createEmptyContext();
}

strategy实现
默认使用的strategy就是基于ThreadLocal的ThreadLocalSecurityContextHolderStrategy来实现的
Spring Security提供了三种类型的strategy来实现

  • GlobalSecurityContextHolderStrategy:表示全局使用一个SecurityContext
  • InheritableThreadLocalSecurityContextHolderStrategy:使用InheritableThreadLocal来存放SecurityContext,即子线程可以使用父线程中存放的变量
  • ThreadLocalSecurityContextHolderStrategy:使用Threadlocal来存放SecurityContext

strategy有3种不同的类型,分别为MODE_THREADLOCAL,MODE_INHERITABLETHREADLOCAL和MODE_GLOBAL
一般默认的strategy就够了,如果要改变strategy,有两种方法:

  • 通过SecurityContextHolder的静态方法setStrategyName(java.lang.String.strategyName)来改变需要使用的strategy
  • 通过系统属性(SYSTEM_PROPERTY)进行指定,其中属性名默认为"Spring.security.strategy",属性值为对应strategy的名称

获取当前用户的SecurityContext
Spring Security使用一个Authentication对象来描述当前用户的相关信息,Security-ContextHolder中持有的是当前用户的SecurityContext,而SecurityContext持有的是代表当前用户相关信息的Authentication的引用
在程序的任何地方,可以通过如下方式获取到当前用户的用户名

public String getCurrentUsername(){
	Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
	if(principal instanceof UserDetails){
		return ((UserDetails)principal).getUsername();
	}
	if(principal instanceof Principal){
		return ((Principal)principal).getName();
	}
	return String.valueOf(principal);
}

getAuthentication()方法会返回认证信息
getPrincipal()方法返回身份信息,它是UserDetails对身份信息的封装

  1. ProviderManager
    ProviderManager会维护一个认证的列表,以便处理不同认证方式的认证,认证时,如果ProviderManager的认证结果不是null,则说明认证成功,不再进行其他方式的认证,认证结构保存在SecurityContext,不成功抛出错误信息

  2. DaoAuthenticationProvider
    是AuthenticationProvider最常用的实现,用来获取用户提交的用户名和密码,并进行正确性对比,如果正确,则返回一个数据库中的用户信息,
    前台提交完用户名和密码后,会被封装成UsernamepasswordAuthentication-Token,然后DaoAuthenticationProvider根据retrieveUser方法,交给additionalAuthentication-Checks方法完成U色那么PasswordAuthenticationToken和UserDetails密码的䶏对比,如果没有抛出异常,则认为对比成功

  3. UserDetails
    UserDetails是Spring Security的用户实体类,包含用户名,密码,权限等信息,Spring Security默认实现了内置的User类,供Spring Security安全认证使用,也可以自己实现
    UserDetails提供了以下几种方法

  • String getPassword():返回验证用户密码,无法返回则显示为null
  • String getUsername():返回验证用户名,无法返回则显示为null
  • boolean isAccountNonExpired():账户是否过期,过期无法验证
  • boolean isAccountNonLocked():指定用户是否被锁定或解锁,锁定的用户无法进行身份验证
  • boolean isCredentialsNonExpired():指定是否已过期的用户的凭据,过期的凭据无法认证
  • boolean isEnabled():是否被禁用
  1. UserDetailsService
    用户的相关信息通过UserDetailsService接口来加载的,该接口的唯一方法是loadUserByUsername(String username),用来根据用户名加载相关信息,这个方法的返回值是UserDetails接口

  2. GrantedAuthority
    指定了一个getAuthority()方法,该方法返回一个字符串,表示对应权限的字符串,GrandtedAuthority接口通过UserDetailsService进行加载,然后赋予UserDetails,

  3. Filter

  • SecurityContextPersistenceFilter:从SecurityContextRepository中取出用户认证信息,从Session中取出已认证的用户信息,然后将其放入SecurityContextHolder中,以便其他Filter使用
  • WebAsyncManagerIntegrationFilter:集成了SecurityContext和WebAsyncManager,把SecurityContext设置到异步线程,使其也能获取到用户上下文认证信息
  • HanderWriterFilter:它对请求的Header添加相应的信息
  • CsrfFilter:跨域请求伪造过滤器,通过客户端传过来的token与服务器端存储的token进行对比,判断请求合法性
  • LogoutFilter:匹配登出URL,匹配成功后,退出用户,并清除认证信息
  • UsernamePasswordAuthenticationFilter:登录认证过滤器
  • AnonymousAuthenticationFilter:如果SecurityContextHolder中的认证信息为空,则会创建一个匿名用户
  • SessionManagementFilter:持久化登录的用户信息,用户信息会被保存到Session,Cookie或Redis中

你可能感兴趣的:(java)