欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Spring源代碼解析(九):Spring Acegi框架鑒權的實(shí)現

簡(jiǎn)單分析一下Spring Acegi的源代碼實(shí)現:
Servlet.Filter的實(shí)現AuthenticationProcessingFilter啟動(dòng)Web頁(yè)面的驗證過(guò)程 - 在A(yíng)bstractProcessingFilter定義了整個(gè)驗證過(guò)程的模板:

Java代碼
  1. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)   
  2.     throws IOException, ServletException {   
  3.     //這里檢驗是不是符合ServletRequest/SevletResponse的要求   
  4.     if (!(request instanceof HttpServletRequest)) {   
  5.         throw new ServletException("Can only process HttpServletRequest");   
  6.     }   
  7.   
  8.     if (!(response instanceof HttpServletResponse)) {   
  9.         throw new ServletException("Can only process HttpServletResponse");   
  10.     }   
  11.   
  12.     HttpServletRequest httpRequest = (HttpServletRequest) request;   
  13.     HttpServletResponse httpResponse = (HttpServletResponse) response;   
  14.     //根據HttpServletRequest和HttpServletResponse來(lái)進(jìn)行驗證   
  15.     if (requiresAuthentication(httpRequest, httpResponse)) {   
  16.         if (logger.isDebugEnabled()) {   
  17.             logger.debug("Request is to process authentication");   
  18.         }   
  19.         //這里定義Acegi中的Authentication對象來(lái)持有相關(guān)的用戶(hù)驗證信息   
  20.         Authentication authResult;   
  21.   
  22.         try {   
  23.             onPreAuthentication(httpRequest, httpResponse);   
  24.             //這里的具體驗證過(guò)程委托給子類(lèi)完成,比如AuthenticationProcessingFilter來(lái)完成基于Web頁(yè)面的用戶(hù)驗證   
  25.             authResult = attemptAuthentication(httpRequest);   
  26.         } catch (AuthenticationException failed) {   
  27.             // Authentication failed   
  28.             unsuccessfulAuthentication(httpRequest, httpResponse, failed);   
  29.   
  30.             return;   
  31.         }   
  32.   
  33.         // Authentication success   
  34.         if (continueChainBeforeSuccessfulAuthentication) {   
  35.             chain.doFilter(request, response);   
  36.         }   
  37.         //完成驗證后的后續工作,比如跳轉到相應的頁(yè)面   
  38.         successfulAuthentication(httpRequest, httpResponse, authResult);   
  39.   
  40.         return;   
  41.     }   
  42.   
  43.     chain.doFilter(request, response);   
  44. }  
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {//這里檢驗是不是符合ServletRequest/SevletResponse的要求if (!(request instanceof HttpServletRequest)) {throw new ServletException("Can only process HttpServletRequest");}if (!(response instanceof HttpServletResponse)) {throw new ServletException("Can only process HttpServletResponse");}HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;//根據HttpServletRequest和HttpServletResponse來(lái)進(jìn)行驗證if (requiresAuthentication(httpRequest, httpResponse)) {if (logger.isDebugEnabled()) {logger.debug("Request is to process authentication");}//這里定義Acegi中的Authentication對象來(lái)持有相關(guān)的用戶(hù)驗證信息Authentication authResult;try {onPreAuthentication(httpRequest, httpResponse);//這里的具體驗證過(guò)程委托給子類(lèi)完成,比如AuthenticationProcessingFilter來(lái)完成基于Web頁(yè)面的用戶(hù)驗證authResult = attemptAuthentication(httpRequest);} catch (AuthenticationException failed) {// Authentication failedunsuccessfulAuthentication(httpRequest, httpResponse, failed);return;}// Authentication successif (continueChainBeforeSuccessfulAuthentication) {chain.doFilter(request, response);}//完成驗證后的后續工作,比如跳轉到相應的頁(yè)面successfulAuthentication(httpRequest, httpResponse, authResult);return;}chain.doFilter(request, response);}


在A(yíng)uthenticationProcessingFilter中的具體驗證過(guò)程是這樣的:

Java代碼
  1. public Authentication attemptAuthentication(HttpServletRequest request)   
  2.     throws AuthenticationException {   
  3.     //這里從HttpServletRequest中得到用戶(hù)驗證的用戶(hù)名和密碼   
  4.     String username = obtainUsername(request);   
  5.     String password = obtainPassword(request);   
  6.   
  7.     if (username == null) {   
  8.         username = "";   
  9.     }   
  10.   
  11.     if (password == null) {   
  12.         password = "";   
  13.     }   
  14.     //這里根據得到的用戶(hù)名和密碼去構造一個(gè)Authentication對象提供給AuthenticationManager進(jìn)行驗證,里面包含了用戶(hù)的用戶(hù)名和密碼信息   
  15.     UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);   
  16.   
  17.     // Place the last username attempted into HttpSession for views   
  18.     request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username);   
  19.   
  20.     // Allow subclasses to set the "details" property   
  21.     setDetails(request, authRequest);   
  22.     //這里啟動(dòng)AuthenticationManager進(jìn)行驗證過(guò)程   
  23.     return this.getAuthenticationManager().authenticate(authRequest);   
  24. }  
    public Authentication attemptAuthentication(HttpServletRequest request)throws AuthenticationException {//這里從HttpServletRequest中得到用戶(hù)驗證的用戶(hù)名和密碼String username = obtainUsername(request);String password = obtainPassword(request);if (username == null) {username = "";}if (password == null) {password = "";}//這里根據得到的用戶(hù)名和密碼去構造一個(gè)Authentication對象提供給AuthenticationManager進(jìn)行驗證,里面包含了用戶(hù)的用戶(hù)名和密碼信息UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);// Place the last username attempted into HttpSession for viewsrequest.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username);// Allow subclasses to set the "details" propertysetDetails(request, authRequest);//這里啟動(dòng)AuthenticationManager進(jìn)行驗證過(guò)程return this.getAuthenticationManager().authenticate(authRequest);}


在A(yíng)cegi框架中,進(jìn)行驗證管理的主要類(lèi)是AuthenticationManager,我們看看它是怎樣進(jìn)行驗證管理的 - 驗證的調用入口是authenticate在A(yíng)bstractAuthenticationManager的實(shí)現中:
//這是進(jìn)行驗證的函數,返回一個(gè)Authentication對象來(lái)記錄驗證的結果,其中包含了用戶(hù)的驗證信息,權限配置等,同時(shí)這個(gè)Authentication會(huì )以后被授權模塊使用

Java代碼
  1. //如果驗證失敗,那么在驗證過(guò)程中會(huì )直接拋出異常   
  2.     public final Authentication authenticate(Authentication authRequest)   
  3.         throws AuthenticationException {   
  4.         try {//這里是實(shí)際的驗證處理,我們下面使用ProviderManager來(lái)說(shuō)明具體的驗證過(guò)程,傳入的參數authRequest里面已經(jīng)包含了從HttpServletRequest中得到的用戶(hù)輸入的用戶(hù)名和密碼   
  5.             Authentication authResult = doAuthentication(authRequest);   
  6.             copyDetails(authRequest, authResult);   
  7.   
  8.             return authResult;   
  9.         } catch (AuthenticationException e) {   
  10.             e.setAuthentication(authRequest);   
  11.             throw e;   
  12.         }   
  13.     }  
//如果驗證失敗,那么在驗證過(guò)程中會(huì )直接拋出異常public final Authentication authenticate(Authentication authRequest)throws AuthenticationException {try {//這里是實(shí)際的驗證處理,我們下面使用ProviderManager來(lái)說(shuō)明具體的驗證過(guò)程,傳入的參數authRequest里面已經(jīng)包含了從HttpServletRequest中得到的用戶(hù)輸入的用戶(hù)名和密碼Authentication authResult = doAuthentication(authRequest);copyDetails(authRequest, authResult);return authResult;} catch (AuthenticationException e) {e.setAuthentication(authRequest);throw e;}}


在ProviderManager中進(jìn)行實(shí)際的驗證工作,假設這里使用數據庫來(lái)存取用戶(hù)信息:

Java代碼
  1. public Authentication doAuthentication(Authentication authentication)   
  2.     throws AuthenticationException {   
  3.     //這里取得配置好的provider鏈的迭代器,在配置的時(shí)候可以配置多個(gè)provider,這里我們配置的是DaoAuthenticationProvider來(lái)說(shuō)明, 它使用數據庫來(lái)保存用戶(hù)的用戶(hù)名和密碼信息。   
  4.     Iterator iter = providers.iterator();   
  5.   
  6.     Class toTest = authentication.getClass();   
  7.   
  8.     AuthenticationException lastException = null;   
  9.   
  10.     while (iter.hasNext()) {   
  11.         AuthenticationProvider provider = (AuthenticationProvider) iter.next();   
  12.   
  13.         if (provider.supports(toTest)) {   
  14.             logger.debug("Authentication attempt using " + provider.getClass().getName());   
  15.             //這個(gè)result包含了驗證中得到的結果信息   
  16.             Authentication result = null;   
  17.   
  18.             try {//這里是provider進(jìn)行驗證處理的過(guò)程   
  19.                 result = provider.authenticate(authentication);   
  20.                 sessionController.checkAuthenticationAllowed(result);   
  21.             } catch (AuthenticationException ae) {   
  22.                 lastException = ae;   
  23.                 result = null;   
  24.             }   
  25.   
  26.             if (result != null) {   
  27.                 sessionController.registerSuccessfulAuthentication(result);   
  28.                 publishEvent(new AuthenticationSuccessEvent(result));   
  29.   
  30.                 return result;   
  31.             }   
  32.         }   
  33.     }   
  34.   
  35.     if (lastException == null) {   
  36.         lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound",   
  37.                     new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}"));   
  38.     }   
  39.   
  40.     // 這里發(fā)布事件來(lái)通知上下文的監聽(tīng)器   
  41.     String className = exceptionMappings.getProperty(lastException.getClass().getName());   
  42.     AbstractAuthenticationEvent event = null;   
  43.   
  44.     if (className != null) {   
  45.         try {   
  46.             Class clazz = getClass().getClassLoader().loadClass(className);   
  47.             Constructor constructor = clazz.getConstructor(new Class[] {   
  48.                         Authentication.class, AuthenticationException.class  
  49.                     });   
  50.             Object obj = constructor.newInstance(new Object[] {authentication, lastException});   
  51.             Assert.isInstanceOf(AbstractAuthenticationEvent.class, obj, "Must be an AbstractAuthenticationEvent");   
  52.             event = (AbstractAuthenticationEvent) obj;   
  53.         } catch (ClassNotFoundException ignored) {}   
  54.         catch (NoSuchMethodException ignored) {}   
  55.         catch (IllegalAccessException ignored) {}   
  56.         catch (InstantiationException ignored) {}   
  57.         catch (InvocationTargetException ignored) {}   
  58.     }   
  59.   
  60.     if (event != null) {   
  61.         publishEvent(event);   
  62.     } else {   
  63.         if (logger.isDebugEnabled()) {   
  64.             logger.debug("No event was found for the exception " + lastException.getClass().getName());   
  65.         }   
  66.     }   
  67.   
  68.     // Throw the exception   
  69.     throw lastException;   
  70. }  
    public Authentication doAuthentication(Authentication authentication)throws AuthenticationException {//這里取得配置好的provider鏈的迭代器,在配置的時(shí)候可以配置多個(gè)provider,這里我們配置的是DaoAuthenticationProvider來(lái)說(shuō)明, 它使用數據庫來(lái)保存用戶(hù)的用戶(hù)名和密碼信息。Iterator iter = providers.iterator();Class toTest = authentication.getClass();AuthenticationException lastException = null;while (iter.hasNext()) {AuthenticationProvider provider = (AuthenticationProvider) iter.next();if (provider.supports(toTest)) {logger.debug("Authentication attempt using " + provider.getClass().getName());//這個(gè)result包含了驗證中得到的結果信息Authentication result = null;try {//這里是provider進(jìn)行驗證處理的過(guò)程result = provider.authenticate(authentication);sessionController.checkAuthenticationAllowed(result);} catch (AuthenticationException ae) {lastException = ae;result = null;}if (result != null) {sessionController.registerSuccessfulAuthentication(result);publishEvent(new AuthenticationSuccessEvent(result));return result;}}}if (lastException == null) {lastException = new ProviderNotFoundException(messages.getMessage("ProviderManager.providerNotFound",new Object[] {toTest.getName()}, "No AuthenticationProvider found for {0}"));}// 這里發(fā)布事件來(lái)通知上下文的監聽(tīng)器String className = exceptionMappings.getProperty(lastException.getClass().getName());AbstractAuthenticationEvent event = null;if (className != null) {try {Class clazz = getClass().getClassLoader().loadClass(className);Constructor constructor = clazz.getConstructor(new Class[] {Authentication.class, AuthenticationException.class});Object obj = constructor.newInstance(new Object[] {authentication, lastException});Assert.isInstanceOf(AbstractAuthenticationEvent.class, obj, "Must be an AbstractAuthenticationEvent");event = (AbstractAuthenticationEvent) obj;} catch (ClassNotFoundException ignored) {}catch (NoSuchMethodException ignored) {}catch (IllegalAccessException ignored) {}catch (InstantiationException ignored) {}catch (InvocationTargetException ignored) {}}if (event != null) {publishEvent(event);} else {if (logger.isDebugEnabled()) {logger.debug("No event was found for the exception " + lastException.getClass().getName());}}// Throw the exceptionthrow lastException;}


我們下面看看在DaoAuthenticationProvider是怎樣從數據庫中取出對應的驗證信息進(jìn)行用戶(hù)驗證的,在它的基類(lèi)AbstractUserDetailsAuthenticationProvider定義了驗證的處理模板:

Java代碼
  1. public Authentication authenticate(Authentication authentication)   
  2.     throws AuthenticationException {   
  3.     Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,   
  4.         messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports",   
  5.             "Only UsernamePasswordAuthenticationToken is supported"));   
  6.   
  7.     // 這里取得用戶(hù)輸入的用戶(hù)名   
  8.     String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();   
  9.     // 如果配置了緩存,從緩存中去取以前存入的用戶(hù)驗證信息 - 這里是UserDetail,是服務(wù)器端存在數據庫里的用戶(hù)信息,這樣就不用每次都去數據庫中取了   
  10.     boolean cacheWasUsed = true;   
  11.     UserDetails user = this.userCache.getUserFromCache(username);   
  12.     //沒(méi)有取到,設置標志位,下面會(huì )把這次取到的服務(wù)器端用戶(hù)信息存入緩存中去   
  13.     if (user == null) {   
  14.         cacheWasUsed = false;   
  15.   
  16.         try {//這里是調用UserDetailService去取用戶(hù)數據庫里信息的地方   
  17.             user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);   
  18.         } catch (UsernameNotFoundException notFound) {   
  19.             if (hideUserNotFoundExceptions) {   
  20.                 throw new BadCredentialsException(messages.getMessage(   
  21.                         "AbstractUserDetailsAuthenticationProvider.badCredentials""Bad credentials"));   
  22.             } else {   
  23.                 throw notFound;   
  24.             }   
  25.         }   
  26.   
  27.         Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");   
  28.     }   
  29.   
  30.     if (!user.isAccountNonLocked()) {   
  31.         throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked",   
  32.                 "User account is locked"));   
  33.     }   
  34.   
  35.     if (!user.isEnabled()) {   
  36.         throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled",   
  37.                 "User is disabled"));   
  38.     }   
  39.   
  40.     if (!user.isAccountNonExpired()) {   
  41.         throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired",   
  42.                 "User account has expired"));   
  43.     }   
  44.   
  45.     // This check must come here, as we don't want to tell users   
  46.     // about account status unless they presented the correct credentials   
  47.     try {//這里是驗證過(guò)程,在retrieveUser中從數據庫中得到用戶(hù)的信息,在additionalAuthenticationChecks中進(jìn)行對比用戶(hù)輸入和服務(wù)器端的用戶(hù)信息   
  48.           //如果驗證通過(guò),那么構造一個(gè)Authentication對象來(lái)讓以后的授權使用,如果驗證不通過(guò),直接拋出異常結束鑒權過(guò)程   
  49.         additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);   
  50.     } catch (AuthenticationException exception) {   
  51.         if (cacheWasUsed) {   
  52.             // There was a problem, so try again after checking   
  53.             // we're using latest data (ie not from the cache)   
  54.             cacheWasUsed = false;   
  55.             user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);   
  56.             additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);   
  57.         } else {   
  58.             throw exception;   
  59.         }   
  60.     }   
  61.   
  62.     if (!user.isCredentialsNonExpired()) {   
  63.         throw new CredentialsExpiredException(messages.getMessage(   
  64.                 "AbstractUserDetailsAuthenticationProvider.credentialsExpired""User credentials have expired"));   
  65.     }   
  66.     //根據前面的緩存結果決定是不是要把當前的用戶(hù)信息存入緩存以供下次驗證使用   
  67.     if (!cacheWasUsed) {   
  68.         this.userCache.putUserInCache(user);   
  69.     }   
  70.   
  71.     Object principalToReturn = user;   
  72.   
  73.     if (forcePrincipalAsString) {   
  74.         principalToReturn = user.getUsername();   
  75.     }   
  76.     //最后返回Authentication記錄了驗證結果供以后的授權使用   
  77.     return createSuccessAuthentication(principalToReturn, authentication, user);   
  78. }   
  79. //這是是調用UserDetailService去加載服務(wù)器端用戶(hù)信息的地方,從什么地方加載要看設置,這里我們假設由JdbcDaoImp來(lái)從數據中進(jìn)行加載   
  80. protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)   
  81.     throws AuthenticationException {   
  82.     UserDetails loadedUser;   
  83.     //這里調用UserDetailService去從數據庫中加載用戶(hù)驗證信息,同時(shí)返回從數據庫中返回的信息,這些信息放到了UserDetails對象中去了   
  84.     try {   
  85.         loadedUser = this.getUserDetailsService().loadUserByUsername(username);   
  86.     } catch (DataAccessException repositoryProblem) {   
  87.         throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);   
  88.     }   
  89.   
  90.     if (loadedUser == null) {   
  91.         throw new AuthenticationServiceException(   
  92.             "UserDetailsService returned null, which is an interface contract violation");   
  93.     }   
  94.     return loadedUser;   
  95. }  
    public Authentication authenticate(Authentication authentication)throws AuthenticationException {Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,messages.getMessage("AbstractUserDetailsAuthenticationProvider.onlySupports","Only UsernamePasswordAuthenticationToken is supported"));// 這里取得用戶(hù)輸入的用戶(hù)名String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();// 如果配置了緩存,從緩存中去取以前存入的用戶(hù)驗證信息 - 這里是UserDetail,是服務(wù)器端存在數據庫里的用戶(hù)信息,這樣就不用每次都去數據庫中取了boolean cacheWasUsed = true;UserDetails user = this.userCache.getUserFromCache(username);//沒(méi)有取到,設置標志位,下面會(huì )把這次取到的服務(wù)器端用戶(hù)信息存入緩存中去if (user == null) {cacheWasUsed = false;try {//這里是調用UserDetailService去取用戶(hù)數據庫里信息的地方user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);} catch (UsernameNotFoundException notFound) {if (hideUserNotFoundExceptions) {throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));} else {throw notFound;}}Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");}if (!user.isAccountNonLocked()) {throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked","User account is locked"));}if (!user.isEnabled()) {throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled","User is disabled"));}if (!user.isAccountNonExpired()) {throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired","User account has expired"));}// This check must come here, as we don't want to tell users// about account status unless they presented the correct credentialstry {//這里是驗證過(guò)程,在retrieveUser中從數據庫中得到用戶(hù)的信息,在additionalAuthenticationChecks中進(jìn)行對比用戶(hù)輸入和服務(wù)器端的用戶(hù)信息//如果驗證通過(guò),那么構造一個(gè)Authentication對象來(lái)讓以后的授權使用,如果驗證不通過(guò),直接拋出異常結束鑒權過(guò)程additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);} catch (AuthenticationException exception) {if (cacheWasUsed) {// There was a problem, so try again after checking// we're using latest data (ie not from the cache)cacheWasUsed = false;user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken) authentication);} else {throw exception;}}if (!user.isCredentialsNonExpired()) {throw new CredentialsExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.credentialsExpired", "User credentials have expired"));}//根據前面的緩存結果決定是不是要把當前的用戶(hù)信息存入緩存以供下次驗證使用if (!cacheWasUsed) {this.userCache.putUserInCache(user);}Object principalToReturn = user;if (forcePrincipalAsString) {principalToReturn = user.getUsername();}//最后返回Authentication記錄了驗證結果供以后的授權使用return createSuccessAuthentication(principalToReturn, authentication, user);}//這是是調用UserDetailService去加載服務(wù)器端用戶(hù)信息的地方,從什么地方加載要看設置,這里我們假設由JdbcDaoImp來(lái)從數據中進(jìn)行加載protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)throws AuthenticationException {UserDetails loadedUser;//這里調用UserDetailService去從數據庫中加載用戶(hù)驗證信息,同時(shí)返回從數據庫中返回的信息,這些信息放到了UserDetails對象中去了try {loadedUser = this.getUserDetailsService().loadUserByUsername(username);} catch (DataAccessException repositoryProblem) {throw new AuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);}if (loadedUser == null) {throw new AuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");}return loadedUser;}


