Custom Membership provider for SharePoint

No.of Views5418
Bookmarked2 times
Downloads 
Votes0
By  ninethsense   On  16 Feb 2010 00:02:57
Tag : SharePoint , Setup, Upgrade, Administration and Operation
Custom Membership provider for SharePoint
emailbookmarkadd commentsprint

Images in this article missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at info@codegain.com

 

Introduction

My intention is to provide a kick start for the SharePoint developers to write a Custom Provider for their database. You should be able to:

  • Use your existing user database with your SharePoint
  • Upgrade your existing ASP.NET appliation to SharePoint
  • Authenticate against a webservice etc.

If you search on internet, you will find much results for configuring forms authentication in SharePoint. As a beginner you will be still confuzed and the question still pending will be "how to use my own user database with SharePoint?".

Answer to the question is same - use forms authentication

Membership Class

ASP.NET forms authentication uses .NET Membership class of System.web.security. Same we will also need to use. We need to make a mock class (I would like to call...) which derives from the Membershilp class. 

Task List

Before going further, I would like you know what you are going to do.

  1. Build a Custom Membership .dll
  2. Add .dll to GAC - The Global Assembly Cache
  3. SharePoint Central Administration - Configure web.config
  4. SharePoint Central Administration - Administration
  5. SharePoint Website - Configure web.config

Prerequisites

The tools I used while writing this article are:

  • Visual Studio 2008 (you can use any edition, even express edition willl do)
  • Pre-installed Windows SharePoint Service 3.0
  • Knowledge in SharePoint
  • Knowledge in C#

Step 1: Build a Custom Membership .dll

Step 1.1: Database Setup

For the demonstration purpose, I use the following table structure.

CREATE TABLE users (
 [id] [int] IDENTITY(1,1) NOT NULL,
 [username] [varchar](50) NULL,
 [password] [varchar](50) NULL,
 [name] [varchar](50) NULL
)
Image Loading

Step 1.2: Implement MembershipProvider .dll

Frankly the process is just same as the creation of a Membership provider for ordinary ASP.NET application.You need to create a new class (a class libray project will do) which inherits the MembershipProvider of System.Web.Security.

public class pitMembership : MembershipProvider
{
}

You need to include all overriden methods in your memebership class. For this demonstration purpose, I use only those who are necessary for the working of SharePoint. Eg: GetUser(), GetAllUsers(), ValidateUser() etc.

Here goes the full source code:

