Spring Security 认证原理

    1. 背景介绍: 在认识Spring Security以前,全部的权限验证逻辑都混杂在业务逻辑中,用户的每一个操做之前可能都须要对用户是否有进行该项操做的权限进行判断,来达到认证受权的目的。相似这样的权限验证逻辑代码被分散在系统的许多地方,难以维护。 spring security的简单原理: ![输入图片说明] 其实spring security这样的权限框架就是根据一系列的依赖代理(delegates)和servlet过滤器来实现的。 Spring security使用众多的拦截器对url拦截,以此来管理权限。大体流程: 输入图片说明
    1. 这里是列表文本这里是列表文本认证过程—Authentication具体实现类的对象—>:SecurityContextHolder 输入图片说明
    1. AuthenticationManager —>ProviderManager AuthenticationManager是一个用来处理认证(Authentication)请求的接口。在Spring Security中,AuthenticationManager的默认实现是ProviderManager。 输入图片说明 输入图片说明
    1. 校验认证获取用户信息—>DaoAuthenticationProvider—>UserDetailsService接口:
  • 用户信息—>数据库: 输入图片说明输入图片说明 根据请求的用户名加载对应的UserDetails,而后比对UserDetails的密码与认证请求的密码是否一致,一致则表示认证经过。Spring Security内部的DaoAuthenticationProvider就是使用的这种方式。其内部使用UserDetailsService来负责加载UserDetails,在认证成功之后会使用加载的UserDetails来封装要返回的Authentication对象,加载的UserDetails对象是包含用户权限等信息的。认证成功返回的Authentication对象将会保存在当前的SecurityContext中。经过Authentication.getPrincipal()返回一个UserDetails的实例。Spring Security内部使用的UserDetails实现类大都是内置的User类。 能够自定义UserDetails,在该实现类中咱们能够定义一些获取用户其它信息的方法,这样就能够直接从当前SecurityContext的Authentication的principal中获取自定义的信息了。
    1. 这里是列表文本SecurityContextHolder:用来保存SecurityContext 输入图片说明 **Q:**既然SecurityContext 是存放在 ThreadLocal 中的,并且在每次权限鉴定的时候都是从 ThreadLocal 中获取 SecurityContext 中对应的 Authentication 所拥有的权限,而且不一样的 request 是不一样的线程,为何每次均可以从 ThreadLocal 中获取到当前用户对应的 SecurityContext 呢? R: SecurityContextPersistentFilter: 输入图片说明 输入图片说明 在 Web 应用中这是经过 SecurityContextPersistentFilter 实现的,默认状况下其会在每次请求开始的时候从 session 中获取 SecurityContext,而后把它设置给 SecurityContextHolder,在请求结束后又会将 SecurityContextHolder 所持有的 SecurityContext 保存在 session 中,而且清除 SecurityContextHolder 所持有的 SecurityContext。这样当咱们第一次访问系统的时候,SecurityContextHolder 所持有的 SecurityContext 确定是空的,待咱们登陆成功后,SecurityContextHolder 所持有的 SecurityContext 就不是空的了,且包含有认证成功的 Authentication 对象,待请求结束后咱们就会将 SecurityContext 存在 session 中,等到下次请求的时候就能够从 session 中获取到该 SecurityContext 并把它赋予给 SecurityContextHolder 了,因为 SecurityContextHolder 已经持有认证过的 Authentication 对象了,因此下次访问的时候也就再也不须要进行登陆认证了。
    1. 这里是列表文本AbstractSecurityInterceptor FilterSecurityInterceptor, MethodSecurityInterceptor, AspectJSecurityInterceptor(JoinPoint) 自定义:从数据库中获取用户、权限、资源来实现权限管理 1) MySecurityFilter: 输入图片说明 从数据库中获取权限验证的数据,因此要重写FilterInvocationSecurityMetadataSource 接口, AccessDecisionManager 接口,UserDetailsService 接口。项目启动后,进行资源请求时,就自动会去执行咱们重定义的类进行权限判断。 a. MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource (资源数据定义) 加载全部url和权限的对应关系。 输入图片说明 b. MyAccessDecisionManager implements AccessDecisionManager 接口(过滤用户请求) 输入图片说明 参数说明: 一、configAttributes 装载了请求的url容许的角色数组 。这里是从MySecurityMetadataSource里的loadResourceDefine方法里的atts对象取出的角色数据赋予给了configAttributes对象 二、authentication 装载了从数据库读出来的角色数据。这里是从MyUserDetailsService里的loadUserByUsername方法里的auths对象的值传过来给 authentication 对象 [AbstractSecurityInterceptor有三个派生类 FilterSecurityInterceptor,负责处理FilterInvocation,实现对URL资源的拦截 MethodSecurityInterceptor,负责处理MethodInvocation,实现对方法调用的拦截 AspectJSecurityInterceptor,负责处理JoinPoint,主要是用于对切面方法(AOP)调用的拦截 还能够直接使用注解对Action方法进行拦截,例如在方法上加 @PreAuthorize("hasRole('ROLE_SUPER')");负责权限的控制,若是请求的url在权限集合中有这个url对应的值,则放行。注:若是数据库中没有对这个url定义访问的权限,默认是会被放行的] c. 认证管理器AuthenticationManager(用户认证的入口)—>UserDetailsService接口、 ![输入图片说明] MyUserDetailServiceImpl:【登陆验证+获取用户权限】 输入图片说明
相关文章
相关标签/搜索