Simple example with Custom Membership provider

Posted by Community Admin on 03-Aug-2018 15:42

Simple example with Custom Membership provider

All Replies

Posted by Community Admin on 09-Mar-2011 00:00

Hello,
I need to write my own custom membership provider that only needs to replace the ValidateUser method.... I tried using a

TestProvider : MembershipProvider

and I can stop at validate user,
using

TestProvider : SitefinityMembershipProvider

I got no luck.......since for what I need I don't have to override all the methods but only one, anyone can provide me a sample? even what to set in web.config and Security.Config (I've tried to add via admin panel but with no luck

Thanks
Paolo

Posted by Community Admin on 09-Mar-2011 00:00

Hello Paolo,

Please take a look at this post

www.sitefinity.com/.../extending-membership-provider.aspx

Best wishes,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 09-Mar-2011 00:00

Hello Ivan,
 I just looked at that posted before, my question is from which class should I hinerits ? I'll use my custom SQLServer database to validate the user.....so I think I can't use the OpenAccessMembershipProvider, am I right?

Posted by Community Admin on 09-Mar-2011 00:00

Hello Paolo,

MembershipDataProvider is the base class. There is OpenAccessMembershipProvider which inherits from MembershipDataProvider.  OpenAccessMembershipProvider is our implementation related to the OA model. If you are not going to use our logic and our database as a storage you can inherit from MembershipDataProvider

Best wishes,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 09-Mar-2011 00:00

Hello Ivan,
thanks a lot, just a question, when I login/logout it executes the

public override IQueryable<Telerik.Sitefinity.Security.Model.User> GetUsers()
       
            
           throw new System.NotImplementedException();
       

using the OpenData I can set to base.GetUsers(), hineriting from MembershipDataProvider doens't permits to me to do so...any suggestion?

what should I put in there? I can't set it to null...

Posted by Community Admin on 09-Mar-2011 00:00

Hello Paolo,

In your previous post you said that you would use another database to get the users. In this method you should query this external for Sitefinity database.
 
If the user belong to another database and it is not created through Sitefinity the Validate method should also be rewritten, because it will not work outside of the OA provider.

Kind regards,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 10-Mar-2011 00:00

Hello Ivan,
but the GetUsers method should retrieve all the user that are inside my external DB? I've done a simple test doing :

public override IQueryable<Telerik.Sitefinity.Security.Model.User> GetUsers()
      
          IQueryable<Telerik.Sitefinity.Security.Model.User> lst = new List<Telerik.Sitefinity.Security.Model.User>().AsQueryable();
          return lst;
      
      public override bool ValidateUser(string userName, string password)
      
          return true;
          int a = 0;
          re

but when I log in I receive this :

Invalid user name.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: Invalid user name.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[ArgumentException: Invalid user name.]
   Telerik.Sitefinity.Security.SecurityManager.AuthenticateUser(String membershipProviderName, String userName, String password, Boolean persistent, User& user) +206
   Telerik.Sitefinity.Security.Web.UI.LoginForm.LoginForm_Authenticate(Object sender, AuthenticateEventArgs e) +189
   System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e) +115
   System.Web.UI.WebControls.Login.AttemptLogin() +127
   System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e) +101
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
   System.Web.UI.WebControls.LinkButton.OnCommand(CommandEventArgs e) +125
   System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +169
   System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +9
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +176
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563

any help?
Thanks

Posted by Community Admin on 10-Mar-2011 00:00

Hi Paolo,

Yes you need to query your database in GetUsers method and return a Queriable list of yuor users. Currently you are returning an empty list.Also you should set the login form control to use your custom membership provider. If this is the backend login control you should see a drop down with the two providers inside it.

Kind regards,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 10-Mar-2011 00:00

Hello Ivan,
I don't know if I'm doing something wrong or if it's a bug..... by the way If I do so :

public override IQueryable<Telerik.Sitefinity.Security.Model.User> GetUsers()
       
           Stopwatch sw = new Stopwatch();
           sw.Start();
           List<Telerik.Sitefinity.Security.Model.User> lst = new List<Telerik.Sitefinity.Security.Model.User>();
           //using (XXXEntities entities = new XXXEntities())
           //
           //    Parallel.ForEach(entities.I_UTENTI, (i) =>
           //   
           //        User user = new User();
           //        user.SetUserName(i.UTENTE.ToUpper());
           //        lst.Add(user);
           //    );
           //
           //sw.Stop();
           //TimeSpan ts = sw.Elapsed;
           return lst.AsQueryable();
       

I got an error.......(Invalid user name)

