国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > 綜合 > 正文

Community Server專題八:MemberRole之Membership深入篇

2024-07-21 02:29:26
字體:
來源:轉載
供稿:網友

專題八的上篇大致討論了memberrole中的membership實現(xiàn),對于運用membership進行足夠,但是對于想更深入了解membership實現(xiàn)機理的朋友那是遠遠不夠的,這個專題我們更深入一下了解membership。

其實memberrole是一個非常好的資源包,借住reflector這個優(yōu)秀的工具,你可以對其進行代碼分析。它無論是在組建的構架、代碼的設計、數(shù)據庫表的建立、存儲過程的使用等都是非常優(yōu)秀的,你是程序員也好構架師也罷,其中可以學習的真的很多很多,我在整個分析的過程中也深深受益。

由于memberrole中的membership只實現(xiàn)了對sql server的操provider類,即sqlmembershipprovider類。因此我們從sqlmembershipprovider開始分析。provider模型在上篇已經做過介紹,sqlmembershipprovider類繼承了membershipprovider,并實現(xiàn)其所有的抽象方法。在分析之前先看兩個類:membershipuser與membershipusercollection。

membershipuser,先看看代碼:(代碼中省略的具體實現(xiàn),只有方法與屬性名稱)

public class membershipuser
{
      // methods
      protected membershipuser();
      public membershipuser(membershipprovider provider, string name, object provideruserkey, string email, string passwordquestion, string comment, bool isapproved, bool islockedout, datetime creationdate, datetime lastlogindate, datetime lastactivitydate, datetime lastpasswordchangeddate, datetime lastlockoutdate);
      public virtual bool changepassword(string oldpassword, string newpassword);
      public virtual bool changepasswordquestionandanswer(string password, string newpasswordquestion, string newpasswordanswer);
      public virtual string getpassword();
      public virtual string getpassword(string passwordanswer);
      public virtual string resetpassword();
      public virtual string resetpassword(string passwordanswer);
      public override string tostring();
      public virtual bool unlockuser();
      internal virtual void update();
      private void updateself();
      // properties
      public virtual string comment { get; set; }
      public virtual datetime creationdate { get; }
      public virtual string email { get; set; }
      public virtual bool isapproved { get; set; }
      public virtual bool islockedout { get; }
      public bool isonline { get; }
      public virtual datetime lastactivitydate { get; set; }
      public virtual datetime lastlockoutdate { get; }
      public virtual datetime lastlogindate { get; set; }
      public virtual datetime lastpasswordchangeddate { get; }
      public virtual string passwordquestion { get; }
      public virtual membershipprovider provider { get; }
      public virtual object provideruserkey { get; }
      public virtual string username { get; }
      // fields
      private string _comment;
      private datetime _creationdate;
      private string _email;
      private bool _isapproved;
      private bool _islockedout;
      private datetime _lastactivitydate;
      private datetime _lastlockoutdate;
      private datetime _lastlogindate;
      private datetime _lastpasswordchangeddate;
      private string _passwordquestion;
      private membershipprovider _provider;
      private object _provideruserkey;
      private string _username;
}

這是一個實體類,表示一個由membership創(chuàng)建的user,該類中有這個user的一些基本狀態(tài),如該user的username、email等,還有一些方法,如changepassword()、resetpassword()等(如果你是初學者,還在為建立一個對象需要什么屬性,包含什么方法發(fā)愁,那這就是你應該好好學的,這也是oop最基本的要求)。

membershipusercollection,這是一個membershipuser類的容器,用來存放membershipuser列表,記得上次廣州.net俱樂部聚會時,我的演講中有朋友在提出cs是否使用自定義類來存儲用戶列表,其實在這里可以看到cs中使用的就是自定義的類而不是dataset(我想在asp.net 2.0正式發(fā)布后這也不會改變),這樣做主要是因為考慮到性能與靈活性。

好了,回到sqlmembershipprovider類上來,我們具體分析一個有代表性質的方法:


