整体架构
spring security的核心是用来做权限管理的。权限管理中核心的是认证(Authentiaction)和授权(Authorization);在spring security架构设计中,认证和授权是分开的,无论使用什么样的认证方式,都不影响授权。
认证
AuthenticationManager:
在spring security中认证是由AuthenticatonManager接口负责
如果方法返回Authenticaton则表示认证成功,如果抛出AuthenticationException异常说明认证失败。其中Authentication参数包含:用户名和密码。接口肯定是没办法实现权限认证的,肯定会被某一个实现类去实现。
AuthenticationManager的主要实现类有:ProviderManager实现类,在spring security中有多套认证解决方案,所以在spring security中允许存多个AuthenticationProvider实例,用来实现多种认证方式。这些AuthenticationProvider是由ProviderManager整体管理。
Authenticaton:
authentication既是入参又是返回值。入参时只有用户名和密码,而返回时保存用户认证成功的相关信息。
SecurityContextHolder:
是用来获取用户登录之后的信息。spring security会降登录的用户数据保存到session中,为了方便使用,spring security做了一些改进,其中最主要的一个变化就是线程绑定。当用户登录成功后,spring security将用户信息保存到SecurityContextHolder中。而SecurityContextHolder默认是使用ThreadLocal来实现的。使用ThreadLocal创建的变量只能被当前线程访问,不能被其他线程访问和修改。当登录请求处理完毕后,spring security将SecurityContextHolder中的数据取出保存到session中,同时将SecurityContextHolder数据清空。每当有新的请求时,都会携带session ID,如果session ID能在服务器端找到对应的session并判断是否有Authentication,如果有则spring security就会从session中取出用户登录数据,并保存到SecurityContextHolder中,方便该请求在后续处理过程中使用。请求结束时将SecurityContextHolder中的数据清空保存到session中。
授权
AccessDecisionManager:
访问决策管理器,基于decide方法和AccessDecisionVoter来决定是否允许此次访问。
AccessDecisionVoter:
访问决定投票器,检查当前用户是否具备应有的角色,进而投出赞成、反对和弃权票。
AccessDecisionVoter和AccessDecisionManager都有很多实现类,在AccessDecisionManager中会遍历AccessDecisionVoter,进而决定用户是否允许访问。
ConfigAttribute:
用来保存授权时的角色信息。在spring security中用户访问一个资源需要的角色会被封装成一个ConfigAttribute对象。在ConfigAttribute中只有一个getAttribute方法,该方法返回一个String字符串。ROLE_为前缀。AccessDecisionVoter需要做的就是比较用户具有的角色和请求资源所需的ConfigAttribute之间的关系。
总结
认证的时候会用到AuthenticationManager,认证成功之后会将信息保存到Authenticaton中,为了方便回去认证之后的信息,可以通过SecurityContextHolder直接获取。当请求某个资源时,先经过AccessDecisionManager会将当前用户的角色封装成ConfigAttribute,同时调用AccessDecisionVoter进行比对,如果投票器投赞成,则表明当前用户允许访问,如果投反对,则抛出异常并返回无权限访问。