I also get this error if I write the username in lowercase when executing the code I wrote you uncommented (going on XXXEntity's I_UTENTI and having the username written in lowercase....... it needs a match on I_UTENTE.UTENTE equals to telerik's logintextbox . text ....

I've set the memebership provider in the userconrol and I see the two providers (the login control is the one for the fronend users, the backend users will log using the default credentials)

another question when implementing the providers I saw a

MembershipManagerInfo and ApplicationName, what should I put in there?

Thanks
Paolo

Posted by Community Admin on 10-Mar-2011 00:00

Hi Paolo,

You should create a user object and return a list of users

User newUser = new User ;
 newUser.Comment = "";
 newUser.LastActivityDate = DateTime.UtcNow.AddDays(-1);
 newUser.LastModified = DateTime.MinValue;
 newUser.FailedPasswordAnswerAttemptWindowStart = DateTime.MinValue;
 newUser.FailedPasswordAttemptWindowStart = DateTime.MinValue;
 newUser.LastActivityDate = DateTime.MinValue;
 newUser.LastLoginDate = DateTime.MinValue;
 var mi = new ManagerInfo();
 newUser.SetCreationDate(DateTime.UtcNow);
 newUser.SetLastPasswordChangedDate(DateTime.UtcNow);
 newUser.SetLastLockoutDate(DateTime.UtcNow);
 mi.ApplicationName = newUser.ApplicationName;
 mi.ManagerType = typeof(UserManager).FullName;
 mi.ProviderName = "SampleProvider";
 newUser.ManagerInfo = mi;
 users.Add(newUser);


Regards,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 10-Mar-2011 00:00

Hello Ivan,
I tried but I always get 

Server Error in '/' Application.

Invalid user name.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentException: Invalid user name.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[ArgumentException: Invalid user name.]
   Telerik.Sitefinity.Security.SecurityManager.AuthenticateUser(String membershipProviderName, String userName, String password, Boolean persistent, User& user) +206
   Telerik.Sitefinity.Security.Web.UI.LoginForm.LoginForm_Authenticate(Object sender, AuthenticateEventArgs e) +189
   System.Web.UI.WebControls.Login.OnAuthenticate(AuthenticateEventArgs e) +115
   System.Web.UI.WebControls.Login.AttemptLogin() +127
   System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e) +101
   System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +37
   System.Web.UI.WebControls.Button.OnCommand(CommandEventArgs e) +125
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +167
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563

In order to avoid this I need to have in my collection an item with the same name I typed in the textbox....

Posted by Community Admin on 11-Mar-2011 00:00

Hello Ivan,
can you please update me on this?
Thanks

Posted by Community Admin on 11-Mar-2011 00:00

Hello Paolo,

This error is thrown when the user does not exist in the datasource. So, the provider name of you use is not correct

var membershipProviderName = "YOUR PROVIDER NAME";
var manager = UserManager.GetManager(membershipProviderName);
manager.Provider.SuppressSecurityChecks = true;
 if (manager.ValidateUser(userName, password))
           
                user = manager.GetUser(userName);
            
                if (user == null)
                    throw new ArgumentException("Invalid user name.");

Can you run the code below to see whether it will pass. The user should not be null if the provider is correct.

Best wishes,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 11-Mar-2011 00:00

I'm to try this now but my get users will return just a dummy username, am I right? as you pasted me below..... or for each user I've in my collection I need to create such an object?

For my provider name you intend the name of my class?
Thanks

Posted by Community Admin on 15-Mar-2011 00:00

Hello Paolo,

Since you have a custom provider this provider should have a name which you used to register it. Inside manager.ValidateUser you should pass the name and password of the user you are trying to authenticate. This should be an object of type Telerik.Sitefinity.Security.Model.User

Best wishes,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 21-Mar-2011 00:00

Hello Ivan,
I've returned working on this.... I've got my own MembershipProvider and I used successfully to log in, I've tried going in the backend and changing the page permission (I wish to set it to authenticated), when I set it I got a strange problem.....I got the following error :

A referential integrity constraint violation occurred: A primary key property that is a part of referential integrity constraint cannot be changed when the dependent object is Unchanged unless it is being set to the association's principal object. The principal object must be tracked and not marked for deletion.

This error happens in the getter of self generated property

[XmlIgnoreAttribute()]
     [SoapIgnoreAttribute()]
     [DataMemberAttribute()]
     [EdmRelationshipNavigationPropertyAttribute("IModel", "FK_SF_PROFILI_UTENTI_I_UTENTI", "SF_PROFILI_UTENTI")]
     public SF_PROFILI_UTENTI SF_PROFILI_UTENTI
     
         get
         
             return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<SF_PROFILI_UTENTI>("IModel.FK_SF_PROFILI_UTENTI_I_UTENTI", "SF_PROFILI_UTENTI").Value;
         
         set
         
             ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<SF_PROFILI_UTENTI>("IModel.FK_SF_PROFILI_UTENTI_I_UTENTI", "SF_PROFILI_UTENTI").Value = value;
         
     

I defined my RoleProvider as follow :