public override membershipuser createuser(string username, string password, string email, string passwordquestion, string passwordanswer, bool isapproved, object provideruserkey, out membershipcreatestatus status)

{

      string text3;

      membershipuser user1;

      if (!secutility.validateparameter(ref password, true, true, false, 0x80))

      {

            status = membershipcreatestatus.invalidpassword;

            return null;

      }

      string text1 = base.generatesalt();

      string text2 = base.encodepassword(password, (int) this._passwordformat, text1);

      if (text2.length > 0x80)

      {

            status = membershipcreatestatus.invalidpassword;

            return null;

      }

      if (passwordanswer != null)

      {

            passwordanswer = passwordanswer.trim();

      }

      if ((passwordanswer != null) && (passwordanswer.length > 0))

      {

            if (passwordanswer.length > 0x80)

            {

                  status = membershipcreatestatus.invalidanswer;

                  return null;

            }

            text3 = base.encodepassword(passwordanswer.tolower(cultureinfo.invariantculture), (int) this._passwordformat, text1);

      }

      else

      {

            text3 = passwordanswer;

      }

      if (!secutility.validateparameter(ref text3, this.requiresquestionandanswer, this.requiresquestionandanswer, false, 0x80))

      {

            status = membershipcreatestatus.invalidanswer;

            return null;

      }

      if (!secutility.validateparameter(ref username, true, true, true, 0x100))

      {

            status = membershipcreatestatus.invalidusername;

            return null;

      }

      if (!secutility.validateparameter(ref email, this.requiresuniqueemail, this.requiresuniqueemail, false, 0x100))

      {

            status = membershipcreatestatus.invalidemail;

            return null;

      }

      if (!secutility.validateparameter(ref passwordquestion, this.requiresquestionandanswer, this.requiresquestionandanswer, false, 0x100))

      {

            status = membershipcreatestatus.invalidquestion;

            return null;

      }

      if ((provideruserkey != null) && !(provideruserkey is guid))

      {

            status = membershipcreatestatus.invalidprovideruserkey;

            return null;

      }

      if (password.length < this.minrequiredpasswordlength)

      {

            status = membershipcreatestatus.invalidpassword;

            return null;

      }

      int num1 = 0;

      for (int num2 = 0; num2 < password.length; num2++)

      {

            if (!char.isletterordigit(password, num2))

            {

                  num1++;

            }

      }

      if (num1 < this.minrequirednonalphanumericcharacters)

      {

            status = membershipcreatestatus.invalidpassword;

            return null;

      }

      if ((this.passwordstrengthregularexpression.length > 0) && !regex.ismatch(password, this.passwordstrengthregularexpression))

      {

            status = membershipcreatestatus.invalidpassword;

            return null;

      }

      validatepasswordeventargs args1 = new validatepasswordeventargs(username, password, true);

      this.onvalidatingpassword(args1);

      if (args1.cancel)

      {

            status = membershipcreatestatus.invalidpassword;

            return null;

      }

      try

      {

            sqlconnectionholder holder1 = null;

            try

            {

                  holder1 = sqlconnectionhelper.getconnection(this._sqlconnectionstring, true);

                  this.checkschemaversion(holder1.connection);

                  sqlcommand command1 = new sqlcommand("dbo.aspnet_membership_createuser", holder1.connection);

                  command1.commandtimeout = this.commandtimeout;

                  command1.commandtype = commandtype.storedprocedure;

                  command1.parameters.add(this.createinputparam("@applicationname", sqldbtype.nvarchar, this.applicationname));

                  command1.parameters.add(this.createinputparam("@username", sqldbtype.nvarchar, username));

                  command1.parameters.add(this.createinputparam("@password", sqldbtype.nvarchar, text2));

                  command1.parameters.add(this.createinputparam("@passwordsalt", sqldbtype.nvarchar, text1));

                  command1.parameters.add(this.createinputparam("@email", sqldbtype.nvarchar, email));

                  command1.parameters.add(this.createinputparam("@passwordquestion", sqldbtype.nvarchar, passwordquestion));

                  command1.parameters.add(this.createinputparam("@passwordanswer", sqldbtype.nvarchar, text3));

                  command1.parameters.add(this.createinputparam("@isapproved", sqldbtype.bit, isapproved));

                  command1.parameters.add(this.createinputparam("@uniqueemail", sqldbtype.int, this.requiresuniqueemail ? 1 : 0));

                  command1.parameters.add(this.createinputparam("@passwordformat", sqldbtype.int, (int) this.passwordformat));

                  command1.parameters.add(this.gettimezoneadjustmentparam());

                  sqlparameter parameter1 = this.createinputparam("@userid", sqldbtype.uniqueidentifier, provideruserkey);

                  parameter1.direction = parameterdirection.inputoutput;

                  command1.parameters.add(parameter1);

                  parameter1 = new sqlparameter("@returnvalue", sqldbtype.int);

                  parameter1.direction = parameterdirection.returnvalue;

                  command1.parameters.add(parameter1);

                  object obj1 = command1.executescalar();

                  datetime time1 = this.roundtoseconds(datetime.now);

                  if ((obj1 != null) && (obj1 is datetime))

                  {

                        time1 = (datetime) obj1;

                  }

                  int num3 = (parameter1.value != null) ? ((int) parameter1.value) : -1;

                  if ((num3 < 0) || (num3 > 11))

                  {

                        num3 = 11;

                  }

                  status = (membershipcreatestatus) num3;

                  if (num3 != 0)

                  {

                        return null;

                  }

                  provideruserkey = new guid(command1.parameters["@userid"].value.tostring());

                  return new membershipuser(this, username, provideruserkey, email, passwordquestion, null, isapproved, false, time1, time1, time1, time1, new datetime(0x6da, 1, 1));

            }

            finally

            {

                  if (holder1 != null)

                  {

                        holder1.close();

                        holder1 = null;

                  }

            }

      }

      catch

      {

            throw;

      }

      return user1;

}


