UserNamePasswrodAuthenticationFilter验证过程
来源:互联网 发布:声音训练教程软件 编辑:程序博客网 时间:2024/04/27 22:08
体系结构
AuthenticationManager的体系结构
AuthenticationProvider
其实,在UserNamePasswrodAuthenticationFilter中,验证是通过AuthenticationManager,但AuthenticationManager就相当于一个AuthenticationProvider容器,会把验证转让给集合中的AuthenticationProvider去验证
请求一个index.jsp页面,由于页面不足,他会自动把请求承递到spring_security_login,也就是由DefaultLoginPageGeneratingFilter自动生成的一个登录页面
登陆界面
页面源码
第一次登录页面时候,服务器会产生一个Session,并把cookieid返回来给浏览器,所以可以看到请求地址行的请求参数中带有jsesessionid,其实就是一个cookie值了
同时,以spring_security_check结尾(不算上jessessionid参数)所以会激发filter UserNamePasswrodAuthenticationFilter了
接下来看一下他是怎么处理的
进入attempAuthentication()中
再看一下getAuthenticationManager()
可见authenticationManager默认实现是ProviderManager
以下对ProviderManager的authenticate源码进行仔细解读了
//ProviderManager.authenticatepublic Authentication authenticate(Authentication authentication) throws AuthenticationException { Class<? extends Authentication> toTest = authentication.getClass(); AuthenticationException lastException = null; Authentication result = null; boolean debug = logger.isDebugEnabled(); for (AuthenticationProvider provider : getProviders()) { if (!provider.supports(toTest)) { continue; } if (debug) { logger.debug("Authentication attempt using " + provider.getClass().getName()); } try { result = provider.authenticate(authentication); if (result != null) { copyDetails(authentication, result); break; } } catch (AccountStatusException e) { prepareException(e, authentication); // SEC-546: Avoid polling additional providers if auth failure is due to invalid account status throw e; } catch (AuthenticationException e) { lastException = e; } } if (result == null && parent != null) { // Allow the parent to try. try { result = parent.authenticate(authentication); } catch (ProviderNotFoundException e) { // ignore as we will throw below if no other exception occurred prior to calling parent and the parent // may throw ProviderNotFound even though a provider in the child already handled the request } catch (AuthenticationException e) { lastException = e; } } if (result != null) { if (eraseCredentialsAfterAuthentication && (result instanceof CredentialsContainer)) { // Authentication is complete. Remove credentials and other secret data from authentication ((CredentialsContainer)result).eraseCredentials(); } eventPublisher.publishAuthenticationSuccess(result); return result; } // Parent was null, or didn't authenticate (or throw an exception). if (lastException == null) { lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound", new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}")); } prepareException(lastException, authentication); throw lastException; }
看上面代码中的第一个for循环
配置文件中没有配置其他的AuthenticationProvider,所以采用默认实现AnonymousAuthenticationManager去验证
这里可见AuthenticationManager其实里面还分装这一个parent,他也是一个ProviderManager(AuthenticationManager),而他的默认的providers集合里面有一个DaoAuthenticationProvider
parent的验证过程也是一样的,只不过这次的provider是DaoAuthenticationProvider了
再看一下provider.authenticate()实现
看一下retriveUser()中的实现
这里是根据我们登录界面提交的用户名去检索一个UserDetails,其中包括用户的密码,权限还有一下相信信息,我们只要在Hibernate中加入一个UserDetailsService就可以实现,用户名和密码等存储在数据库了,当然,我们这里只是简单的将用户名guest和密码guest配置在配置文件中而已了
再看一下additionAuthenticationChecks()中的实现吧
这里简单的检查一下,我们的密码有没有加入艳值salt(salt可以在密码中对密码加密的时候一起加上去加密,增加破解难度),明显,我们这里没有,然后他会把我们之前在登录界面输入用户名密码的一个封装Authentication和数据库或者配置文件中获取的UserDetails的密码进行匹配
于是,验证成功了,回到AbstractAuthenticationFilter中看successfulAuthentication(request, response, chain, authResult);的实现,他会接着调用successfulAuthentication()
红色部分,将验证成功的实体加入SecurityContextHolder,如果配置了rememberMeService,他还会将请求成功的实体加入rememberme中的缓存,以便下次可以实现remember me功能了
验证成功了,filter链不再继续进行下去了,于是一路返回
我们回去看SecurityContextPersistentFilter中借来下的处理吧
可见,验证登录过的用户下次就不用在登录了,因为springsecurity已经把上次登录成功的securityContext加入了SecurityContextRepository了
于是,登录成功了
总结
1、UserNamePasswrodAuthenticationFilter的处理过程就是先从登录界面中得到的Authentication(用户名和密码的封装实体)中的用户名去寻找配置文件或者数据库中的用户信息,并把该信息进行分装成一个UserDetails
2、将Authentication和UserDetails进行密码的匹配,可能还会涉及到盐值salt
3、若请求成功,则进行一些列设定,包括securityContext、rememberme、还有缓存该登陆成功的用户信息,用session进行标识,避免他登录过期,替换新的session(这会根据你在sessionManngerfilter中的配置,是新建还是迁移)
0 0
- UserNamePasswrodAuthenticationFilter验证过程
- DNA验证过程
- Forms验证的过程
- Forms验证的过程
- discuz验证过程
- NTLM验证过程
- 验证证书的过程
- Ouath 验证过程
- NTLM验证过程
- 数字证书验证过程
- ZKTFinger指纹验证过程
- Keystone验证过程
- SSL 验证过程
- springsecurity3的验证过程
- Laravel 自定义验证过程
- 四位验证码简单验证过程
- 验证交换机STP选举过程
- 活动目录验证过程原理
- CodeCombat-命令下属
- 保留的页框池
- 80X86指令集
- 醉追诅酌纵仔住嘴锥追组族卒篆赚篆amszmk
- 看遍炎凉薄寡,听惯蜚短流长
- UserNamePasswrodAuthenticationFilter验证过程
- checkio (Numbers Factory)
- hdu 2012 素数判定(打表)(备战LQB)
- .NET平台下websocket协议的实现!
- cocos2dx视频教程进阶篇--第2天--打砖块游戏-box2d物理引擎--续
- cocos2dx视频教程进阶篇--第2天--打砖块游戏-box2d物理引擎
- hdu 1506
- Android输入法与自定义软键盘初探
- linux进程间通信之实名管道