public class IFRoleProvider :  RoleDataProvider
  
      public IFRoleProvider()
      
          int t = 0;
      
      public override Telerik.Sitefinity.Security.Model.Role CreateRole(Guid id, string roleName)
      
          throw new NotImplementedException();
      
      public override Telerik.Sitefinity.Security.Model.Role CreateRole(string roleName)
      
          throw new NotImplementedException();
      
      public override Telerik.Sitefinity.Security.Model.UserLink CreateUserLink(Guid id)
      
          throw new NotImplementedException();
      
      public override Telerik.Sitefinity.Security.Model.UserLink CreateUserLink()
      
          throw new NotImplementedException();
      
      public override void Delete(Telerik.Sitefinity.Security.Model.UserLink item)
      
          throw new NotImplementedException();
      
      public override void Delete(Telerik.Sitefinity.Security.Model.Role item)
      
          throw new NotImplementedException();
      
      public override Telerik.Sitefinity.Security.Model.Role GetRole(Guid id)
      
          throw new NotImplementedException();
      
      public override IQueryable<Telerik.Sitefinity.Security.Model.Role> GetRoles()
      
          throw new NotImplementedException();
      
      public override Telerik.Sitefinity.Security.Model.UserLink GetUserLink(Guid id)
      
          throw new NotImplementedException();
      
      public override IQueryable<Telerik.Sitefinity.Security.Model.UserLink> GetUserLinks()
      
          List<Telerik.Sitefinity.Security.Model.UserLink> lst = new List<Telerik.Sitefinity.Security.Model.UserLink>();
          var l = lst.AsQueryable();
          return l;
      
  

What should I put in there since I don't need to use userlink?
Thanks

Posted by Community Admin on 24-Mar-2011 00:00

Hi Paolo,

Are you using the Microsoft Entiry Framework? It seems to me that the exception comes from it somewhere. We are soon releasing the providers updates so you could simply use our implementation, because there are some specifics that we have tracked and debugged.

Greetings,
Liubomir
the Telerik team

Posted by Community Admin on 31-Mar-2011 00:00

Hello Ivan,
yes I'm using EF but I've refactored the tables and now it works... I got problems now with showing the roles in the Administration -> Roles but I've opened another thread

Thanks

Posted by Community Admin on 04-Apr-2011 00:00

Hello Ivan,
when I implement the Membership provider you suggested me to specify a 

User newUser = GeneraUtenteSF_Da_UtenteIDEA(user);
                 newUser.Comment = string.Empty;
                 newUser.LastActivityDate = DateTime.UtcNow.AddDays(-1);
                 newUser.LastModified = DateTime.MinValue;
                 newUser.FailedPasswordAnswerAttemptWindowStart = DateTime.MinValue;
                 newUser.FailedPasswordAttemptWindowStart = DateTime.MinValue;
                 newUser.LastActivityDate = DateTime.MinValue;
                 newUser.LastLoginDate = DateTime.MinValue;
                 newUser.SetCreationDate(DateTime.UtcNow);
                 newUser.SetLastPasswordChangedDate(DateTime.UtcNow);
                 newUser.SetLastLockoutDate(DateTime.UtcNow);
                 newUser.Id = id;
                 var mi = new ManagerInfo();
                 mi.ApplicationName = newUser.ApplicationName;
                 mi.ManagerType = typeof(UserManager).FullName;
                 mi.ProviderName = "IFProvider";

ManagerInfo, when I implement the role provider should I use the same manager info or what? I got problem showing the users and their roles in the backoffice (also got problem when setting the role to the one I have in my provider)

Any suggestion?
Thanks

Posted by Community Admin on 05-Apr-2011 00:00

Hi Paolo,

You have to set the ApplicationName for the role object.

public override IQueryable<Role> GetRoles()
       
            var allRoles = this.roleProvider.GetAllRoles();
            var result = new List<RoleWrapper>();
            for (int i = 0; i < allRoles.Length; i++)
           
                var newRole = new RoleWrapper(this.id , allRoles[i]);
                newRole.ApplicationName = this.ApplicationName;
                result.Add(newRole);
           

            return result.AsQueryable<Role>();
       

public class RoleWrapper : Telerik.Sitefinity.Security.Model.Role
    
     
        public RoleWrapper(Guid id, string roleName)
       
            this.Id = id;
            this.Name = roleName;
         
       


Regards,
Ivan Dimitrov
the Telerik team


Posted by Community Admin on 05-Apr-2011 00:00

Hello Ivan, but should I also set a MembershipInfo to the User / UserLink / Role (I've not got the solution right now...so I remember there's also a ManagerInfo as property.... need I to inherit from RoleManager/UserManager?

I've also noticed that if I put some Users in the Membership provider for the GetUsers() I got an "Object not set to an instance..."  when I'm in the Admin->Users  section....

Thanks

This thread is closed