該方法實現(xiàn)建立一個用戶的過程,建立后返回一個被建立的membershipuser對象,如果建立失敗membershipuser對象為null(其實我早期做過一些項目的時候喜歡在建立對象成功后返回一個id)。可以看到在這個方法中有很多的if語句,它們是為了檢驗數(shù)據是否合法,這是必須的嗎?其實不是,但對于構建一個強壯的底層代碼這是必須的,不然一點點的錯誤都有可能導致系統(tǒng)的癱瘓。其實做項目與做開發(fā)有的時候不太一樣,企業(yè)的有些項目開發(fā)很多時候只要能實現(xiàn)功能就可以了,而且開發(fā)過程也集中在一些現(xiàn)有的代碼或者組建的基礎上,個人的錯誤不會影響全局的運行,pm也不做過多要求。但如果是做產品,這個情況可能會有所改變,很多時候要求很嚴格,至少我是這樣。在做完對輸入參數(shù)的驗證后,createuser建立與數(shù)據庫的連接,這里是調用sqlconnectionhelper類下的getconnection方法進行的,為了照顧初學者閱讀,我這里這一下為什么需要把對數(shù)據庫連接與操作寫在sqlconnectionhelper類下,而不是直接采用sqlconnection提供的方法,其實這是一個設計模式的問題,membership的實現(xiàn)需要很多的方法與數(shù)據庫進行交換數(shù)據庫,如果每次方法都調用一次sqlconnection的方法建立數(shù)據庫連接,一來會造成大量的代碼冗余,而且一旦數(shù)據庫連接語句一旦改變,你就要去修改很多個方法,如果你把這個過程都包裝在一個類下面,連接數(shù)據庫就有統(tǒng)一的入口,一來容易維護,二來不會有太多的代碼冗余,再者如果需要查找錯誤也非常容易。這里membership采用的是存儲過程,我們可以看到使用的是dbo.aspnet_membership_createuser存儲過程,好了,打開你的數(shù)據庫,找到這個存儲過程:

 

