本文爲轉載學習java
原來你連接:http://blog.csdn.net/dsundsun/article/details/11847279spring
咱們看一看UserDetailsService爲咱們提供了那些實現類。安全
裏邊還提供了一個名爲JdbcuserDetailsManager的JdbcDaoImpl(UserDetailsService的子類)的實現類。那他到底是如何擴展jdbcDaoImpl的呢?mvc
他的類中,又定義了不少的SQL語句,並且添加了不少方法,很明顯,他對JdbcDaoImpl進行了功能上的擴展。app
書中提供了一些擴展的舉例:ide
若是是這樣的話,上次的修改密碼的功能,它也幫助咱們實現了,寫到這,咱們能夠猜出來,其實配置它和配置上一個自定義的JdbcDaoImpl是同樣的。學習
<bean id="jdbcUserService" class="org.springframework.security.provisioning.JdbcUserDetailsManager" > <property name= "dataSource" ref="dataSource" /> <property name="authenticationManager" ref="authenticationManager" /> </bean >
spring security配置:this
<authentication-manager alias="authenticationManager" > <authentication-provider user-service-ref="jdbcUserService" /> </authentication-manager >
這個配置,惟一一個優勢區別的就是要在jdbcUserService中配置一下authenticationManager,那麼爲何要設置這個屬性呢?咱們經過查看源碼就能夠找到答案的:spa
/* */ protected void initDao() throws ApplicationContextException /* */ { /* 129 */ if (this. authenticationManager == null) { /* 130 */ this.logger.info( "No authentication manager set. Reauthentication of users when changing passwords will not be performed."); /* */ } /* */ /* 134 */ super.initDao(); /* */ } /* */ public void changePassword(String oldPassword, String newPassword) throws AuthenticationException { /* 192 */ Authentication currentUser = SecurityContextHolder.getContext().getAuthentication(); /* */ /* 194 */ if (currentUser == null) /* */ { /* 196 */ throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user."); /* */ } /* */ /* 200 */ String username = currentUser.getName(); /* */ /* 203 */ if (this. authenticationManager != null) { /* 204 */ this.logger .debug("Reauthenticating user '" + username + "' for password change request."); /* */ /* 206 */ this.authenticationManager .authenticate(new UsernamePasswordAuthenticationToken(username, oldPassword)); /* */ } else { /* 208 */ this.logger.debug( "No authentication manager set. Password won't be re-checked."); /* */ } /* */ /* 211 */ this.logger.debug( "Changing password for user '" + username + "'"); /* */ /* 213 */ getJdbcTemplate().update(this .changePasswordSql , new Object[] { newPassword, username }); /* */ /* 215 */ SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(currentUser, newPassword)); /* */ /* 217 */ this.userCache.removeUserFromCache(username); /* */ }
咱們能夠推斷出來,只有更改密碼時會使用到,因此若是不設置authenticationManager屬性的話,更改密碼會失敗的。.net
spring mvc中是這樣修改密碼的:
@RequestMapping(value= "/account/changePassword.do",method=RequestMethod.POST) public String submitChangePasswordPage(@RequestParam ("password" ) String newPassword) { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String username = principal.toString(); if (principal instanceof UserDetails) { username = ((UserDetails)principal).getUsername(); } changePasswordDao.changePassword( username, newPassword); SecurityContextHolder. clearContext(); return "redirect:home.do" ; }
那麼。這裏邊涉及到了一個叫作SecurityContextHolder的對象,這個對象是作什麼用的呢?
它能夠獲取認證信息(經過認證流程之後會返回一個新的Authentication,前幾回咱們已經說過了):SecurityContextHolder.getContext().getAuthentication();
返回Authentication而後經過getPrincipal()方法獲取安全實體(咱們把它想象成安全對像就行),返回值是Object類型,也就是說,他可使任何對象類型,通常來講是UserDetails,但有時也是username(這個通常是UserDetails中的一部分).
獲取用戶名完成之後,能夠經過咱們前邊定義好的修改密碼類(JdbcUserDetailsManager)實現修改密碼。
接着又有一句話叫作:SecurityContextHolder. clearContext(); 那麼它完成了什麼功能呢,很遺憾,我再電子書和官方的幫助文檔中都沒有找到,因此我查詢了spring security API:
就是說,當我調用這個方法之後,咱們將清除Security 上下文中的全部當前線程中的值(看起來挺好用的)。