Just Code

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            1 隨筆 :: 0 文章 :: 0 評(píng)論 :: 0 Trackbacks

           在Acegi中是由認(rèn)證管理器確定用戶身份。一個(gè)認(rèn)證管理器由借口AuthenticationManager實(shí)現(xiàn)。

          public ? interface ?AuthenticationManager? {
          ????
          // ~Methods?==================================================================?
          ???
          ???
          /**
          ?????*?嘗試驗(yàn)證用戶身份,如果驗(yàn)證成功,將返回一個(gè)含授權(quán)的完整的Authentication對(duì)象。
          ?????*?一個(gè)AuthenticationManager必須按照下面的規(guī)則處理異常:
          ?????*?如果賬號(hào)是不被允許的必須拋出DisabledException,AuthenticationManager能檢測(cè)到這個(gè)狀態(tài)。
          ?????*?如果賬號(hào)已經(jīng)被鎖定必須拋出LockedException,AuthenticationManager能夠檢測(cè)被鎖定的賬號(hào)。
          ?????*?如果取到的是非法的信任狀(credential?)必須拋出BadCredentialsException。同時(shí)上述的2種異常也是可選
          ?????*?的,AuthenticationManager必須總是檢測(cè)信任狀(credential)。
          ?????*?異常必須被檢測(cè),如果有上述的異常出現(xiàn)須拋出異常。
          ?????*?如果一個(gè)賬號(hào)是不被允許的或是被鎖定的,認(rèn)證請(qǐng)求會(huì)立即被拒絕,信任狀的檢測(cè)不會(huì)發(fā)生。
          ?????*?這防止了對(duì)不被允許賬號(hào)和被鎖定的賬號(hào)的信任狀檢測(cè)。
          ?????*
          ?????*?
          @param ?authentication?the?authentication?request?object
          ?????*
          ?????*?
          @return ?a?fully?authenticated?object?including?credentials
          ?????*
          ?????*?
          @throws ?AuthenticationException?if?authentication?fails
          ????
          */

          ????
          public ?Authentication?authenticate(Authentication?authentication)
          ????????
          throws ?AuthenticationException;
          }

           Authentication?繼承了java.security.Principal,Principal實(shí)現(xiàn)了簡(jiǎn)單的主體(Principal)定義。

          public ? interface ?Principal? {

          ????
          public ? boolean ?equals(Object?another);

          ????
          public ?String?toString();

          ????
          public ? int ?hashCode();

          ???
          /**
          ?????*?返回主體的名字
          ?????*
          ?????*?
          @return ?the?name?of?this?principal.
          ????
          */

          ????
          public ?String?getName();
          }

          ?

          public ? interface ?Authentication? extends ?Principal,?Serializable? {
          ????
          // ?~Methods?==================================================================

          ?
          /**
          ?????*?通過(guò)AuthenticationManager設(shè)置Principal的授權(quán)信息。
          ?????*?注意:當(dāng)Class狀態(tài)為valid時(shí),除非Value已經(jīng)被可信任的AuthenticationManager設(shè)置t過(guò),否則對(duì)Class
          ?????*?不起作用。(此句存疑?Note?that?classes?should?not?rely?on?this?value?as?being?valid?unless?it?has?
          ?????*?been?set?by?AuthenticationManager)
          ?????*?Authentication的實(shí)現(xiàn)類需要確保修改返回的數(shù)足不會(huì)影響Authentication?Object的狀態(tài)。(比如返回一個(gè)
          ?????*?數(shù)組的copy)。
          ?????*?
          ?????*?
          @return ?the?authorities?granted?to?the?principal,?or?null?if?authentication?has?not?been?completed
          ????
          */

          ????
          public ?GrantedAuthority[]?getAuthorities();

          ??
          /**
          ?????*?信任狀證明Principal的身份是合法的。它經(jīng)常是密碼,但是也可以是任何與AuthenticationManager
          ?????*?相關(guān)的東西。
          ?????*
          ?????*?
          @return ?the?credentials?that?prove?the?identity?of?the?Principal
          ????
          */

          ????
          public ?Object?getCredentials();

          ??
          /**
          ?????*?儲(chǔ)存認(rèn)證請(qǐng)求的額外信息。有可能是IP地址,證件號(hào)碼等。
          ?????*
          ?????*?
          @return ?additional?details?about?the?authentication?request,?or??null?if?not?used
          ????
          */

          ????
          public ?Object?getDetails();

          ??
          /**
          ?????*?返回一個(gè)已經(jīng)通過(guò)驗(yàn)證的Principal(這通常是一個(gè)用戶名)。
          ?????*
          ?????*?
          @return ?the?Principal?being?authenticated
          ????
          */

          ????
          public ?Object?getPrincipal();

          ??
          /**
          ???? * AbstractSecurityInterceptor將認(rèn)證令牌交給AuthenticationManager。如果認(rèn)證成功AuthenticaionManager
          ???? * 會(huì)返回一個(gè)不變的認(rèn)證令牌(返回true)。
          ???? * 返回"true"會(huì)改善性能,因?yàn)椴辉偈敲恳粋€(gè)請(qǐng)求都需要調(diào)用AuthenticationManager。
          ???? * 由于安全上的考慮,實(shí)現(xiàn)這個(gè)接口返回true的時(shí)候需要十分的小心。除非他們不再變化或者有什么途徑
          ???? * 確保屬性在最初的初始化后不再變化。
          ?????*
          ?????*?
          @return ?true?if?the?token?has?been?authenticated?and?the? AbstractSecurityInterceptor?
          ?????*????????does?not?need?to?represent?the?token?for?re-authentication?to?the AuthenticationManager
          ????
          */

          ????
          public ? boolean ?isAuthenticated();

          ??
          /**
          ???? * 詳情參閱isAuthenticate()方法
          ???? * 參數(shù)為true的情況下,如果某個(gè)實(shí)現(xiàn)希望拒絕一個(gè)調(diào)用,那么將拋出一個(gè)IllegalArgumentException異常。

          ?????*
          ?????*?
          @param ?isAuthenticated?true?if?the?token?should?be?trusted?(which?may?result?in?an?exception)?or
          ?????*????????false?if?the?token?should?not?be?trusted
          ?????*
          ?????*?
          @throws ?IllegalArgumentException?if?an?attempt?to?make?the?authentication?token?trusted?(by?
          ?????*????????passing?true?as?the?argument)?is?rejected?due?to?the?implementation?being?immutable?or
          ?????*????????implementing?its?own?alternative?approach?to isAuthenticated()}

          ????
          */

          ????
          public ? void ?setAuthenticated( boolean ?isAuthenticated)
          ????????
          throws ?IllegalArgumentException;
          }

           Acegi提供了一個(gè)能適應(yīng)大多數(shù)情況的ProviderManager,實(shí)現(xiàn)了AuthenticationManager。
            ProviderManager繼承抽象類AbstractAuthenticationManager:

          public ? abstract ? class ?AbstractAuthenticationManager? implements ?AuthenticationManager? {
          ????
          // ?~Methods?==================================================================?

          ?
          /**
          ?????*?實(shí)現(xiàn)通過(guò)調(diào)用抽象方法doAuthentication()進(jìn)行工作。
          ?????*?如果doAuthentication()方法拋出AuthenticationException異常,驗(yàn)證失敗。
          ?????*
          ?????*?
          @param ?authRequest?the?authentication?request?object
          ?????*
          ?????*?
          @return ?a?fully?authenticated?object?including?credentials
          ?????*
          ?????*?
          @throws ?AuthenticationException?if?authentication?fails
          ????
          */

          ????
          public ? final ?Authentication?authenticate(Authentication?authRequest)
          ????????
          throws ?AuthenticationException? {
          ????????
          try ? {
          ????????????Authentication?authResult?
          = ?doAuthentication(authRequest);
          ????????????copyDetails(authRequest,?authResult);

          ????????????
          return ?authResult;
          ????????}
          ? catch ?(AuthenticationException?e)? {
          ????????????e.setAuthentication(authRequest);
          ????????????
          throw ?e;
          ????????}

          ????}


          ?
          /**
          ?????*?在目標(biāo)Authentication的detail沒(méi)有被設(shè)置的情況下從源Authentication復(fù)制detail信息。
          ?????*
          ?????*?
          @param ?source?source?authentication
          ?????*?
          @param ?dest?the?destination?authentication?object
          ????
          */

          ????
          private ? void ?copyDetails(Authentication?source,?Authentication?dest)? {
          ????????
          if ?((dest? instanceof ?AbstractAuthenticationToken)? && ?(dest.getDetails()? == ? null ))? {
          ????????????AbstractAuthenticationToken?token?
          = ?(AbstractAuthenticationToken)?dest;

          ????????????token.setDetails(source.getDetails());
          ????????}

          ????}


          ?
          /**
          ?????*?具體的實(shí)現(xiàn)通過(guò)覆寫此方法提供認(rèn)證服務(wù),此方法的約束詳見(jiàn)AuthenticationManager的authenticate()方法
          ?????*
          ?????*?
          @param ?authentication?the?authentication?request?object
          ?????*
          ?????*?
          @return ?a?fully?authenticated?object?including?credentials
          ?????*
          ?????*?
          @throws ?AuthenticationException?if?authentication?fails
          ????
          */

          ????
          protected ? abstract ?Authentication?doAuthentication(Authentication?authentication)
          ????????
          throws ?AuthenticationException;
          }

          ?

          /**
          ??? ?*?認(rèn)證請(qǐng)求重復(fù)的通過(guò)一組AuthenticationProviders容器進(jìn)行認(rèn)證。
          ??? ?*?可以通過(guò)配置ConcurrentSessionController來(lái)限制單個(gè)用戶的session數(shù)目。
          ??? ?*?AuthenticationProvider試圖得到一個(gè)非空的響應(yīng)。非空的響應(yīng)表明Provider已經(jīng)對(duì)認(rèn)證請(qǐng)求作出決議
          ??? ?*?而不需要嘗試其他的Provider。
          ???? *?如果provider拋出一個(gè)AuthenticationException,這個(gè)異常將會(huì)被保留直到后續(xù)的providers都被嘗試為止。
          ???? *?如果認(rèn)真請(qǐng)求在后續(xù)的Providers中被認(rèn)證成功,早先的認(rèn)證異常會(huì)被忽略而成功的認(rèn)證信息將被使用。
          ???? *?如果后續(xù)的Providers沒(méi)有作出一個(gè)非空的響應(yīng)或一個(gè)新的AuthenticationException,那么最后接收到的
          ???? *?AuthenticationException將會(huì)被使用。
          ???? *?如果沒(méi)有一個(gè)Provider返回一個(gè)非空的響應(yīng)或是表明能運(yùn)行一個(gè)Authentication,那么ProviderManager將會(huì)
          ???? *?拋出一個(gè)ProviderNotFoundException異常。
          ???? *?如果一個(gè)有效的Authentication被AuthenticationProvider返回,ProviderManager將會(huì)發(fā)布一個(gè)org
          ???? *?.acegisecurity.event.authentication.AuthenticationSuccessEvent。
          ???? *?如果發(fā)現(xiàn)AuthenticationException,最后的AuthenticationException會(huì)發(fā)布一個(gè)適當(dāng)?shù)氖∈录?br />???? *?默認(rèn)的ProviderManager將異常和事件對(duì)應(yīng)起來(lái),我們可以通過(guò)定一個(gè)新的exceptionMappings?Properties
          ???? *?來(lái)調(diào)整對(duì)應(yīng)關(guān)系。
          ???? *?在properties中,key表現(xiàn)的是異常的類名的完整路徑,value表現(xiàn)的是AbstractAuthenticationFailureEvent的
          ???? *?子類,提供子類的構(gòu)造。
          ???? *
          ??? ?*?
          @see ?ConcurrentSessionController
          ?
          ??? */

          public ? class ?ProviderManager? extends ?AbstractAuthenticationManager? implements ?InitializingBean,
          ????ApplicationEventPublisherAware,?MessageSourceAware?
          {
          ????
          // ~?Static?fields/initializers?=======================================================?

          ????
          private ? static ? final ?Log?logger? = ?LogFactory.getLog(ProviderManager. class );

          ????
          // ~?Instance?fields?=============================================================?

          ????
          private ?ApplicationEventPublisher?applicationEventPublisher;
          ????
          private ?ConcurrentSessionController?sessionController? = ? new ?NullConcurrentSessionController();
          ????
          private ?List?providers;
          ????
          protected ?MessageSourceAccessor?messages? = ?AcegiMessageSource.getAccessor();
          ????
          private ?Properties?exceptionMappings;

          ????
          // ~?Methods?==================================================================?

          ????
          public ? void ?afterPropertiesSet()? throws ?Exception? {
          ????????checkIfValidList(
          this .providers);
          ????????Assert.notNull(
          this .messages,? " A?message?source?must?be?set " );

          ????????
          if ?(exceptionMappings? == ? null )? {
          ????????????exceptionMappings?
          = ? new ?Properties();
          ????????????exceptionMappings.put(AccountExpiredException.
          class .getName(),
          ????????????????AuthenticationFailureExpiredEvent.
          class .getName());
          ????????????exceptionMappings.put(AuthenticationServiceException.
          class .getName(),
          ????????????????AuthenticationFailureServiceExceptionEvent.
          class .getName());
          ????????????exceptionMappings.put(LockedException.
          class .getName(),?AuthenticationFailureLockedEvent. class .getName());
          ????????????exceptionMappings.put(CredentialsExpiredException.
          class .getName(),
          ????????????????AuthenticationFailureCredentialsExpiredEvent.
          class .getName());
          ????????????exceptionMappings.put(DisabledException.
          class .getName(),?AuthenticationFailureDisabledEvent. class .getName());
          ????????????exceptionMappings.put(BadCredentialsException.
          class .getName(),
          ????????????????AuthenticationFailureBadCredentialsEvent.
          class .getName());
          ????????????exceptionMappings.put(UsernameNotFoundException.
          class .getName(),
          ????????????????AuthenticationFailureBadCredentialsEvent.
          class .getName());
          ????????????exceptionMappings.put(ConcurrentLoginException.
          class .getName(),
          ????????????????AuthenticationFailureConcurrentLoginEvent.
          class .getName());
          ????????????exceptionMappings.put(ProviderNotFoundException.
          class .getName(),
          ????????????????AuthenticationFailureProviderNotFoundEvent.
          class .getName());
          ????????????exceptionMappings.put(ProxyUntrustedException.
          class .getName(),
          ????????????????AuthenticationFailureProxyUntrustedEvent.
          class .getName());
          ????????????doAddExtraDefaultExceptionMappings(exceptionMappings);
          ????????}

          ????}


          ????
          private ? void ?checkIfValidList(List?listToCheck)? {
          ????????
          if ?((listToCheck? == ? null )? || ?(listToCheck.size()? == ? 0 ))? {
          ????????????
          throw ? new ?IllegalArgumentException( " A?list?of?AuthenticationManagers?is?required " );
          ????????}

          ????}


          ?
          /**
          ?????*?如果在啟動(dòng)期間沒(méi)有exception被IoC容器注入,這個(gè)方法提供額外的異常對(duì)應(yīng)。
          ?????*
          ?????*?
          @param ?exceptionMappings?the?properties?object,?which?already?has?entries?in?it
          ????
          */

          ????
          protected ? void ?doAddExtraDefaultExceptionMappings(Properties?exceptionMappings)? {}

          ?
          /**
          ?????*?嘗試認(rèn)證通過(guò)Authentication對(duì)象。
          ?????*?AuthenticationProviders組將會(huì)接連嘗試認(rèn)證對(duì)象,直到其中的一個(gè)通過(guò)這個(gè)Authentication對(duì)象。
          ?????*?如果多個(gè)AuthenticationProvider通過(guò)了Authentication對(duì)象,那么只有第一個(gè)AuthenticationProvider
          ?????*?產(chǎn)生結(jié)果,后續(xù)的AuthenticationProvider將不會(huì)被嘗試。
          ?????*
          ?????*?
          @param ?authentication?the?authentication?request?object.
          ?????*
          ?????*?
          @return ?a?fully?authenticated?object?including?credentials.
          ?????*
          ?????*?
          @throws ?AuthenticationException?if?authentication?fails.
          ????
          */

          ????
          public ?Authentication?doAuthentication(Authentication?authentication)
          ????????
          throws ?AuthenticationException? {
          ????????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());

          ????????????????Authentication?result?
          = ? null ;

          ????????????????
          try ? {
          ????????????????????result?
          = ?provider.authenticate(authentication);
          ????????????????????sessionController.checkAuthenticationAllowed(result);
          ????????????????}
          ? catch ?(AuthenticationException?ae)? {
          ????????????????????lastException?
          = ?ae;
          ????????????????????result?
          = ? null ;
          ????????????????}


          ????????????????
          if ?(result? != ? null )? {
          ????????????????????sessionController.registerSuccessfulAuthentication(result);
          ????????????????????applicationEventPublisher.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} " ));
          ????????}


          ????????
          // ?Publish?the?event
          ????????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 )? {
          ????????????applicationEventPublisher.publishEvent(event);
          ????????}
          ? else ? {
          ????????????
          if ?(logger.isDebugEnabled())? {
          ????????????????logger.debug(
          " No?event?was?found?for?the?exception? " ? + ?lastException.getClass().getName());
          ????????????}

          ????????}


          ????????
          // ?Throw?the?exception
          ???????? throw ?lastException;
          ????}


          ????
          public ?List?getProviders()? {
          ????????
          return ? this .providers;
          ????}


          ?
          /**
          ?????*?返回設(shè)定的ConcurrentSessionController對(duì)象,如果對(duì)象沒(méi)有被設(shè)置則返回一個(gè)
          ?????*?NullConcurrentSessionController(默認(rèn)初始化的對(duì)象)
          ?????*
          ?????*?
          @return ?ConcurrentSessionController?instance
          ????
          */

          ????
          public ?ConcurrentSessionController?getSessionController()? {
          ????????
          return ?sessionController;
          ????}


          ????
          public ? void ?setApplicationEventPublisher(ApplicationEventPublisher?applicationEventPublisher)? {
          ????????
          this .applicationEventPublisher? = ?applicationEventPublisher;
          ????}


          ????
          public ? void ?setMessageSource(MessageSource?messageSource)? {
          ????????
          this .messages? = ? new ?MessageSourceAccessor(messageSource);
          ????}


          ?
          /**
          ?????*?設(shè)置AuthenticationProvider對(duì)象
          ?????*?
          ?????*?
          @param ?newList
          ?????*
          ?????*?
          @throws ?IllegalArgumentException?DOCUMENT?ME!
          ????
          */

          ????
          public ? void ?setProviders(List?newList)? {
          ????????checkIfValidList(newList);

          ????????Iterator?iter?
          = ?newList.iterator();

          ????????
          while ?(iter.hasNext())? {
          ????????????Object?currentObject?
          = ? null ;

          ????????????
          try ? {
          ????????????????currentObject?
          = ?iter.next();

          ????????????????AuthenticationProvider?attemptToCast?
          = ?(AuthenticationProvider)?currentObject;
          ????????????}
          ? catch ?(ClassCastException?cce)? {
          ????????????????
          throw ? new ?IllegalArgumentException( " AuthenticationProvider? " ? + ?currentObject.getClass().getName()
          ????????????????????
          + ? " ?must?implement?AuthenticationProvider " );
          ????????????}

          ????????}


          ????????
          this .providers? = ?newList;
          ????}


          ?
          /**
          ?????*?設(shè)置ConcurrentSessionController來(lái)限制用戶的session數(shù)量。
          ?????*?默認(rèn)設(shè)置為NullConcurrentSessionController
          ?????*
          ?????*?
          @param ?sessionController?ConcurrentSessionController
          ????
          */

          ????
          public ? void ?setSessionController(ConcurrentSessionController?sessionController)? {
          ????????
          this .sessionController? = ?sessionController;
          ????}

          }



            AuthenticationManager不依靠自己實(shí)現(xiàn)身份驗(yàn)證,而是通過(guò)Iterator逐個(gè)遍歷AuthenticationProvider的子類集合(如果使用Spring的話子類類型由配置文件注入),直到某個(gè)Provider成功驗(yàn)證Authentication。

            Acegi提供的Provider實(shí)現(xiàn)包括:
            AuthByAdapterProvider、CasAuthenticationProvider、DaoAuthenticationProvider、JaasAuthenticationProvider、PasswordDaoAuthenticationProvider、RemoteAuthenticationProvider、RunAsImplAuthenticationProvider、TestingAuthenticationProvider。

            下面只分析DaoAuthenticationProvider的相關(guān)類,按照AuthenticationProvider-->AbstractUserDetailsAuthenticationProvider-->DaoAuthenticationProvider的順序展開。

          /**
          ???? *?這個(gè)類處理一個(gè)Authenticaon類的具體實(shí)現(xiàn)
          ?
          ??? */

          public ? interface ?AuthenticationProvider? {
          ????
          // ~?Methods?==================================================================

          ?
          /**
          ?????*?和AuthenticationManager的同名方法實(shí)現(xiàn)同樣的功能,詳見(jiàn)AuthenticationManager
          ?????*
          ?????*?
          @param ?authentication?the?authentication?request?object.
          ?????*
          ?????*?
          @return ?a?fully?authenticated?object?including?credentials.?May?return?null?if?the
          ?????*?????????AuthenticationProvider?is?unable?to?support?authentication?of?the?passed
          ?????*?????????Authentication?object.?In?such?a?case,?the?next?AuthenticationProvider?that
          ?????*?????????supports?the?presented?Authentication?class?will?be?tried.
          ?????*
          ?????*?
          @throws ?AuthenticationException?if?authentication?fails.
          ????
          */

          ????
          public ?Authentication?authenticate(Authentication?authentication)
          ????????
          throws ?AuthenticationException;

          ??
          /**
          ?????*?如果這個(gè)AuthenticationProvider支持通過(guò)Authentication對(duì)象,則返回True。
          ?????*?返回True并不意味著AuthenticationProvider能認(rèn)證當(dāng)前的Authenctication。
          ?????*?他只是簡(jiǎn)單的聲明支持通過(guò)認(rèn)證。AuthenticationProvider仍舊能夠通過(guò)authenticate()方法返回null,
          ?????*?使其它的Provider能夠嘗試認(rèn)證這個(gè)Authentication。(存疑)
          ?????*?選擇哪一個(gè)AuthenticatonProvider履行鑒定是由ProviderManager在運(yùn)行時(shí)管理的。
          ?????*
          ?????*?
          @param ?authentication?DOCUMENT?ME!
          ?????*
          ?????*?
          @return ?true?if?the?implementation?can?more?closely?evaluate?the?Authentication?class
          ?????*?????????presented
          ????
          */

          ????
          public ? boolean ?supports(Class?authentication);
          }


          /**
          ???? *?Authentication的基類,允許子類覆寫他的方法以及使用UserDetails對(duì)象
          ???? *?這個(gè)類被設(shè)計(jì)用來(lái)對(duì)UsernamePasswordAuthenticationToken的認(rèn)證請(qǐng)求作出相應(yīng)。
          ???? *?在成功驗(yàn)證的基礎(chǔ)上,UsernamePasswordAuthenticationToken會(huì)被構(gòu)造同時(shí)返回給調(diào)用者。
          ???? *?令牌可以是用戶名的String形式也可以是由認(rèn)證庫(kù)中取得的UserDetails對(duì)象。
          ???? *?如果適配器容器正在被使用,而又期望得到用戶名的情況下,使用String類型是適當(dāng)?shù)摹?
          ???? *?如果需要訪問(wèn)額外的用戶信息,例如電子郵件地址、用戶導(dǎo)向的名字等等,那么使用UserDetail是恰
          ???? *?當(dāng)?shù)摹serDetail提供了更靈活的訪問(wèn),所以通常情況下我們返回一個(gè)UserDetail而并不推薦使用適配
          ???? *?器容器。如果想要覆寫默認(rèn)的方式,將setForcePrincipalAsString置true即可。
          ???? *?UserDetails通過(guò)緩存放置在UserCache中。這確保了如果后續(xù)的請(qǐng)求在用戶名相同的情況下可以不通過(guò)
          ???? *?UserDetailsService查詢。需要指出的是:如果用戶無(wú)意間輸入了錯(cuò)誤的密碼,UserDetailService去查詢
          ??? ?*?出用戶最后一次輸入的密碼并與之比較。
          ?
          ??? */

          public ? abstract ? class ?AbstractUserDetailsAuthenticationProvider? implements ?AuthenticationProvider,?InitializingBean,
          ????MessageSourceAware?
          {
          ????
          // ~?Instance?fields?=============================================================

          ????
          protected ?MessageSourceAccessor?messages? = ?AcegiMessageSource.getAccessor();
          ????
          private ?UserCache?userCache? = ? new ?NullUserCache();
          ????
          private ? boolean ?forcePrincipalAsString? = ? false ;
          ????
          protected ? boolean ?hideUserNotFoundExceptions? = ? true ;

          ????
          // ~?Methods?==================================================================

          ?
          /**
          ?????*?允許子類對(duì)認(rèn)證請(qǐng)求返回或緩存的UserDetails提供額外的校驗(yàn)。
          ?????*?通常情況下子類至少會(huì)對(duì)Authentication的getCredentials()方法和UserDetails的getPassword()方法進(jìn)行
          ?????*?比照。
          ?????*?如果定制的邏輯需要比照額外的UserDetail屬性或者UsernamePasswordAuthenticationToken,也應(yīng)該在
          ?????*?這個(gè)方法中定制。
          ?????*
          ?????*?
          @param ?userDetails?as?retrieved?from?the??#retrieveUser(String,?
          ?????*????????UsernamePasswordAuthenticationToken)}?or UserCache
          ?????*?
          @param ?authentication?the?current?request?that?needs?to?be?authenticated
          ?????*
          ?????*?
          @throws ?AuthenticationException?AuthenticationException?if?the?credentials?could?not?be?validated?
          ?????*????????(generally?a ?BadCredentialsException?an?AuthenticationServiceException)
          ????
          */

          ????
          protected ? abstract ? void ?additionalAuthenticationChecks(UserDetails?userDetails,
          ????????UsernamePasswordAuthenticationToken?authentication)
          ????????
          throws ?AuthenticationException;

          ????
          public ? final ? void ?afterPropertiesSet()? throws ?Exception? {
          ????????Assert.notNull(
          this .userCache,? " A?user?cache?must?be?set " );
          ????????Assert.notNull(
          this .messages,? " A?message?source?must?be?set " );
          ????????doAfterPropertiesSet();
          ????}


          ????
          public ?Authentication?authenticate(Authentication?authentication)
          ????????
          throws ?AuthenticationException? {
          ????????Assert.isInstanceOf(UsernamePasswordAuthenticationToken.
          class ,?authentication,
          ????????????messages.getMessage(
          " AbstractUserDetailsAuthenticationProvider.onlySupports " ,
          ????????????????
          " Only?UsernamePasswordAuthenticationToken?is?supported " ));

          ????????
          // ?Determine?username
          ????????String?username? = ?(authentication.getPrincipal()? == ? null )? ? ? " NONE_PROVIDED " ?:?authentication.getName();

          ????????
          boolean ?cacheWasUsed? = ? true ;
          ????????UserDetails?user?
          = ? this .userCache.getUserFromCache(username);

          ????????
          if ?(user? == ? null )? {
          ????????????cacheWasUsed?
          = ? false ;

          ????????????
          try ? {
          ????????????????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?credentials
          ???????? try ? {
          ????????????additionalAuthenticationChecks(user,?(UsernamePasswordAuthenticationToken)?authentication);
          ????????}
          ? catch ?(AuthenticationException?exception)? {
          ????????????
          // ?There?was?a?problem,?so?try?again?after?checking?we're?using?latest?data
          ????????????cacheWasUsed? = ? false ;
          ????????????user?
          = ?retrieveUser(username,?(UsernamePasswordAuthenticationToken)?authentication);
          ????????????additionalAuthenticationChecks(user,?(UsernamePasswordAuthenticationToken)?authentication);
          ????????}


          ????????
          if ?( ! user.isCredentialsNonExpired())? {
          ????????????
          throw ? new ?CredentialsExpiredException(messages.getMessage(
          ????????????????????
          " AbstractUserDetailsAuthenticationProvider.credentialsExpired " ,? " User?credentials?have?expired " ));
          ????????}


          ????????
          if ?( ! cacheWasUsed)? {
          ????????????
          this .userCache.putUserInCache(user);
          ????????}


          ????????Object?principalToReturn?
          = ?user;

          ????????
          if ?(forcePrincipalAsString)? {
          ????????????principalToReturn?
          = ?user.getUsername();
          ????????}


          ????????
          return ?createSuccessAuthentication(principalToReturn,?authentication,?user);
          ????}


          ?
          /**
          ?????*?構(gòu)建一個(gè)成功的Authentication對(duì)象。使用的保護(hù)類型所以子類可以覆寫本方法。
          ?????*?子類往往會(huì)將用戶提供的原始信任狀(未經(jīng)修改以及密碼未被解密)儲(chǔ)存在返回的Authentication
          ?????*?對(duì)象中。
          ?????*
          ?????*?
          @param ?principal?that?should?be?the?principal?in?the?returned?object?(defined?by?the?
          ?????*????????#isForcePrincipalAsString()?method)
          ?????*?
          @param ?authentication?that?was?presented?to?the?provider?for?validation
          ?????*?
          @param ?user?that?was?loaded?by?the?implementation
          ?????*
          ?????*?
          @return ?the?successful?authentication?token
          ????
          */

          ????
          protected ?Authentication?createSuccessAuthentication(Object?principal,?Authentication?authentication,
          ????????UserDetails?user)?
          {
          ????????
          // ?Ensure?we?return?the?original?credentials?the?user?supplied,
          ????????
          // ?so?subsequent?attempts?are?successful?even?with?encoded?passwords.
          ????????
          // ?Also?ensure?we?return?the?original?getDetails(),?so?that?future
          ????????
          // ?authentication?events?after?cache?expiry?contain?the?details
          ????????UsernamePasswordAuthenticationToken?result? = ? new ?UsernamePasswordAuthenticationToken(principal,
          ????????????????authentication.getCredentials(),?user.getAuthorities());
          ????????result.setDetails(authentication.getDetails());

          ????????
          return ?result;
          ????}


          ????
          protected ? void ?doAfterPropertiesSet()? throws ?Exception? {}

          ????
          public ?UserCache?getUserCache()? {
          ????????
          return ?userCache;
          ????}


          ????
          public ? boolean ?isForcePrincipalAsString()? {
          ????????
          return ?forcePrincipalAsString;
          ????}


          ????
          public ? boolean ?isHideUserNotFoundExceptions()? {
          ????????
          return ?hideUserNotFoundExceptions;
          ????}


          ?
          /**
          ?????*?允許子類由定義的實(shí)現(xiàn)位置獲取UserDetails,如果呈上的信任狀是非法的可以有選擇的拋出
          ?????*?AuthenticationExcepton異常(在有必要將用戶與資源綁定來(lái)獲取或產(chǎn)生UserDetail的情況下,這種處理
          ?????*?方式是十分有效的)。
          ?????*?子類沒(méi)有必要去實(shí)現(xiàn)任何的緩存,因?yàn)锳bstractUserDetailsAuthenticationProvider在默認(rèn)的情況下
          ?????*?將會(huì)緩存UserDetails。
          ?????*?UserDetails的緩存是十分復(fù)雜的,這意味著后續(xù)的認(rèn)證請(qǐng)求即使是從緩存中得到回復(fù)也仍舊要進(jìn)行
          ?????*?信任狀的校驗(yàn),即使信任狀的校驗(yàn)被基類在這個(gè)方法中用binding-based策略實(shí)現(xiàn)。
          ?????*?因此在子類禁用緩存(如果想要保證這個(gè)方法是唯一能夠進(jìn)行認(rèn)證的方法,沒(méi)有UserDetails將會(huì)
          ?????*?被緩存)或是確認(rèn)子類實(shí)現(xiàn)additionalAuthenticationChecks()方法來(lái)進(jìn)行被緩存的UserDetails
          ?????*?對(duì)象的信任狀和后續(xù)的認(rèn)證請(qǐng)求的比照的情況下它是十分重要的。
          ?????*?在大多數(shù)情況下子類不必要在這個(gè)方法中實(shí)現(xiàn)信任狀的校驗(yàn),取而代之的是在
          ?????*?additionalAuthenticationChecks()方法中實(shí)現(xiàn)。這樣代碼不用在2個(gè)方法中都實(shí)現(xiàn)信任狀的校驗(yàn)。
          ?????*
          ?????*?
          @param ?username?The?username?to?retrieve
          ?????*?
          @param ?authentication?The?authentication?request,?which?subclasses?may?need?to?perform?a?binding-based
          ?????*????????retrieval?of?the?UserDetails
          ?????*
          ?????*?
          @return ?the?user?information?(never?null?-?instead?an?exception?should?the?thrown)
          ?????*
          ?????*?
          @throws ?AuthenticationException?if?the?credentials?could?not?be?validated?(generally?a
          ?????*?????????BadCredentialsExceptionan?,an?AuthenticationServiceException?or
          ?????*?????????UsernameNotFoundException)
          ????
          */

          ????
          protected ? abstract ?UserDetails?retrieveUser(String?username,?UsernamePasswordAuthenticationToken?authentication)
          ????????
          throws ?AuthenticationException;

          ????
          public ? void ?setForcePrincipalAsString( boolean ?forcePrincipalAsString)? {
          ????????
          this .forcePrincipalAsString? = ?forcePrincipalAsString;
          ????}


          ?
          /**
          ?????*?在通常情況,如果用戶名沒(méi)有找到或是密碼錯(cuò)誤AbstractUserDetailsAuthenticationProvider將會(huì)
          ?????*?拋出一個(gè)BadCredentialsException異常。設(shè)置這個(gè)屬性為false的話,程序?qū)?huì)拋出
          ?????*?UsernameNotFoundException來(lái)取代BadCredentialsException異常。
          ?????*?需要注意的是:我們認(rèn)為這不如拋出BadCredentialsException來(lái)的可靠。
          ?????*
          ?????*?
          @param ?hideUserNotFoundExceptions?set?to?false?if?you?wish?UsernameNotFoundExceptions
          ?????*????????to?be?thrown?instead?of?the?non-specific?BadCredentialsException?(defaults?to
          ?????*????????true)
          ????
          */

          ????
          public ? void ?setHideUserNotFoundExceptions( boolean ?hideUserNotFoundExceptions)? {
          ????????
          this .hideUserNotFoundExceptions? = ?hideUserNotFoundExceptions;
          ????}


          ????
          public ? void ?setMessageSource(MessageSource?messageSource)? {
          ????????
          this .messages? = ? new ?MessageSourceAccessor(messageSource);
          ????}


          ????
          public ? void ?setUserCache(UserCache?userCache)? {
          ????????
          this .userCache? = ?userCache;
          ????}


          ????
          public ? boolean ?supports(Class?authentication)? {
          ????????
          return ?(UsernamePasswordAuthenticationToken. class .isAssignableFrom(authentication));
          ????}

          }

          ?

          /**
          ???? *?AuthenticationProvider的具體實(shí)現(xiàn),由UserDetailsService獲取用戶的詳細(xì)信息。
          ???? *
          ?
          ??? */

          public ? class ?DaoAuthenticationProvider? extends ?AbstractUserDetailsAuthenticationProvider? {
          ????
          // ~?Instance?fields?=============================================================

          ????
          private ?PasswordEncoder?passwordEncoder? = ? new ?PlaintextPasswordEncoder();
          ????
          private ?SaltSource?saltSource;
          ????
          private ?UserDetailsService?userDetailsService;

          ????
          // ~?Methods?==================================================================

          ????
          protected ? void ?additionalAuthenticationChecks(UserDetails?userDetails,
          ????????UsernamePasswordAuthenticationToken?authentication)
          ????????
          throws ?AuthenticationException? {
          ????????Object?salt?
          = ? null ;

          ????????
          if ?( this .saltSource? != ? null )? {
          ????????????salt?
          = ? this .saltSource.getSalt(userDetails);
          ????????}


          ????????
          if ?( ! passwordEncoder.isPasswordValid(userDetails.getPassword(),?authentication.getCredentials().toString(),?salt))? {
          ????????????
          throw ? new ?BadCredentialsException(messages.getMessage(
          ????????????????????
          " AbstractUserDetailsAuthenticationProvider.badCredentials " ,? " Bad?credentials " ),?userDetails);
          ????????}

          ????}


          ????
          protected ? void ?doAfterPropertiesSet()? throws ?Exception? {
          ????????Assert.notNull(
          this .userDetailsService,? " An?Authentication?DAO?must?be?set " );
          ????}


          ????
          public ?PasswordEncoder?getPasswordEncoder()? {
          ????????
          return ?passwordEncoder;
          ????}


          ????
          public ?SaltSource?getSaltSource()? {
          ????????
          return ?saltSource;
          ????}


          ????
          public ?UserDetailsService?getUserDetailsService()? {
          ????????
          return ?userDetailsService;
          ????}


          ????
          protected ? final ?UserDetails?retrieveUser(String?username,?UsernamePasswordAuthenticationToken?authentication)
          ????????
          throws ?AuthenticationException? {
          ????????UserDetails?loadedUser;

          ????????
          try ? {
          ????????????loadedUser?
          = ? this .getUserDetailsService().loadUserByUsername(username);
          ????????}
          ? catch ?(DataAccessException?repositoryProblem)? {
          ????????????
          throw ? new ?AuthenticationServiceException(repositoryProblem.getMessage(),?repositoryProblem);
          ????????}


          ????????
          if ?(loadedUser? == ? null )? {
          ????????????
          throw ? new ?AuthenticationServiceException(
          ????????????????
          " AuthenticationDao?returned?null,?which?is?an?interface?contract?violation " );
          ????????}


          ????????
          return ?loadedUser;
          ????}


          ?
          /**
          ?????*?設(shè)置密碼解密實(shí)例來(lái)進(jìn)行密碼的解密校驗(yàn)。如果沒(méi)有設(shè)置,將會(huì)使用PlaintextPosswordEncoder
          ?????*?作為默認(rèn)設(shè)置。
          ?????*
          ?????*?
          @param ?passwordEncoder?The?passwordEncoder?to?use
          ????
          */

          ????
          public ? void ?setPasswordEncoder(PasswordEncoder?passwordEncoder)? {
          ????????
          this .passwordEncoder? = ?passwordEncoder;
          ????}


          ?
          /**
          ?????*?(source?of?salts翻譯不來(lái))此方法解迷密碼的時(shí)候使用。
          ?????*?null是一個(gè)合法得值,這表明DaoAuthenticationProvider會(huì)把null返回給PasswordEncoder。
          ?????*
          ?????*?
          @param ?saltSource?to?use?when?attempting?to?decode?passwords?via?the?PasswordEncoder
          ????
          */

          ????
          public ? void ?setSaltSource(SaltSource?saltSource)? {
          ????????
          this .saltSource? = ?saltSource;
          ????}


          ????
          public ? void ?setUserDetailsService(UserDetailsService?authenticationDao)? {
          ????????
          this .userDetailsService? = ?authenticationDao;
          ????}

          }


          ?

          posted on 2006-07-25 16:13 dada 閱讀(2047) 評(píng)論(0)  編輯  收藏 所屬分類: Acegi

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 葫芦岛市| 连平县| 芦溪县| 新乡县| 驻马店市| 本溪市| 荆门市| 泾阳县| 花莲县| 隆化县| 白山市| 新安县| 四川省| 城步| 成安县| 万安县| 云霄县| 开封县| 新干县| 房产| 河北省| 库尔勒市| 化州市| 鹤峰县| 武邑县| 乐都县| 高要市| 漾濞| 化州市| 德令哈市| 海阳市| 吉木萨尔县| 密云县| 武夷山市| 玉树县| 顺义区| 体育| 吕梁市| 龙游县| 鞍山市| 安远县|