create procedure dbo.aspnet_membership_createuser

    @applicationname                        nvarchar(256),

    @username                               nvarchar(256),

    @password                               nvarchar(128),

    @passwordsalt                           nvarchar(128),

    @email                                  nvarchar(256),

    @passwordquestion                       nvarchar(256),

    @passwordanswer                         nvarchar(128),

    @isapproved                             bit,

    @timezoneadjustment                     int,

    @createdate                             datetime = null,

    @uniqueemail                            int      = 0,

    @passwordformat                         int      = 0,

    @userid                                 uniqueidentifier output

as

begin

    declare @applicationid uniqueidentifier

    select  @applicationid = null

 

    declare @newuserid uniqueidentifier

    select @newuserid = null

 

    declare @islockedout bit

    set @islockedout = 0

 

    declare @lastlockoutdate  datetime

    set @lastlockoutdate = convert( datetime, '17540101', 112 )

 

    declare @failedpasswordattemptcount int

    set @failedpasswordattemptcount = 0

 

    declare @failedpasswordattemptwindowstart  datetime

    set @failedpasswordattemptwindowstart = convert( datetime, '17540101', 112 )

 

    declare @failedpasswordanswerattemptcount int

    set @failedpasswordanswerattemptcount = 0

 

    declare @failedpasswordanswerattemptwindowstart  datetime

    set @failedpasswordanswerattemptwindowstart = convert( datetime, '17540101', 112 )

 

    declare @newusercreated bit

    declare @returnvalue   int

    set @returnvalue = 0

 

    declare @errorcode     int

    set @errorcode = 0

 

    declare @transtarted   bit

    set @transtarted = 0

 

    if( @@trancount = 0 )

    begin

           begin transaction

           set @transtarted = 1

    end

    else

           set @transtarted = 0

 

    exec dbo.aspnet_applications_createapplication @applicationname, @applicationid output

 

    if( @@error <> 0 )

    begin

        set @errorcode = -1

        goto cleanup

    end

 

    if (@createdate is null)

        exec dbo.aspnet_getutcdate @timezoneadjustment, @createdate output

    else

        select  @createdate = dateadd(n, [email protected], @createdate) -- switch to utc time

 

    select  @newuserid = userid from dbo.aspnet_users where lower(@username) = loweredusername and @applicationid = applicationid

    if ( @newuserid is null )

    begin

        set @newuserid = @userid

        exec @returnvalue = dbo.aspnet_users_createuser @applicationid, @username, 0, @createdate, @newuserid output

        set @newusercreated = 1

    end

    else

    begin

        set @newusercreated = 0

        if( @newuserid <> @userid and @userid is not null )

        begin

            set @errorcode = 6

            goto cleanup

        end

    end

 

    if( @@error <> 0 )

    begin

        set @errorcode = -1

        goto cleanup

    end

 

    if( @returnvalue = -1 )

    begin

        set @errorcode = 10

        goto cleanup

    end

 

    if ( exists ( select userid

                  from   dbo.aspnet_membership

                  where  @newuserid = userid ) )

    begin

        set @errorcode = 6

        goto cleanup

    end

 

    set @userid = @newuserid

 

    if (@uniqueemail = 1)

    begin

        if (exists (select *

                    from  dbo.aspnet_membership m with ( updlock, holdlock )

                    where applicationid = @applicationid and loweredemail = lower(@email)))

        begin

            set @errorcode = 7

            goto cleanup

        end

    end

 

    insert into dbo.aspnet_membership

                ( applicationid,

                  userid,

                  password,

                  passwordsalt,

                  email,

                  loweredemail,

                  passwordquestion,

                  passwordanswer,

                  passwordformat,

                  isapproved,

                  islockedout,

                  createdate,

                  lastlogindate,

                  lastpasswordchangeddate,

                  lastlockoutdate,

                  failedpasswordattemptcount,

                  failedpasswordattemptwindowstart,

                  failedpasswordanswerattemptcount,

                  failedpasswordanswerattemptwindowstart )

         values ( @applicationid,

                  @userid,

                  @password,

                  @passwordsalt,

                  @email,

                  lower(@email),

                  @passwordquestion,

                  @passwordanswer,

                  @passwordformat,

                  @isapproved,

                  @islockedout,

                  @createdate,

                  @createdate,

                  @createdate,

                  @lastlockoutdate,

                  @failedpasswordattemptcount,

                  @failedpasswordattemptwindowstart,

                  @failedpasswordanswerattemptcount,

                  @failedpasswordanswerattemptwindowstart )

    if( @@error <> 0 )

    begin

        set @errorcode = -1

        goto cleanup

    end

    if (@newusercreated = 0)

    begin

        update dbo.aspnet_users

        set    lastactivitydate = @createdate

        where  @userid = userid

        if( @@error <> 0 )

        begin

            set @errorcode = -1

            goto cleanup

        end

    end

    select @createdate = dateadd( n, @timezoneadjustment, @createdate )

    if( @transtarted = 1 )

    begin

           set @transtarted = 0

           commit transaction

    end

    return 0

