作为一个Java入行“多”年的新手(这句话没毛病,因为一直在做Android),最近又开始做Java的项目。
最近在做spring security的集成,用于系统用户的权限验证。系统根据用户角色和对应的资源不同,校验和判断有无权限访问。user-role-rescourc.
spring security 原理是基于众多的过滤/拦截器实现。主要通过拦截url,认证授权,访问授权。
1.spring security shiro的比较
Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密
1.支持支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等),简单的身份认证(登录)
2.对角色的简单的签权(访问控制),支持细粒度的签权;支持一级缓存,以提升应用程序的性能;
3.非常简单的加密 API;不跟任何的框架或者容器捆绑,可以独立运行。
spring security 除了不能脱离Spring,shiro的功能它都有。
1.Spring Security支持CAS单点登录,支持Oauth、OpenID,Shiro则需要自己手动实现。(这几个我也没用过)Spring Security的权限细粒度更高。
发了一张spring security sample的截图
从网上找了一张spring security的验证执行流程图
2.认证授权
先看张图
AuthenticationManager它用来校验用户的凭证信息,或者会抛出一个特定的异常(校验失败的情况)或者完整填充Authentication对象,将会包含了权限信息。
AuthenticationProvider它为AuthenticationManager提供凭证校验。一些AuthenticationProvider的实现基于凭证信息的存储,如数据库,来判定凭证信息是否可以被认可。
spring security 中进行身份验证的是AuthenticationManager接口,ProviderManager是它的一个默认实现,但它并不用来处理身份认证,而是委托给配置好的AuthenticationProvider,每个AuthenticationProvider会轮流检查身份认证。检查后或者返回Authentication对象或者抛出异常
下图是从网上找的身份认证的时序图
AbstractAuthenticationProcessingFilter它在认证请求中使用。处理包含认证信息的请求,如认证信息可能是form POST提交的,SSO信息或者其他用户提供的。创建一个部分完整的Authentication对象以在链中传递凭证信息。
UsernamePasswordAuthentication 继承 AbstractAuthenticationProcessingFilter,是系统默认提供的实现类
UsernamePasswordAuthenticationFilter的验证过程如下:
1. 首先过滤器会调用自身的attemptAuthentication方法,从request中取出authentication, authentication是在org.springframework.security.web.context.SecurityContextPersistenceFilter过滤器中通过捕获用户提交的登录表单中的内容生成的一个org.springframework.security.core.Authentication接口实例.
2. 拿到authentication对象后,过滤器会调用ProviderManager类的authenticate方法,并传入该对象
3.ProviderManager类的authenticate方法再调用自身的doAuthentication方法,在doAuthentication方法中会调用类中的Listproviders集合中的各个AuthenticationProvider接口实现类中的authenticate(Authentication authentication)方法进行验证,由此可见,真正的验证逻辑是由各个各个AuthenticationProvider接口实现类来完成的,DaoAuthenticationProvider类是默认情况下注入的一个AuthenticationProvider接口实现类
4.AuthenticationProvider接口通过UserDetailsService 接口来获取用户信息,实现loadUserByUsername(String username)方法,至此已经认证通过。
3.访问授权
spring security 通过拦截访问的url,查询url对应的角色或权限信息,通过对比当前用户的信息,判断是否有权限访问
FilterSecurityInterceptor 继承AbstractSecurityInterceptor是默认实现,用于访问拦截
doFilter()方法会拦截到当前访问的url,并访问SecurityMetadataSource,AccessDecisionManager 接口
SecurityMetadataSource 资源管理器,负责组装角色资源
AccessDecisionManager,访问决策管理器,判定是不是有权限访问
可以通过继承FilterSecurityInterceptor,自定义自己的Filter实现自己的业务,自定义的需要提供SecurityMetadataSource,AccessDecisionManager,UserDetailsService的实现
4.最后
挣扎了几天,完成spring security项目的引入,中间也跳进过坑,翻阅过别人的博客,最后也慢慢爬出来,在此记录下最近的学习过程。感谢那些之前那些分享经验的人。
初次写博客,有错误的地方,欢迎同行一起交流,指正错误。