using System;using System.Web.Security;using System.Data;using System.Data.SqlClient;/* * Coded by Praveen (ninethsense[at]hotmail.com) for article/demonstration purpose * Warning: I did not follow standards*/namespace pitCustomMembership
{public class pitMembership : MembershipProvider{//Your SQL Server connectionprivate const string conStr = "Data Source=localhost;Initial Catalog=test;User Id=blah;Password=blah;";// I would like call the appilcation name...private string _AppName = "pitMembership";// Dummy ValidateUserStart ******************************public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords){throw new NotImplementedException();}public override int GetNumberOfUsersOnline(){throw new NotImplementedException();}public override string GetUserNameByEmail(string email){throw new NotImplementedException();}public override string ResetPassword(string username, string answer){throw new Exception("The method or operation not implemented.");}public override bool UnlockUser(string userName){throw new Exception("The method or operation not implemented.");}public override void UpdateUser(MembershipUser user){throw new Exception("The method or operation not implemented.");}public override bool ChangePassword(string username, string oldPassword, string newPassword){throw new Exception("The method or operation not implemented.");}public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer){throw new Exception("The method or operation not implemented.");}public override string GetPassword(string username, string answer){throw new Exception("The method or operation not implemented.");}public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status){throw new Exception("The method or operation not implemented.");}public override int MinRequiredPasswordLength{get { return 1; }}public override int MinRequiredNonAlphanumericCharacters{get { return 1; }}public override string PasswordStrengthRegularExpression{get { return ""; }}public override MembershipPasswordFormat PasswordFormat{get { return MembershipPasswordFormat.Clear; }}public override bool RequiresUniqueEmail{get { return false; }}public override bool DeleteUser(string username, bool deleteAllRelatedData){throw new Exception("The method or operation not implemented.");}public override int PasswordAttemptWindow { get { return 1; } }public override int MaxInvalidPasswordAttempts { get { return 5; } }public override bool RequiresQuestionAndAnswer { get { return false; } }public override bool EnablePasswordReset { get { return true; } }public override bool EnablePasswordRetrieval { get { return true; } }public override string ApplicationName{get { return _AppName; }set { if (_AppName != value) { _AppName = value; } }}// Dummy End ******************************public override bool ValidateUser(string username, string password){SqlConnection con = new SqlConnection(conStr);SqlCommand cmd = new SqlCommand("SELECT COUNT(1) FROM users WHERE username=@username AND password=@password");cmd.Parameters.Add(new SqlParameter("@username", username));cmd.Parameters.Add(new SqlParameter("@password", password));cmd.Connection = con;con.Open();int count =  Convert.ToInt16(cmd.ExecuteScalar());con.Close();return count != 0;}public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords){MembershipUserCollection muc = new MembershipUserCollection();try{SqlDataAdapter da = new SqlDataAdapter("SELECT id, username, password, name FROM users",new SqlConnection(conStr));DataSet ds = new DataSet();da.Fill(ds);foreach (DataRow dr in ds.Tables[0].Rows){muc.Add(new MembershipUser("pitMembership",dr["username"].ToString(),dr["id"],"ninethsense[at]hotmail.com","","",true,false,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.MinValue));}totalRecords = ds.Tables[0].Rows.Count;}catch (Exception e){throw new Exception("Exception in GetAllUsers():" + e.Message);}return muc;}public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords){MembershipUserCollection muc = new MembershipUserCollection();try{// Beware of code injection :-)SqlDataAdapter da = new SqlDataAdapter("SELECT id, username, password, name FROM users WHERE username='"+usernameToMatch+"'", new SqlConnection(conStr));DataSet ds = new DataSet();da.Fill(ds);foreach (DataRow dr in ds.Tables[0].Rows){muc.Add(new MembershipUser("pitMembership",dr["username"].ToString(),dr["id"],"ninethsense[at]hotmail.com","","",true,false,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.MinValue));}totalRecords = ds.Tables[0].Rows.Count;}catch (Exception e){throw new Exception("Exception in GetAllUsers():" + e.Message);}return muc;}public override MembershipUser GetUser(object providerUserKey, bool userIsOnline){MembershipUser mu = null;try{// Beware of code injection :-)SqlDataAdapter da = new SqlDataAdapter("SELECT id, username, password, name FROM users WHERE id=" + providerUserKey.ToString(), new SqlConnection(conStr));DataSet ds = new DataSet();da.Fill(ds);if (ds.Tables[0].Rows.Count > 0){DataRow dr = ds.Tables[0].Rows[0];mu = new MembershipUser("pitMembership",dr["username"].ToString(),dr["id"],"ninethsense[at]hotmail.com","","",true,false,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.MinValue);}}catch (Exception e){throw new Exception("Exception in GetUser()1:" + e.Message);}return mu;}public override MembershipUser GetUser(string username, bool userIsOnline){MembershipUser mu = null;try{// Beware of code injection :-)SqlDataAdapter da = new SqlDataAdapter("SELECT id, username, password, name FROM users WHERE username='" + username + "'", new SqlConnection(conStr));DataSet ds = new DataSet();da.Fill(ds);if (ds.Tables[0].Rows.Count > 0){DataRow dr = ds.Tables[0].Rows[0];mu = new MembershipUser("pitMembership",dr["username"].ToString(),dr["id"],"ninethsense[at]hotmail.com","","",true,false,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.Now,DateTime.MinValue);}}catch (Exception e){throw new Exception("Exception in GetUser()2:" + e.Message);}return mu;}}}

For your easy understanding I used plain SQL statements inside the code. You can see for all dummy overriden methods, I thrown exception. Let me tell you about the used methods:

  1. ValidateUser() - This method verifies whether the supplied username and password matches any record in your database. This is used when you try to login to sharepoint.
  2. GetAllUsers() - Returns a list of all members available in database
  3. FindUsersByName() - Returns a list of members which matches the supplied username
  4. GetUser(providerUserKey,bool) - Get the user information based on supplied user key
  5. GetUser(username, bool) - Get the user information based on the supplied username

Step 1.3: Sign the .dll

In order to add your dll (assembly) to GAC, you need to sign your dll with a strong name. An easy method will be to do the following:

  1. Take Project Properties (right click on the project node on Solution Explorer -> Properties)
  2. Signing Tab
  3. Click the checkbox of Sign the assembly
  4. Select from the dropdown
  5. Add a new keyname (and provide password if you wish or just uncheck the check box)

Step 1.4: Build

Now build the appliation so that you have the .dll file ready. I have a dll with name pitCustomMembership.dll.

Step 2: Add .dll to GAC

I will use the gacutil command line to do this. Follow these steps if you do not know.

  1. Start -> Programs -> Microsoft Visual Studio 2008 -> Visual Studio 2008 Tools -> Visual Studio 2008 Command Prompt
  2. type gacutil /i your dll.

Here is what I saw:

C:\SharePoint custom provider\pitCustomMembership\bin>gacutil /i pitCustomMembership.dll
Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembly successfully added to the cache

Now let us assume the dll is in GAC.

Step 3: SharePoint Central Administration - Configure web.config

Take the web.config file of your Central Adminstration website. You can find the path from IIS Manager - Start -> Settings ->Control Panel -> Administrative Tools -> Internet Information Services (IIS) Manager

Add the below code inside the node:

Wonder where this assembly, Version etc. comes from? Here is one way to get those details:

  1. On windows explorer, point to C:\Windows\assembly
  2. Locate your dll
  3. Right click -> Properties

Step 4: SharePoint Central Administration - Administration

Image Loading
  1. Login to your Central Administration Website
  2. Application Management -> Application Security:Authentication Provider
  3. Select Default Zone
  4. Choose Authentication Type = Forms
  5. Typ3 Membership provider name
Image Loading

Now go back to Application Management again then

  1. Application Management -> SharePoint Site Management:Site Collection Administrators
  2. Type a username from your database and click check names icon.
Image Loading

You should see your username underlined now. This is a good sign that your authentication provider started working.

Image Loading

Step 5: SharePoint Website - Configure web.config

Now paste the same of your central administration website's web.config (Step 3) in your SharePoint website.

Everything Finished!

 

Image Loading

Now you should be able to login to the SharePoint website with the username and password in your database.

 
Sign Up to vote for this article
 
About Author
 
ninethsense
Occupation-
Company-
Member Type-Junior
Location-Not Provided
Joined date-21 Jul 2009
Home Page-http://blog.ninethsense.com/
Blog Page-http://blog.ninethsense.com/
 
 
Other popularSectionarticles
Comments
By:jerkfaceDate Of Posted:2/3/2011 10:24:23 AM
jerk
save time and put the version of SP
By:OrnaDate Of Posted:12/30/2010 5:30:07 AM
Do I need to implement Role manger Provider as well?
Do I need to implement a role provider as well? can you refer me to an article? Thanks
By:PraVeeNDate Of Posted:9/21/2010 4:15:40 AM
Web.config content
Please refer to this link - http://kidoos.net/content/SharePointCustomMemershipProvider.aspx
By:StarkDate Of Posted:9/21/2010 4:08:00 AM
web.config code missing
Hi there, Could you please provide me with the web.config section code, you seem to have left it out of this post. thanks!
By:yiu-faicDate Of Posted:8/4/2010 9:23:56 AM
missing information on your steps of description
After this "Add the below code inside the node: " Ik think I'm missing the information what to fill in.
Leave a Reply
Title:
Display Name:
Email:
(not display in page for the security purphase)
Website:
Message:
Please refresh your screen using Ctrl+F5
If you can't read this number refresh your screen
Please input the anti-spam code that you can read in the image.
^ Scroll to Top