下面我們重點(diǎn)分析一下JdbcDaoImp這個(gè)類(lèi)來(lái)看看具體是怎樣從數據庫中得到用戶(hù)信息的:

Java代碼
  1. public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService {   
  2.     //~ Static fields/initializers =====================================================================================   
  3.     //這里是預定義好的對查詢(xún)語(yǔ)句,對應于默認的數據庫表結構,也可以自己定義查詢(xún)語(yǔ)句對應特定的用戶(hù)數據庫驗證表的設計   
  4.     public static final String DEF_USERS_BY_USERNAME_QUERY =   
  5.             "SELECT username,password,enabled FROM users WHERE username = ?";   
  6.     public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY =   
  7.             "SELECT username,authority FROM authorities WHERE username = ?";   
  8.   
  9.     //~ Instance fields ================================================================================================   
  10.     //這里使用Spring JDBC來(lái)進(jìn)行數據庫操作   
  11.     protected MappingSqlQuery authoritiesByUsernameMapping;   
  12.     protected MappingSqlQuery usersByUsernameMapping;   
  13.     private String authoritiesByUsernameQuery;   
  14.     private String rolePrefix = "";   
  15.     private String usersByUsernameQuery;   
  16.     private boolean usernameBasedPrimaryKey = true;   
  17.   
  18.     //~ Constructors ===================================================================================================   
  19.     //在初始化函數中把查詢(xún)語(yǔ)句設置為預定義的SQL語(yǔ)句   
  20.     public JdbcDaoImpl() {   
  21.         usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY;   
  22.         authoritiesByUsernameQuery = DEF_AUTHORITIES_BY_USERNAME_QUERY;   
  23.     }   
  24.   
  25.     //~ Methods ========================================================================================================   
  26.   
  27.     protected void addCustomAuthorities(String username, List authorities) {}   
  28.   
  29.     public String getAuthoritiesByUsernameQuery() {   
  30.         return authoritiesByUsernameQuery;   
  31.     }   
  32.   
  33.     public String getRolePrefix() {   
  34.         return rolePrefix;   
  35.     }   
  36.   
  37.     public String getUsersByUsernameQuery() {   
  38.         return usersByUsernameQuery;   
  39.     }   
  40.   
  41.     protected void initDao() throws ApplicationContextException {   
  42.         initMappingSqlQueries();   
  43.     }   
  44.   
  45.     /**  
  46.      * Extension point to allow other MappingSqlQuery objects to be substituted in a subclass  
  47.      */  
  48.     protected void initMappingSqlQueries() {   
  49.         this.usersByUsernameMapping = new UsersByUsernameMapping(getDataSource());   
  50.         this.authoritiesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource());   
  51.     }   
  52.   
  53.     public boolean isUsernameBasedPrimaryKey() {   
  54.         return usernameBasedPrimaryKey;   
  55.     }   
  56.     //這里是取得數據庫用戶(hù)信息的具體過(guò)程   
  57.     public UserDetails loadUserByUsername(String username)   
  58.         throws UsernameNotFoundException, DataAccessException {   
  59.         //根據用戶(hù)名在用戶(hù)表中得到用戶(hù)信息,包括用戶(hù)名,密碼和用戶(hù)是否有效的信息   
  60.         List users = usersByUsernameMapping.execute(username);   
  61.   
  62.         if (users.size() == 0) {   
  63.             throw new UsernameNotFoundException("User not found");   
  64.         }   
  65.         //取集合中的第一個(gè)作為有效的用戶(hù)對象   
  66.         UserDetails user = (UserDetails) users.get(0); // contains no GrantedAuthority[]   
  67.         //這里在權限表中去取得用戶(hù)的權限信息,同樣的返回一個(gè)權限集合對應于這個(gè)用戶(hù)   
  68.         List dbAuths = authoritiesByUsernameMapping.execute(user.getUsername());   
  69.   
  70.         addCustomAuthorities(user.getUsername(), dbAuths);   
  71.   
  72.         if (dbAuths.size() == 0) {   
  73.             throw new UsernameNotFoundException("User has no GrantedAuthority");   
  74.         }   
  75.         //這里根據得到的權限集合來(lái)配置返回的User對象供以后使用   
  76.         GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new GrantedAuthority[dbAuths.size()]);   
  77.   
  78.         String returnUsername = user.getUsername();   
  79.   
  80.         if (!usernameBasedPrimaryKey) {   
  81.             returnUsername = username;   
  82.         }   
  83.   
  84.         return new User(returnUsername, user.getPassword(), user.isEnabled(), truetruetrue, arrayAuths);   
  85.     }   
  86.   
  87.     public void setAuthoritiesByUsernameQuery(String queryString) {   
  88.         authoritiesByUsernameQuery = queryString;   
  89.     }   
  90.   
  91.     public void setRolePrefix(String rolePrefix) {   
  92.         this.rolePrefix = rolePrefix;   
  93.     }   
  94.   
  95.     public void setUsernameBasedPrimaryKey(boolean usernameBasedPrimaryKey) {   
  96.         this.usernameBasedPrimaryKey = usernameBasedPrimaryKey;   
  97.     }   
  98.   
  99.     public void setUsersByUsernameQuery(String usersByUsernameQueryString) {   
  100.         this.usersByUsernameQuery = usersByUsernameQueryString;   
  101.     }   
  102.   
  103.     //~ Inner Classes ==================================================================================================   
  104.   
  105.     /**  
  106.      * 這里是調用Spring JDBC的數據庫操作,具體可以參考對JDBC的分析,這個(gè)類(lèi)的作用是把數據庫查詢(xún)得到的記錄集合轉換為對象集合 - 一個(gè)很簡(jiǎn)單的O/R實(shí)現  
  107.      */  
  108.     protected class AuthoritiesByUsernameMapping extends MappingSqlQuery {   
  109.         protected AuthoritiesByUsernameMapping(DataSource ds) {   
  110.             super(ds, authoritiesByUsernameQuery);   
  111.             declareParameter(new SqlParameter(Types.VARCHAR));   
  112.             compile();   
  113.         }   
  114.   
  115.         protected Object mapRow(ResultSet rs, int rownum)   
  116.             throws SQLException {   
  117.             String roleName = rolePrefix + rs.getString(2);   
  118.             GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);   
  119.   
  120.             return authority;   
  121.         }   
  122.     }   
  123.   
  124.     /**  
  125.      * Query object to look up a user.  
  126.      */  
  127.     protected class UsersByUsernameMapping extends MappingSqlQuery {   
  128.         protected UsersByUsernameMapping(DataSource ds) {   
  129.             super(ds, usersByUsernameQuery);   
  130.             declareParameter(new SqlParameter(Types.VARCHAR));   
  131.             compile();   
  132.         }   
  133.   
  134.         protected Object mapRow(ResultSet rs, int rownum)   
  135.             throws SQLException {   
  136.             String username = rs.getString(1);   
  137.             String password = rs.getString(2);   
  138.             boolean enabled = rs.getBoolean(3);   
  139.             UserDetails user = new User(username, password, enabled, truetruetrue,   
  140.                     new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")});   
  141.   
  142.             return user;   
  143.         }   
  144.     }   
  145. }  