cleanup:

    if( @transtarted = 1 )

    begin

        set @transtarted = 0

           rollback transaction

    end

    return @errorcode

end

go


夠長的,不過沒有關系,分幾個部分看,首先是定義一些要發(fā)揮得參數(shù),然后初始化,接著exec dbo.aspnet_applications_createapplication,調用aspnet_applications_createapplication存儲過程,建立一個名字為@applicationname 的application,如果該application不存在的話.并且返回該application的id,這里的applicationname在web.config membership節(jié)點中設置過,即:dev。如果執(zhí)行以上過程有錯誤,通過sql的goto語句跳至cleanup部分,執(zhí)行rollback transaction,回滾這次操作。如果沒有錯誤存儲過程就接著向下執(zhí)行,exec dbo.aspnet_getutcdate @timezoneadjustment, @createdate output,這是獲得當前utc時間。再下來就判斷aspnet_users表中用戶的userid是否在數(shù)據庫中有該userid(userid是一個guid),如果沒有就在表aspnet_users中建立。這時在進行一次失分發(fā)生錯誤的判斷,執(zhí)行的方法與前一次一樣。再下來判斷aspnet_membership表中是否有該userid存在,如果沒有就根據@uniqueemail參數(shù)判斷是否允許email在數(shù)據庫中重復。最后才是把user的信息插入aspnet_membership表,再下來還有一些對錯誤的處理...

其實這個存儲過程并不復雜,但是非常繁瑣的,也可以看出設計者對數(shù)據庫檢驗的嚴格性的要求非常高。有了對存儲過程一定的了解后,我們接下來那些傳遞的參數(shù)也就明白有何用處了,最后關閉數(shù)據庫的連接,把返回的這些參數(shù)通過實例化一個membershipuser類傳遞過去,然后返回這個實例化的membershipuser,這樣該方法就完成了一次操作。

最后我們看看數(shù)據庫,membership直接關聯(lián)的有3個表

表很簡單,關系也很明了,我就不多說了,總要給我留點時間吧,也給你自己留一些分析的空間,我要是全都說完了那你做什么?呵呵。

    如果你了解cs系統(tǒng),你肯定會提出這樣一個疑問:用戶信息不只表membership中這一點呀,保存用戶個性化設置的如選用什么語言、什么皮膚等等信息的數(shù)據都在哪里?期待吧,那是后面的profile專題需要敘述的問題。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 蓬安县| 缙云县| 东兴市| 富川| 石林| 韶山市| 广德县| 陆川县| 酒泉市| 长春市| 双桥区| 大荔县| 康乐县| 尼玛县| 靖边县| 五家渠市| 扶余县| 太原市| 扬中市| 讷河市| 太原市| 揭西县| 安泽县| 甘洛县| 永济市| 楚雄市| 邯郸市| 蚌埠市| 德州市| 宣汉县| 永仁县| 新密市| 阳高县| 饶河县| 庆城县| 垣曲县| 陆川县| 当雄县| 当雄县| 浪卡子县| 屯门区|