public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService {//~ Static fields/initializers =====================================================================================//這里是預定義好的對查詢(xún)語(yǔ)句,對應于默認的數據庫表結構,也可以自己定義查詢(xún)語(yǔ)句對應特定的用戶(hù)數據庫驗證表的設計public static final String DEF_USERS_BY_USERNAME_QUERY ="SELECT username,password,enabled FROM users WHERE username = ?";public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY ="SELECT username,authority FROM authorities WHERE username = ?";//~ Instance fields ================================================================================================//這里使用Spring JDBC來(lái)進(jìn)行數據庫操作protected MappingSqlQuery authoritiesByUsernameMapping;protected MappingSqlQuery usersByUsernameMapping;private String authoritiesByUsernameQuery;private String rolePrefix = "";private String usersByUsernameQuery;private boolean usernameBasedPrimaryKey = true;//~ Constructors ===================================================================================================//在初始化函數中把查詢(xún)語(yǔ)句設置為預定義的SQL語(yǔ)句public JdbcDaoImpl() {usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY;authoritiesByUsernameQuery = DEF_AUTHORITIES_BY_USERNAME_QUERY;}//~ Methods ========================================================================================================protected void addCustomAuthorities(String username, List authorities) {}public String getAuthoritiesByUsernameQuery() {return authoritiesByUsernameQuery;}public String getRolePrefix() {return rolePrefix;}public String getUsersByUsernameQuery() {return usersByUsernameQuery;}protected void initDao() throws ApplicationContextException {initMappingSqlQueries();}/*** Extension point to allow other MappingSqlQuery objects to be substituted in a subclass*/protected void initMappingSqlQueries() {this.usersByUsernameMapping = new UsersByUsernameMapping(getDataSource());this.authoritiesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource());}public boolean isUsernameBasedPrimaryKey() {return usernameBasedPrimaryKey;}//這里是取得數據庫用戶(hù)信息的具體過(guò)程public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException, DataAccessException {//根據用戶(hù)名在用戶(hù)表中得到用戶(hù)信息,包括用戶(hù)名,密碼和用戶(hù)是否有效的信息List users = usersByUsernameMapping.execute(username);if (users.size() == 0) {throw new UsernameNotFoundException("User not found");}//取集合中的第一個(gè)作為有效的用戶(hù)對象UserDetails user = (UserDetails) users.get(0); // contains no GrantedAuthority[]//這里在權限表中去取得用戶(hù)的權限信息,同樣的返回一個(gè)權限集合對應于這個(gè)用戶(hù)List dbAuths = authoritiesByUsernameMapping.execute(user.getUsername());addCustomAuthorities(user.getUsername(), dbAuths);if (dbAuths.size() == 0) {throw new UsernameNotFoundException("User has no GrantedAuthority");}//這里根據得到的權限集合來(lái)配置返回的User對象供以后使用GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new GrantedAuthority[dbAuths.size()]);String returnUsername = user.getUsername();if (!usernameBasedPrimaryKey) {returnUsername = username;}return new User(returnUsername, user.getPassword(), user.isEnabled(), true, true, true, arrayAuths);}public void setAuthoritiesByUsernameQuery(String queryString) {authoritiesByUsernameQuery = queryString;}public void setRolePrefix(String rolePrefix) {this.rolePrefix = rolePrefix;}public void setUsernameBasedPrimaryKey(boolean usernameBasedPrimaryKey) {this.usernameBasedPrimaryKey = usernameBasedPrimaryKey;}public void setUsersByUsernameQuery(String usersByUsernameQueryString) {this.usersByUsernameQuery = usersByUsernameQueryString;}//~ Inner Classes ==================================================================================================/*** 這里是調用Spring JDBC的數據庫操作,具體可以參考對JDBC的分析,這個(gè)類(lèi)的作用是把數據庫查詢(xún)得到的記錄集合轉換為對象集合 - 一個(gè)很簡(jiǎn)單的O/R實(shí)現*/protected class AuthoritiesByUsernameMapping extends MappingSqlQuery {protected AuthoritiesByUsernameMapping(DataSource ds) {super(ds, authoritiesByUsernameQuery);declareParameter(new SqlParameter(Types.VARCHAR));compile();}protected Object mapRow(ResultSet rs, int rownum)throws SQLException {String roleName = rolePrefix + rs.getString(2);GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);return authority;}}/*** Query object to look up a user.*/protected class UsersByUsernameMapping extends MappingSqlQuery {protected UsersByUsernameMapping(DataSource ds) {super(ds, usersByUsernameQuery);declareParameter(new SqlParameter(Types.VARCHAR));compile();}protected Object mapRow(ResultSet rs, int rownum)throws SQLException {String username = rs.getString(1);String password = rs.getString(2);boolean enabled = rs.getBoolean(3);UserDetails user = new User(username, password, enabled, true, true, true,new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")});return user;}}}


從數據庫中得到用戶(hù)信息后,就是一個(gè)比對用戶(hù)輸入的信息和這個(gè)數據庫用戶(hù)信息的比對過(guò)程,這個(gè)比對過(guò)程在DaoAuthenticationProvider:

Java代碼
  1. //這個(gè)UserDetail是從數據庫中查詢(xún)到的,這個(gè)authentication是從用戶(hù)輸入中得到的   
  2.     protected void additionalAuthenticationChecks(UserDetails userDetails,   
  3.         UsernamePasswordAuthenticationToken authentication)   
  4.         throws AuthenticationException {   
  5.         Object salt = null;   
  6.   
  7.         if (this.saltSource != null) {   
  8.             salt = this.saltSource.getSalt(userDetails);   
  9.         }   
  10.         //如果用戶(hù)沒(méi)有輸入密碼,直接拋出異常   
  11.         if (authentication.getCredentials() == null) {   
  12.             throw new BadCredentialsException(messages.getMessage(   
  13.                     "AbstractUserDetailsAuthenticationProvider.badCredentials""Bad credentials"),   
  14.                     includeDetailsObject ? userDetails : null);   
  15.         }   
  16.         //這里取得用戶(hù)輸入的密碼   
  17.         String presentedPassword = authentication.getCredentials() == null ? "" : authentication.getCredentials().toString();   
  18.         //這里判斷用戶(hù)輸入的密碼是不是和數據庫里的密碼相同,這里可以使用passwordEncoder來(lái)對數據庫里的密碼加解密   
  19.         // 如果不相同,拋出異常,如果相同則鑒權成功   
  20.         if (!passwordEncoder.isPasswordValid(   
  21.                 userDetails.getPassword(), presentedPassword, salt)) {   
  22.             throw new BadCredentialsException(messages.getMessage(   
  23.                     "AbstractUserDetailsAuthenticationProvider.badCredentials""Bad credentials"),   
  24.                     includeDetailsObject ? userDetails : null);   
  25.         }   
  26.     }  
//這個(gè)UserDetail是從數據庫中查詢(xún)到的,這個(gè)authentication是從用戶(hù)輸入中得到的protected void additionalAuthenticationChecks(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication)throws AuthenticationException {Object salt = null;if (this.saltSource != null) {salt = this.saltSource.getSalt(userDetails);}//如果用戶(hù)沒(méi)有輸入密碼,直接拋出異常if (authentication.getCredentials() == null) {throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),includeDetailsObject ? userDetails : null);}//這里取得用戶(hù)輸入的密碼String presentedPassword = authentication.getCredentials() == null ? "" : authentication.getCredentials().toString();//這里判斷用戶(hù)輸入的密碼是不是和數據庫里的密碼相同,這里可以使用passwordEncoder來(lái)對數據庫里的密碼加解密// 如果不相同,拋出異常,如果相同則鑒權成功if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"),includeDetailsObject ? userDetails : null);}}


上面分析了整個(gè)Acegi進(jìn)行驗證的過(guò)程,從AuthenticationProcessingFilter中攔截Http請求得到用戶(hù)輸入的用戶(hù)名和密碼,這些用戶(hù)輸入的驗證信息會(huì )被放到Authentication對象中持有并傳遞給AuthenticatioManager來(lái)對比在服務(wù)端的用戶(hù)信息來(lái)完成整個(gè)鑒權。這個(gè)鑒權完成以后會(huì )把有效的用戶(hù)信息放在一個(gè)Authentication中供以后的授權模塊使用。在具體的鑒權過(guò)程中,使用了我們配置好的各種Provider以及對應的UserDetailService和Encoder類(lèi)來(lái)完成相應的獲取服務(wù)器端用戶(hù)數據以及與用戶(hù)輸入的驗證信息的比對工作。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
源碼分析shiro認證授權流程
決定放棄 JWT 了!
使用JWT和Spring Security保護REST API
項目之通過(guò)Spring Security獲取當前登錄的用戶(hù)的信息(6)
在Spring Boot中整合Spring Security并自定義驗證代碼
使用Redis+AOP優(yōu)化權限管理功能,這波操作賊爽!
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久