Skip to main content
SharePoint Hosting,SharePoint租用,Hosted SharePoint,QFD软件

SharePoint Blog

Go Search
主页
解决方案
QFD 软件
SharePoint租用
SharePoint学习
SharePoint 2010
会员中心
客服中心
关于我们
留言
  

楠木科技 > SharePoint Blog
SharePoint Study, MOSS Study, Silverlight Study.

 All Posts

Expand/Collapse CategoryLive ‎(2)
Expand/Collapse CategorySAAS ‎(4)
Expand/Collapse CategorySharePoint ‎(4)
Expand/Collapse CategorySilverLight ‎(4)
Expand/Collapse CategoryTechnology ‎(95)
Expand/Collapse CategoryWork ‎(1)

 SharePoint Articles

ASP.NET MVC Preview Part 1

ASP.NET MVC Preview: Using The MVC UI Helpers

For the last month or so I've been working on the MVC UI Helpers (aka the MVC Toolkit) that will help developers work with HTML in their Views. These helper methods are primarily Extension Methods, and are designed to encapsulate UI code in much the same way that Server Controls do with Web Forms.

Wednesday, December 05, 2007

For the last month or so I've been working on the MVC UI Helpers (aka the MVC Toolkit) that will help developers work with HTML in their Views. These helper methods are primarily Extension Methods, and are designed to encapsulate UI code in much the same way that Server Controls do with Web Forms.

   

It's All Extension Methods Baby
When you create a View using ASP.NET MVC, you set it to inherit from System.Web.Mvc.ViewPage<>, where the passed-in type is a data class shared between the Controller and ViewPage (read more on this here). At that point it's all up the UI (the HTML View), and we haven't forgotten you :). To that end we've created a set of Extension Methods, currently called the "MVC Tookit", that you can use to push the data from your controller to your screen, wrapped in some nice HTML controls.

The UI Helper library (currently called System.Web.Mvc.Toolkit) extends the HtmlHelper class, which hangs from ViewPage.Html. When you download the MVC bits (later this week), in there will be a binary file which you can add to your project in order to use the new UI bits (this stuff is slated to be combined with the core MVC bits in the next drop). To use it, you simply reference the Toolkit dll, and then in your Web.Config, add a reference to the namespace:

<pages>
    ...
    <namespaces>
        <add namespace="System.Web.Mvc"/>
    </namespaces>
</pages>

Now you're ready to rock!

   

Enough Chatter - Get To The Code!
Accessing the helpers from your view is pretty straightforward once you have the namespace available to your ViewPage:

As you can see here, there are an abundance of methods for you to choose from - I'll go over each one here, and show some examples of each. You asked for more code... you got it!

First, however, you might be asking:

If I can't use server controls, and there's no PostBack, why then can't I just use plain old HTML?

... and the answer is that you can. It's up to you as to what you think is more maintainable and easier to work with.

For the samples below, I'll be working with a sample Forums application for context.

   

Anonymous Hash (Queue Midnight Run Soundtrack)
When looking over the Toolkit code you'll see a lot of "object htmlAttributes" as an argument in the method signatures. We have a nice hashing system we're using which allows you to pass in things we haven't thought of in terms of tag attributes. This system works on the concept of Anonymous Types - the ability to declare, as needed, an object type:

object o=new{name="Rob", type="quack"}

We have an Extension Method (which you can use too!) called "ToAttributeList()", which will transform this object into a set of attrbute values:

//This evaluates to "name=\"Rob\" type=\"quack\" "

string myList=o.ToAttributeList()

So with all of the methods below, you can use htmlAttributes to send in whatever extra tags you like using the Anonymous Type declaration.

Note: if your tag is a reserved work, like "class", use the standard "_" reserved word prefix: "_class"

   

User Controls
The first helper method I want to show off is the RenderUserControl() method. This method allows you to dynamically call/render a UserControl to a page as a string. These controls can be simple standalones, or they can share the ViewData with the controller. So to render a basic UserControl, we use:

<%=Html.RenderUserControl("~/UserControls/ForumList.ascx")%>

This will output the rendered control to the page, right where I put the call. But what if there are properties set on the ForumList? Like ForumGroupID for instance (which tells the ForumList.ascx which forums to display)? We can handle that too by using an Anonymous Type, sent in as a Hash, which will apply each setting to the UserControl:

<%=Html.RenderUserControl("~/UserControls/ForumList.ascx", new{GroupID=2})%>

If the UserControl is typed (ViewUserControl<MyControllerData>) then the ViewData from the controller will be passed down to the control.

To take it one step farther, let's pretend we're building a Forums application and we want to create a skinning engine which applies certain styles (or "skins") to our application based on a setting somewhere and for this we've decided to leverage UserControls.

Normally we'd have to jump through some hoops (small ones) with the BuildManager and some reflection to get this to work properly (note that that since we're not using Server Controls, we also can't use the ASP.NET Skinning Engine).

With MVC we simply setup a Themes folder, and inside of that put our Theme directories. We can then define a set of user controls for each "skin" or Theme, and then call them as needed, based on the current theme. But how do we know what that theme is? And how do we call it?

Since we don't want all this logic in our UI (deciding on which theme and how to call it), we create a Helper Class that will decide for us what theme we're using. Helpers are essentially static classes, designed to contain the UI logic that otherwise clutters up your UI. Think of these as UI utilities.

Since Theme logic is application-wide, I'm going to create an AppHelper class (as opposed to a helper specific to my controller), and put it in my Helpers folder, using the Global namespace. In here I can now put shared View Logic:

And now I can create a method to help me decide which themed control to use. I'll call it GetThemedControl():

/// <summary>

/// Gets the root of the site we're working with

/// </summary>

/// <returns></returns>

public static string GetSiteRoot() {

 

string appPath = System.Web.HttpContext.Current.Request.ApplicationPath;

if (appPath == string.Empty)

appPath = "/";

 

return appPath;

}

/// <summary>

/// Gets a user control based on the current theme

/// </summary>

/// <param name="controlName">The name of the control</param>

/// <returns></returns>

public static string GetThemedControl(string controlName) {

string appPath = GetSiteRoot();

if (!controlName.EndsWith(".ascx"))

controlName += ".ascx";

 

//all themes are kept in ~/Themes/ThemeNAME

string result = appPath+"Themes/" + GetTheme() + "/" + controlName;

return result;

}

One thing you'll notice here is that I can no longer call "Page.ResolveClientUrl()" because, well, we have no Page! I'll show you below how you can get around that with our LinkExtensions class.

The GetTheme() method above can do something as simple as check the Web.Config's appSettings, or it can shoot to the DB to see which theme the user likes - this parts up to you.

So using GetThemedControl(), I can now rewrite the call to be:

<%=Html.RenderUserControl(AppHelper.GetThemedControl("ForumList"),new {GroupID=2})%>

Nice and tight :).

   

Forms
Working with forms takes on a whole new meaning with ASP.NET MVC since we are no longer bound to one form per page. For those of you who have used Web Forms almost explicitly, this might come as a bit of a Strange New Thing.

You can work with many forms on a page - there is no limit - and often it's nice to be able to split things up like this. Each form submits itself to a Controller/Action, and that action is responsible for doing whatever needs done.

The toolkit allows you to create forms in a lot of ways, including the most transparent way (using our Url helper):

<form action="<%=Url.Action(new{controller="Home", action="Index"})%> method=post>

If all of the "new{thing=1}" code is freaking you out - this is new to C# 3.5 and it's anonymous typing. Basically when you see this, know that in the background we're setting properties based on what you send in. This is typical in dynamic languages like Ruby, and you'll see this a lot in the code below (specifically when creating HTML attributes for HTML tags).

The <form> tag above works fine, but it's a tad verbose. It's also worth mentioning at this point that

All you know and think about URLs and ASP.NET is out the window. URLs no longer route to a physical file - they are (essentially) Remote Procedure Calls. Given that, you generally don't want to "hard-code" URLs into a page since it makes your site pretty brittle. Use ViewPage.Url to resolve the URL for you.

You can set routes to your controllers as you see fit, and it's very customizable. You're no longer constrained to folder structure so keep that in mind as you work with MVC - you may decide to change your routes as you develop your application - this might very well break your links if you don't use our helpers (or some of your own).

You can also use a nice, type-safe way to create a form (this was Phil's brain child):

<%using(Html.Form<HomeController>(action=>action.Index()))}%>

...

<%}%>

This is a nice way to create a form control since you can work with intellisense, and have type-safety associated with your form tag. It's also nice because you get a compiler error if you don't close off your Form tag :).

If you don't like all that code, you can also do this:

<%using(Html.Form("Home","Index"))%>

...

<%}%>

If you want to use GET, you can (for either methods):

<%using(Html.Form("Home","Index"), FormExtensions.FormMethod.get)%>

...

<%}%>

To submit the form, you can use:

<%=Html.Submit()%>

or

<%=Html.Submit("Save")%>

or use an image

<%=Html.SubmitImage("~/Images/SaveButton.gif")%>

   

Using Form Data In Your Controller
Once you post your form data back, we have a helper that you can use to gather it from Request.Form. There are two such methods:

Object.UpdateFrom(Request.Form)

and

Controller.ReadFromRequest(string key)

UpdateFrom basically introspects your object and then tries to match your object's properties to the keys passed in from Request.Form - in other words "auto-binding" it. So if you're working with the Northwind.Product class (using any object type - it doesn't matter), you could use:

Product p=new Product();

p.UpdateFrom(Request.Form);

This will bind your object to the values passed-in on the form. If there is a type-conversion error (or other error), we wait until the end of the method, and then throw a PopulateTypeException. This exception gathers all the exceptions into a collection for you to evaluate in your code. The important thing here is that if there is an error - the binding doesn't stop, it continues to "do it's best" and then lets you know there was a problem.

Currently we support 3 naming conventions (i.e. the name for your controls in your HTML page) that UpdateFrom() uses to "sniff out" the passed-in form values for binding:

  • Property Name ("ProductName")
  • Object.PropertyName("Product.ProductName")
  • Object_PropertyName("Product_PropertyName")

Controller.ReadFromRequest() is another extension method that you can call in your controller to pull a value that has been passed in using HTTP GET or POST (or the QueryString):

string myName=this.ReadFromRequest("name");

   

Select, ListBox, CheckBoxList, RadioButtonList
We very much wanted to create an experience with these methods much like you had with their Web Form counterparts.

Each control works in much the same way: you specify a name, a data source, selected values, etc. The dataSource, currently, can be:

  • IEnumerable
  • DataSet
  • DataTable
  • IQueryable (Linq)
  • IDataReader

For CheckBoxList and ListBox, the selectedValues parameter is also IEnumerable.

Samples:

<%

//Sample Data

string [] songs=new string[]{"Robot Rock (Daft Punk)","Stairway to Heaven (Zeppeling)",

"New Slang (Shins)"};

string [] movies=new string[]{"Tron","Big Trouble In Little China",

"Say Anything"};

string [] zodiac =new string[]{"Aries", "Taurus","Gemini","Cancer","Leo",

"Virgo","Libra","Scorpio","Sag","Capricorn","Aquarius","Haack"};

%>

Sign:<br />

<%=Html.Select("myZodiac",zodiac) %><br />

 

Sign (select Haacked):<br />

<%=Html.Select("myZodiac",zodiac,"Haacked") %><br />

 

 

Favorite Movie:<br />

<%=Html.CheckBoxList("favMovie",movies).ToFormattedList("<li>{0}</li>") %>

<br />

 

Favorite Movie, List :<br />

<%=Html.ListBox("favMovie",movies,new string[]{"Say Anything"}) %>

<br />

 

Favorite Movie, List, Long, Mult (select "Say Anything" and "Tron")i:<br />

<%=Html.ListBox("favMovie",movies,20,true,new string[]{"Say Anything", "Tron"}) %>

<br />

 

Favorite Songs (Select Shins):<br />

<%=Html.CheckBoxList("favSongs",songs,new string[]{"New Slang (Shins)"})

.ToFormattedList("<li>{0}</li>") %>

<br />

 

Favorite Songs:<br />

<%=Html.CheckBoxList("favSongs", songs).ToFormattedList("<li>{0}</li>")%>

<br />

 

Favorite Songs, Radio:<br />

<%=Html.RadioButtonList("favSongs", songs,"Robot Rock (Daft Punk)")

.ToFormattedList("<li>{0}</li>")%>

<br />

One super-groovy thing to note here is how CheckBoxList() calls "ToFormattedList()". This is another Extension Method that hangs off of "IEnumerable" and allows you to enumerate the values to a list.

CheckBoxList and RadioButtonList return String[] - not strings! Each string is a single <checkbox> or <radio> tag.

The reason we did it this way was to allow you as much freedom as possible in terms of laying out your page, but if you don't want to write a foreach loop each time, we included the ToFormattedList() method to make things easier.

   

TextBox, TextArea, Password, Hiddens
These methods work in the same way as above. Here are some samples:

Name:<br />

<%=Html.TextBox("txtName",20) %><br />

Name, with maxlength:<br />

<%=Html.TextBox("txtName","My Value",20,20) %><br />

 

Thoughts:<br />

<%=Html.TextArea("txtBlob","Lorem Ipsum la la la") %><br />

 

Thoughts, with maxlength, rows, cols:<br />

<%=Html.TextArea("txtBlob","Lorem Ipsum la la la",20,10,40) %><br />

 

Password<br />

<%=Html.Password("myPassword",50)%><br />

With size, value

<%=Html.Password("myPassword",50,"My Password")%><br />

With size, value, style attribute

<%=Html.Password("myPassword", 50,"",new { style = "width:100px" })%><br />

Links, Buttons, and Navigation
We augmented the Url.Action() method to include a nice, type-safe way of navigating between controllers and actions on your site:

<%=Html.ActionLink<HomeController>(x=>x.Index(),"Home, using Action<T>") %>

Notice that in the linkText argument (second position, after the Lambda) that I'm outputting <T>? It's worth mentioning that we scrub the settable text bits using Html.Encode (another extension method).

You can also navigate between controllers using Button<>():

<%=Html.Button<HomeController>(x=>x.Index(),"cmdNav2","Home") %>

You can also navigate around the internets using NavigateButton():

<%=Html.NavigateButton("cmdNav","GoTo MSN","http://www.msn.com") %>

If you have some custom javascript to run, you can do that with Button():

<%=Html.Button("cmdJS","Click Me","DoTheClickThang()")%>

If you like using Images as buttons, you can do that too, using ImageButton():

<%=Html.Button("cmdJS","~/Images/Clicky.png","DoTheClickThang()")%>

Note: with this method we make sure the cursor hand appears when hovering to denote a clickable element.

   

Images, ResolveUrl, and MailTo
We really want to make things as easy as can be for you with the new MVC Toolkit. So we've also thrown in an Image method:

A nice picture of a wave:

<%=Html.Image("~/Images/bigwave.jpg") %><br />

 

Set the name and width

<%=Html.Image("~/Images/bigwave.jpg", "myWave", new { width = "30px" })%><br />

Since you're ViewPage no longer has access to Page proper, we've included a method to help you resolve URLs on your page:

<%=Html.ResolveUrl("~/HALP!")%>

If you want to embed an email link, you can do so using MailTo():

Simple Email:

<%=Html.MailTo("robcon@microsoft.com","Email Me!") %>

 

With Subject and Body

<%=Html.MailTo("robcon@microsoft.com","Email Me!","Sending you a note"

,"Hey - wanted to say hi!") %>

MailTo() contains all the overloads needed to send subject, body, cc, bcc, to the client's email program.

   

Summary
Long, long post - but I thought it was worth it to get as much out there as possible. The CTP will be landing very soon, and with it will be the MVC Toolkit. We've tried to pack as much UI help in there as possible - and please know that these things will likely change as we keep building and tweaking.

Operation aborted (Exception from HRESULT: 80004004 (EABORT))

Developing customizations over WSS 3.0 (or MOSS 2007) with the server object model exposed by SharePoint, mostly in a test environment, we find out this error message:

 

Operation aborted (Exception from HRESULT: 0×80004004 (E_ABORT))

System.Runtime.InteropServices.COMException : Operation aborted (Exception from HRESULT: 0×80004004 (E_ABORT))
at Microsoft.SharePoint.Library.SPRequestInternalClass.UpdateRoleAssignment(String bstrUrl, Guid& pguidScopeId, Int32 lPrincipalID, Object& pvarArrIdRolesToAdd, Object& pvarArrIdRolesToRemove)
at Microsoft.SharePoint.Library.SPRequest.UpdateRoleAssignment(String bstrUrl, Guid& pguidScopeId, Int32 lPrincipalID, Object& pvarArrIdRolesToAdd, Object& pvarArrIdRolesToRemove)

 

In this specific case, we have this error when we tried to update the permissions of a SharePoint object or when we tried to break its permission inheritance. In other cases, we can find out this error on every update that we do over the SharePoint content database.
For this error, there's three main causes:

  • the log database related to the SharePoint content database is full
  • there's no more available space on the disk
  • the user which access to the content database hasn't correct permissions on it

Our was the first case, so we simply backup the content database and the log avaiable space grows automatically.

Hope this helps.

Automatically applying a My Site master page to a site when it is created

Automatically applying a My Site master page to a site when it is created

I wanted to create own customized My Site. By default My Sites is created on default.master page. Even though sharepoint admin try to change the default.master page, he found that it is not inherit from the Portal Home.

What is the best approach to customize?

You have to modify the default.aspx file in SPSPers to use Custom.Master page to get the My Profile view to use a single master page; it is not inherited from the Portal home.  There are only 2 settings, default.master or custom.master.

You need to create a new master page and place it in the SPSPers directory and then modify the ONET.XML by adding a reference in the configuration to use your page

Step 1 – Create My Site Template

1.       Create a My Site using any account

2.       Make myMaster.master using default.master, which is located under _catalogs/masterpage

3.       Customize U/I using copied master page

4.       Copy this myMaster.master into C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12TEMPLATEGLOBAL

Step 2 – Customize  default.aspx

1.       Change directory to C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12TEMPLATESiteTemplatesSPSPERS

2.       Open default.aspx using Sharepoint Designer 2007

3.       Change master page like shown below

From `MasterPageFile="~masterurl/default.master"'      to `MasterPageFile="~masterurl/custom.master" `    

Step 3 – Customize  ONET.XML

<Configuration ID="0" Name="Default" CustomMasterUrl="_catalogs/masterpage/myMaster.master">

Add a new module

<Module Name="CustomMasterPage" />

and in the modules section, add

<Module Name="CustomMasterPage" List="116" Url="_catalogs/masterpage" RootWebOnly="FALSE">

      <File Url="MyMaster.master" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />

    </Module>

Step 4 – Reset IIS

For the changes to take affect, you will need to reset the IIS.    

   

example ONET.XML

<?xml version="1.0" encoding="utf-8" ?>       
<Project Revision="3" SiteLogoUrl="/_layouts/images/mysite_titlegraphic.gif">
    <NavBars>  
    </NavBars>

    <ListTemplates>
    </ListTemplates>

    <DocumentTemplates>     

    </DocumentTemplates>

 <Configurations>
    <Configuration ID="-1" Name="NewWeb">

</Configuration>  

    <Configuration ID="0" Name="Default" CustomMasterUrl="_catalogs/masterpage/myMaster.master">            
 </Configuration>
             
 <Configuration ID="1" Name="Blank">
        <ExecuteUrl Url="_layouts/[%=System.Threading.Thread.CurrentThread.CurrentUICulture.LCID%]/settings.aspx" /> </Configurations>
 <Modules>
     <Module Name="Default" Url="" Path="">
       </Module>
     <Module Name="CustomMasterPage" List="116" Url="_catalogs/masterpage" RootWebOnly="FALSE" SetupPath="global">
      <File Url="myMaster.master" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE" />
    </Module>

  </Modules>
</Project>

Forms Authentication Across Applications

ASP.NET supports forms authentication in a distributed environment, either across applications on a single server or in a Web farm. When forms authentication is enabled across multiple ASP.NET applications, users are not required to re-authenticate when switching between the applications.

Configuring Forms Authentication Across Applications
To configure forms authentication across applications, you set attributes of the forms and machineKey sections of the Web.config file to the same values for all applications that are participating in shared forms authentication.

The following example shows the Authentication section of a Web.config file. Unless otherwise noted, the name, protection, path, validationKey, validation, decryptionKey, and decryption attributes must be identical across all applications. Similarly, the encryption and validation key values and the encryption scheme and validation scheme used for authentication tickets (cookie data) must be the same. If the settings do not match, authentication tickets cannot be shared.

Note:
Applications that run ASP.NET version 2.0 or later can share forms authentication ticket information with earlier versions of ASP.NET if you include decryption="3DES" in the machineKey element for each ASP.NET version 2.0 (or later) application.
 
  Copy Code
<configuration>
  <system.web>
    <authentication mode="Forms" >
      <!-- The name, protection, and path attributes must match
           exactly in each Web.config file. -->
      <forms loginUrl="login.aspx"
        name=".ASPXFORMSAUTH"
        protection="All" 
        path="/"
        timeout="30" />
    </authentication>

    <!-- Validation and decryption keys must exactly match and cannot
         be set to "AutoGenerate". The validation and decryption
         algorithms must also be the same. -->
    <machineKey
      validationKey="C50B3C89CB21F4F1422FF158A5B42D0E8DB8CB5CD

A1742572A487D9401E3400267682B202B746511891C1BAF47F

8D25C07F6C39A104696DB51F17C529AD3CABE"
      decryptionKey="8A9BE8FD67AF6979E7D20198CFEA50DD3D3799C77AF2B72F"
      validation="SHA1" />
  </system.web>
</configuration>
 

After an authentication ticket (cookie) has been issued, expiration of the cookie is tracked based on the Expires value in the cookie itself. If two applications have different Timeout attributes, the expiration date and original timestamp are retained through each cookie's lifetime. When a cookie is updated, the cookie's original expiration is used to compute the new expiration. The only time that the configuration Timeout value is used is when the cookie is initially created.

Forms Authentication and the Authentication Service
You can also authenticate users across applications by using the authentication service. The authentication service enables you to use forms authentication from any application that can send and consume messages in SOAP format. For more information, see Windows Communication Foundation Authentication Service Overview.

How to config form authentication in SharePoint & MOSS 2007

Forms Authentication in SharePoint Products and Technologies (Part 1): Introduction

Summary: Explore several new features for authentication and authorization in Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0 that make it easier to develop and deploy solutions in Internet-facing and extranet environments. This article is part 1 of 3. (26 printed pages)

Steve Peschka, Microsoft Corporation

Published: December 2007

Updated: June 2009

Applies to: Microsoft Office SharePoint Server 2007, Windows SharePoint Services 3.0

Contents

Read part 2 and part 3:

Forms Authentication in SharePoint Products and Technologies (Part 2): Membership and Role Provider Samples

Forms Authentication in SharePoint Products and Technologies (Part 3): Forms Authentication vs. Windows Authentication

Introduction to Forms Authentication in SharePoint Products and Technologies

Microsoft Office SharePoint Server 2007 and Windows SharePoint Services 3.0 (in this article series, collectively referred to as SharePoint Products and Technologies) contain several new features for authentication and authorization that help to make it easier for you to develop and deploy solutions in Internet-facing—and especially extranet—environments. In earlier SharePoint versions, at some point all security principals needed to resolve to a Windows identity—either a user account or group.

Office SharePoint Server 2007 and Windows SharePoint Services 3.0 are built upon the ASP.NET 2.0 Framework, which allows you to use forms authentication to authenticate users into the system. Because SharePoint Products and Technologies are built upon the ASP.NET 2.0 pluggable authentication provider model, they can now support authentication for users stored in Active Directory, a Microsoft SQL Server database, in an LDAP directory, or in any other directory that has an ASP.NET 2.0 membership provider. Although Windows SharePoint Services 3.0 does not provide any default membership providers, Office SharePoint Server 2007 does provide a built-in LDAP V3 membership and role provider, and ASP.NET 2.0 includes a SQL Server membership and role provider. However, if you want to use a directory and cannot find a membership provider for it, you can write your own! This is a key technology enabler for heterogeneous environments.

Important:

When you use forms authentication, client integration is disabled by default because client integration does not natively support forms authentication. You might be able to use many client integration features with forms authentication, and there are workarounds available to implement varying levels of client integration functionality with forms authentication. Specifically, starting in the Office 2007 Cumulative Update for April 2009 (Microsoft Help and Support), Microsoft Office Word, Microsoft Office Excel, Microsoft Office PowerPoint, and Microsoft Office SharePoint Designer all have native support for forms authentication, as described in Forms Authentication in SharePoint Products and Technologies (Part 3): Forms Authentication vs. Windows Authentication. If you plan to use client integration with forms authentication, you must fully test any available solutions or workarounds to determine whether the performance and functionality are acceptable in your environment. Microsoft Customer Support can provide commercially reasonable support to help you troubleshoot published workarounds.

Deciding to Use Forms Authentication

Some organizations want to use Windows users and groups in SharePoint Products and Technologies, but enter credentials via forms authentication. Before using forms authentication, determine why to use forms authentication in the first place: What is the business driver? If user accounts are stored in a location other than an Active Directory domain controller, or if Active Directory is not available in a particular environment, using forms authentication with a membership provider is a good choice. But if you want to force logon only via forms authentication, but still use Windows and all of the integrated features it provides, you should consider an alternative such as publishing the SharePoint site with Microsoft Internet Security and Acceleration (ISA) Server 2006. ISA Server 2006 allows users to log on by using a forms authentication Web form, but treats them like Windows users after authentication. This implementation provides a more consistent and compelling experience for end users.

Reviewing a Typical Scenario for Authentication

A very common scenario is one in which you have an existing intranet SharePoint site, and the Web application that hosts the site is configured to use Windows authentication. Users log on to corporate desktops and can navigate seamlessly to the SharePoint site by using their logon credentials.

The organization now decides to make this site available on the extranet. Such availability can allow external partners to access and share the content. The organization should not have to duplicate the content between the internal and external sites, and managing both internal and external users' access rights should occur exclusively in the intranet. To accomplish this, user accounts and groups for external users are stored in a SQL Server database. The zone uses the SQL membership and role providers that are included with the Microsoft .NET Framework 2.0.

The rest of this article describes how to configure SharePoint Products and Technologies in this scenario.

Reviewing Changes to Authentication Terminology

Several new features in Office SharePoint Server 2007 and Windows SharePoint Services 3.0 are used to create and configure forms authentication access to a site. In addition, some concepts from SharePoint Products and Technologies 2003 are changed or are renamed. Following are several important definitions to understand when configuring forms authentication in Office SharePoint Server 2007 or Windows SharePoint Services 3.0.

Web Application

Referred to as a virtual server in the previous version of SharePoint Products and Technologies, a virtual server is now a Web application. When a Web application is created, it maps a set of properties, such as the load-balanced URL and the authentication method that will be used, to its Default zone.

Zone

A zone is a way to map multiple Web application configuration settings to a single set of content databases. For example, you can create a Web application, create a content database, and then configure the database to use Windows authentication. All of these settings are configured for the Default zone for the Web application. You can then extend the Web application and map it to a new zone. When you do that, you select a zone to map to, such as Intranet, Internet, Custom, or Extranet. When you configure the second zone, you select an existing or new Internet Information Services (IIS) virtual server and a new load-balanced URL, and determine whether to use NTLM or Kerberos authentication. You can change the authentication provider, for example, to forms authentication, after the new zone is created.

Policy

A policy—useful in many scenarios including when you are configuring a Web application for forms authentication—allows you to grant full access, grant read-only access, deny write access, or deny all access to a user or group on a Web application. This policy grant applies to all sites in the Web application, and it overrides any permissions that are established within individual sites, lists, or items.

Alternate Access Mapping

Alternate access mapping (AAM) is a way to define the different URLs that are associated with a Web application and its set of content databases. It effectively manages the zone relationships described earlier. It also lets you map between internal URLs, such as those a load balancer might use, and the external URLs that users see.

In the earlier versions of SharePoint Products and Technologies, it was less important in an extranet scenario to create an AAM because SharePoint Products and Technologies would get the virtual server and host name information from IIS. In Office SharePoint Server 2007 and Windows SharePoint Services 3.0, you must use AAM or things just will not function correctly.

Authentication Provider

By default, Office SharePoint Server 2007 and Windows SharePoint Services 3.0 use Windows as the authentication provider for new zones. As described earlier, SharePoint Products and Technologies can also use the ASP.NET 2.0 pluggable authentication provider model for the membership provider interface. In addition, SharePoint Products and Technologies also support the role provider interface, which enables you to surface attributes such as group membership about your users. If you are accessing your SharePoint site with forms authentication, you need a membership provider at a minimum. A role provider is optional, but typically quite useful so that you can provision permissions to groups of users, rather than having to add each user to a SharePoint Group.

Setting Up Forms Authentication

Now that we have defined the basic scenario and terminology, we can step through how to configure forms authentication. We make the following assumptions:

  • We created a Web application and the Default zone is using the load balanced URL http://contoso.
  • SQL Server is installed in the extranet on a server named spdb. The SQL membership and role provider are used with this database server.
  • We access the external site at http://www.contoso.com.

Note:

If you are using Office SharePoint Server or Windows SharePoint Services in the extranet for collaboration, you should do so securely over Secure Sockets Layer (SSL). In this case, your external site is located at https://www.contoso.com. We are excluding that step here only to simplify and focus on the processes we are addressing in this article. In a true production environment, excluding that step would not be acceptable.

Extending the Existing Web Application

The existing Web application is located at http://contoso, and is secured with Windows authentication in the Default zone. It resembles Figure 1.



Figure 1. Contoso Portal Web application

To extend the existing Web application into a new zone

  1. Open your browser and navigate to the Central Administration Web site.
  2. Click the Application Management tab, and then click Create or extend Web application.
  3. Click Extend an existing Web application to open the Extend Web Application to Another IIS Web Site page. To select the Web site you are extending, in the Web Application list, click Change Web Application. In this case it is the Contoso Web application.



    Figure 2. Select Web application list

  4. In the dialog box, click the link for the Contoso Web application to select it.
  5. In our scenario, we want to extend the Web application by using the name www.contoso.com. To enable this, create an IIS Web site and configure the Port to 80, and configure the Host Header to www.contoso.com.



    Figure 3. Create IIS Web site

  6. For default provider, click NTLM. We change this in a later step.
  7. Retain the default selections for anonymous users and SSL. As mentioned earlier, in a true production environment you would choose to enable SSL for an external site.
  8. In the Load Balanced URL section, remove the ":80" from the end of the URL, so that the load-balanced URL is http://www.contoso.com.
  9. In the Zone list, click Extranet, and then click OK to save your changes and extend the Web application.



    Figure 4. Zone list

Managing Users and Roles

After you extend the Web application, you must create the database that will store user names and roles. In this case, there is a database in the perimeter network for this purpose named spdb. We will use the ASP.NET membership and role provider to authenticate users and determine their group memberships, so we must create the ASP.NET membership database.

To create the ASP.NET membership database

  1. On the spdb server, open Windows Explorer.
  2. Navigate to the path %System Drive%\Windows\Microsoft.NET\Framework\v2.0.50727.
  3. To start the ASP.NET SQL Server Setup Wizard, double-click aspnet_regsql.exe.
  4. Start the wizard by clicking Next, and then complete the wizard as shown in Figures 5-9.



    Figure 5. ASP.NET SQL Server Setup Wizard

  5. Click Configure SQL Server for application services, and then click Next.



    Figure 6. Select a Setup Option page

  6. In the Server box, type spdb for the database name, and then click Next.



    Figure 7. Select the Server and Database page

  7. Confirm that the data you typed is correct, and then click Next.



    Figure 8. Confirm Your Settings page

  8. The database is created and the final status information is displayed. Click Finish to complete the wizard.



    Figure 9. ASP.NET SQL Server Setup Wizard completion status

To perform actual tasks such as creating users and groups and managing passwords, you need a tool to manage that information. Unfortunately, few existing tools are available to help you. The membership and role provider APIs are fairly rich, however, and you can create both Web-based and Windows-based tools for this task.

For this article, we wrote a tool named MembershipSeeder that demonstrates how to use these APIs in a Windows-based application. The tool and source code are available on CodePlex from the Forms Based Authentication (FBA)page. You can use the MembershipSeeder tool as is for simple user and role management, or you can use the source code as a base on which to create your own tool; however, Microsoft does not provide support for this tool.

To run the MembershipSeeder tool

  1. Start the MembershipSeeder tool.
  2. Click Configure.
  3. In the dialog box that opens, type the name of the computer running SQL Server that hosts your SQL membership database.
  4. Save your changes, and then restart MembershipSeeder so that it will use the new server name.

To create users for testing purposes

  1. In the User Prefix field, type a value.
  2. In the Password field, type the password you want each user to have.
  3. In the # of Users field, select the number of users to create.
  4. Click Create to create users where the user name is the value of the User Prefix field with an incrementing number added to the end.

    For example, if the User Prefix field is user and # of Users is 2, two users are created and named user1 and user2. To add only a single user and not add the numeric value to the end of the user name, select Only create or delete 1 user; don't use the # of Users field check box. Deleting users works similarly to creating users.



    Figure 10. Create users

  5. To open a dialog box with a list of all roles that the tool is aware of, click Get Roles, as a shown in Figure 11.



    Figure 11. Get Roles

  6. To add a new role, type a name for the role in the Role field, and then click Create.
  7. To add users to a role, type the role name in the Role field.

You can add multiple test users to the role and then provide the user credentials with the User Prefix and # of Users fields, just as you created users. The Start Num field is designed to let you add a subset of those users. For example, suppose you created user1 through user50. You created a role named Authors, and you want to add users 5 through 15 to that role. To do this, you type Authors in the Role field, set # of Users to 10 and set Start Num at 5. When you click Add to Role, the users are added to the Authors role.

Also, similar to the process for creating and deleting users, if you want to add only a single user to a role and not a group of users, select the Only add 1 user; don't use the # of Users field check box.

To see all of the users in a role, type the role name in the Role field, and then click Get Users. This displays a dialog box that contains all the users found in that role, as shown in Figure 12.



Figure 12. Get users for role

By default, the MembershipSeeder tool is configured to use the SQL membership and role provider. However, you can manually edit the MembershipSeeder.exe.config file to change providers. As long as the provider implements the interfaces for managing users and groups that the tool uses, you can easily change providers in the .config file and continue to use the tool. If you are using the SQL membership and role provider, there is also another tool available on CodePlex that is useful for some of these account management tasks. You can read about it on the Microsoft SharePoint Products and Technologies Team Blog. For a description of the tool that can be used to add, edit, and delete users, see the Features for Administration section.

Now that you know the basics of working with the tool, we create the users and groups to use to test the forms authentication implementation.

To create a batch of users for testing purposes

  1. Create a batch of 20 users: user1 through user20.
  2. Create two roles: Admins and Readers.
  3. Add user1 through user3 to the Admins role.
  4. Add user1 through user20 to the Readers role.

Configuring web.config Files

At this point, we have two zones mapped to the Web application, and both are configured to use Windows authentication. The database to store users and roles is created, and it is populated with some sample data to test the forms authentication implementation. The next step is to configure the web.config file for several of the Web applications in the farm to support the forms authentication membership and role providers.

To configure the web.config file for the new zone

  1. Find the correct web.config file.

    When the Web application was extended into the new zone, a directory was created on the SharePoint server that contains files it uses, including web.config. By default, that directory is located in the path %SystemDrive%\Inetpub\wwwroot\wss\VirtualDirectories\zone name. So in our current example, the directory is located at C:\Inetpub\wwwroot\wss\VirtualDirectories\www.contoso.com80.

  2. Open Windows Explorer and navigate to the directory that contains the web.config file for the new zone.
  3. Open the file in a text editor such as Notepad. We need to make four entries: a PeoplePicker wildcard, a connection string, a membership provider, and a role provider.

    The entry for the PeoplePicker wildcard tells the PeoplePicker component in Office SharePoint Server or Windows SharePoint Services the character to use to do a wildcard search for an individual user. For the SQL membership provider, it supports the percent sign (%) as a wildcard character.

  4. In your text editor, search for the string "PeoplePickerWildcards". That should take you to a section of the web.config file that looks like the following code.

    XML

    Copy

    <PeoplePickerWildcards>

    <clear />

    <add key="AspNetSqlMembershipProvider" value="%" />

    </PeoplePickerWildcards>

To simplify the example in this article and prevent interference with any of the built-in settings, we will name our membership provider fbaMembers and our role provider fbaRoles. To associate the wildcard search character with our membership provider, we use the fbaMembers name when adding the add subelement to the PeoplePickerWildcards element. After it is added, the PeoplePickerWildcards element looks like the following code.

XML

Copy

<PeoplePickerWildcards>

<clear />

<add key="AspNetSqlMembershipProvider" value="%" />

<add key="fbaMembers" value="%" />

</PeoplePickerWildcards>

In the connectionString element, you define the connection string that the membership and role providers use to connect to their data store. The connectionStrings element does not exist by default when you extend a Web application. You need to create it, and then create the individual connectionString element under it.

The connectionStrings element can go directly above the system.web element in the web.config file.

To define the connection string

  1. In your text editor, search for the string "<system.web>", which takes you to the opening tag for the system.web element.
  2. Directly above this tag, add an empty connectionStrings element, which looks like the following code.

    XML

    Copy

    <connectionStrings>

    </connectionStrings>

  3. Add a subelement add that has a name attribute, which is the name for the connection string, and a value attribute, which is the actual connection string. In this example, we assume that the default Windows authentication is being used on a computer running SQL Server. The database name is spdb, so after the connection string is added, the entire connectionStrings element looks like the following code.

    XML

    Copy

    <connectionStrings>

    <add name="fbaSQL"

    connectionString="server=spdb;database=aspnetdb;Trusted_Connection=true" />

    </connectionStrings>

Note:

The application pool account or accounts for any Web applications that use this provider must have at least Read rights to all of the objects in the aspnetdb database specified in the connection string.

The membership and role provider information, which you can add at the same time, must be a subelement to the system.web element. The membership and role provider elements resemble the following code. Important attributes are described following the example.

XML

Copy

<membership defaultProvider="fbaMembers">

<providers>

<add connectionStringName="fbaSQL" applicationName="/"

name="fbaMembers"

type="System.Web.Security.SqlMembershipProvider, System.Web,

Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

</providers>

</membership>

<roleManager enabled="true" defaultProvider="fbaRoles">

<providers>

<add connectionStringName="fbaSQL" applicationName="/"

name="fbaRoles" type="System.Web.Security.SqlRoleProvider, System.Web,

Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>

</providers>

</roleManager>

Important Attributes for the Providers

Following are descriptions of the important attributes for providers, shown in the previous code example.

  • defaultProvider   In the Membership and roleManager elements, this is the name of the provider to use by default for this Web application. The name you provide here should be the same as the name attribute for the provider.
  • connectionStringName   In the providers subelement for an individual membership or role provider, this is the name of the connectionString element that contains the connection string the provider uses to communicate with the data store.
  • name   In the providers subelement for an individual membership or role provider, this is the name that is used to refer to the provider. It is used in the defaultProvider attribute, and in the SharePoint Central Administration Web site on the Policy configuration page.
  • type   In the providers subelement for an individual membership or role provider, this describes the Microsoft .NET Framework class type and strong name that implements the membership or role provider. The previous examples include the type for the ASP.NET SQL membership and role provider; if you were using a different provider, you would enter the type name for it in this attribute.

This completes the configuration changes needed for the new zone's web.config file. Changes to the other web.config files are almost identical to these changes; however, other web.config files may have some of the parent elements already present, such as the connectionStrings element.

Configure Central Administration and Existing Windows Authentication Web Application web.config Files

For the Central Administration and existing Windows authentication Web application web.config files, you make the same changes as described previously for the forms authentication zone's web.config file—with one exception. In the defaultProvider attribute for the roleManager element, the name should be AspNetWindowsTokenRoleProvider instead of fbaRoles. It looks like the following code example.

XML

Copy

<roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">

The reason the default provider is different from the forms authentication zone is that the default role information for these Web applications is provided by Windows. That is important for Office SharePoint Server 2007 and Windows SharePoint Services to know when trying to determine what groups an individual user belongs to. The default membership provider does not need to be changed in the same way because authentication is managed by IIS; SharePoint Products and Technologies recognize that the site is using Windows authentication.

Note:

If you have multiple front-end Web servers, you must make these changes to the web.config files on each server.

Configuring the Zone's Provider

You must configure the zone's Provider information to use forms authentication with the membership and role provider that was added to the web.config files.

To configure the zone's provider

  1. Open your browser and navigate to the Central Administration Web site.
  2. Click the Application Management tab.
  3. Click Authentication providers.
  4. Ensure that the correct Web application is selected; it is displayed in the upper-right corner of the page. If the correct Web application is not shown, click the Web application drop-down list to select the correct one. With the correct Web application displayed, click the authentication type link that is displayed next to the Extranet zone. By default, the link text is Windows, as shown in Figure 13.



    Figure 13. Authentication Providers list

  5. In the Authentication Type section, click Forms. The page updates and displays Membership provider name and Role manager name boxes.
  6. Type the appropriate values in the Membership and Role boxes. Based on the current scenario, the page should look like Figure 14.



    Figure 14. Configure forms authentication Provider

  7. Click Save to commit your changes. The browser returns to the Authentication Providers main page, which should now display the new authentication provider name next to the Extranet zone, as shown in Figure 15.



    Figure 15. Updated Authentication Providers list

The final configuration step is to grant the appropriate policy for forms authentication users.

Granting the Appropriate Policy

Policies provide a mechanism to grant or deny rights to all site collections and subsites in a Web application, and override any permission settings that are applied on individual items or sites in that Web application. In this scenario, rights are granted to at least one forms authentication user. This policy allows the user to log on to the site, and then enables the user to add other forms authentication users and roles to SharePoint groups so that the rest of the forms authentication users can access the site.

In the specific scenario used in this article, this step is not necessary because we configured the Windows-secured Web application so that we can add and remove forms authentication users and roles and Windows users and roles from the same Web application. However, you might encounter situations in which a Windows-secured Web application is not being used. In that case, a policy is the only way to grant rights to a user.

For this scenario we grant a Full Rights policy to user1. That user can then log on to the site and provision other forms authentication users and roles into SharePoint groups.

To create the Full Rights policy

  1. Open your browser and navigate to the Central Administration Web site.
  2. Click the Application Management tab, and then click Policy for Web application.
  3. Ensure that the correct Web application is selected; it is displayed in the upper-right corner. Click Add Users.
  4. In the Zones list, click the Extranet zone.

Important:

This step is critical! If you select the wrong zone, you cannot correctly grant the policy rights.

  1. On the Add Users page, click the address book icon to open the People Picker dialog box, as shown in Figure 16.



    Figure 16. Add Users page

  2. In the People Picker dialog box, type user1 in the Find box, and then click the search button.

    If you created 20 users, as described earlier in this article, 11 results should be returned: user1 through user19. If so, the configuration you created in the web.config file is correct. If not, there is a problem in the web.config files, which you must correct.

    You should also notice that the account name is displayed in the format that SharePoint uses internally to keep track of it: MembershipProviderName:accountName. In this scenario, that means the account name for user1 is fbaMembers:user1.

  3. Double-click user1 to add it to the Add box, and then click OK.
  4. Select Full Control, as shown in Figure 17.



    Figure 17. Choose permissions on Add Users page

  5. Click Finish to save your changes.

The basic configuration is now complete; user1 should be able to log on to the site at www.contoso.com. Both forms authentication and Windows users and roles can be added from either Web site.

Granting Permissions to Create My Sites

When you log on to a site by using forms authentication, you may notice that by default, a My Site link does not appear in the upper-right corner of the page, as it does with sites secured with Windows authentication. In Windows authentication, by default the configuration for My Sites is a special group named NT AUTHORITY\authenticated users, who are granted rights to create My Sites. By default, each authenticated Windows user is granted the appropriate permissions to create a My Site. When you access a site as a forms authentication user, however, you do not have an associated Windows credential. Therefore, to Office SharePoint Server or Windows SharePoint Services, you are not a member of that Windows group so you do not have rights to create a My Site. As a result, the menu does not appear.

The process to grant forms authentication users the appropriate permissions to create My Sites is very similar to what you do to extend an existing Windows authentication site with forms authentication. For those steps, refer to the details provided in the section Setting Up Forms Authentication earlier in this article.

To enable forms authentication users to create My Sites

  1. Extend the Shared Services Provider (SSP) Web application into a new zone.

    For consistency, the zone you extend the SSP Web application into should be the same zone into which the forms authentication was extended, but this is not required unless the My Sites are hosted in the same Web application as the SSP. In the scenario described earlier in this article, forms authentication was used in the Extranet zone. In this example, it is extended into the Extranet zone also.

  2. Modify the web.config file for the new zone to use the same forms authentication membership and role providers.
  3. Modify the web.config file for the default SSP zone to use the same forms authentication membership and role providers. Because it is a Windows authentication site, remember to change the default role provider to AspNetWindowsTokenRoleProvider.
  4. Use the Authentication Provider administration page to configure the new zone to use forms authentication.

After you complete these steps, you can change the permissions in the My Sites section to allow forms authentication users to create My Sites.

To configure the permissions

  1. Open your browser and navigate to the SSP Web site.
  2. Click Personalization services permissions.
  3. Click Add Users/Groups.
  4. Click the address book button to open the People Picker dialog box.
  5. You can use the picker to grant either individual users or roles the right to create My Sites. Assuming you created and populated the Readers role as described earlier in this document, type Readers in the Find box, and then click the search button. Search should find a group named Readers that has an account name of fbaRoles:Readers.
  6. Double-click the Readers group in the search results pane. Selecting this group gives all members of the Readers role the right to create My Sites.
  7. Click OK to close the People Picker dialog box.
  8. Select the Create personal site check box and the Use personal features check box. The completed page should look like Figure 18.



    Figure 18. Configure permissions to create My Sites

  9. Click Save to save your changes.

All members of the Readers role now have the rights to create My Sites, and the My Site menu link appears in the upper-right corner of the page for them also.

Before forms authentication users can actually create a My Site, you must perform one additional step. To create a My Site, or view the public details of other users, you must grant rights to the My Site host site to all forms authentication users who will use My Sites.

When a user clicks the My Site link, he or she is directed to the /_layouts/MySite.aspx page in the My Site host application. That page determines whether the user already has a My Site created. If so, the user is automatically redirected to his or her site. If not, the My Site is created for the user and then the user is redirected to it. But to be able to navigate to the MySite.aspx page, a My Site user must have, at a minimum, Read rights on that site. Using the example from this article, someone with administrative rights on the My Site host site must add the Readers role to a SharePoint site group that has, at a minimum, Read rights on the site. After that is completed, forms authentication users can create My Sites.

Hosting My Sites in a Separate Web Application

If My Sites are hosted in the same Web application that was already extended for forms authentication users, no further action is needed. However, if you host your My Sites in a separate Web application, you must also extend it as described previously.

To host My Sites in a separate Web application

  1. Extend the My Site Web application into a new zone. The zone you extend it into MUST BE the same zone into which the forms authentication zone was extended. For the My Sites to display the correct URL for both Windows users and forms authentication users, you must also extend the Web application into the same zone; in this scenario, it is the Extranet zone.
  2. Modify the web.config file for the new zone to use the same forms authentication membership and role providers.
  3. Modify the web.config file for the existing My Site zone to use the same forms authentication membership and role providers. If it is a Windows authentication site, remember to change the default role provider to AspNetWindowsTokenRoleProvider.
  4. Use the Authentication Provider administration page to configure the new zone to use forms authentication.

From a configuration standpoint, you must consider one other aspect when configuring options for My Sites. If you intend to host multiple authentication membership providers and allow all of them to create My Sites, there could potentially be name collision issues. For example, if both membership providers had user accounts with the name user1, there would be a conflict when the second user1 tried to create a My Site because a site collection named user1 would already exist. In that scenario, you can configure the naming used when creating My Sites to include the provider name in addition to the account name.

To configure My Sites to be created with a name in the format of provider_accountName

  1. Open your browser and navigate to the SSP Web site.
  2. Click My Site settings.
  3. In the Site Naming Format section, click Domain and user name.

    If you select the first or second option, all sites for forms authentication users are created with the user name only.

  4. Click OK to save your changes.

There is one final point to make here. If your My Sites are hosted in a separate Web application, when forms authentication users click the My Site link, they are taken to the forms logon page again, even if they have already authenticated to their main corporate content site (in our example, http://www.contoso.com). The reason is that the authentication cookie that is generated when a user logs on to a forms authentication site is associated with the domain name. Domain name, in this case, refers to the URL namespace, not an Active Directory domain.

For example, if your corporate content is hosted on a site at domain www.contoso.com, and My Sites are hosted on a site at domain mysites.contoso.com, the content requires two different authentication cookies. The user experience may seem strange at first, because most users think of all the content as just "one Web site." It may cause some confusion when the forms logon page is shown again just from clicking a link in the main corporate content site.

However, by following the steps described earlier in this article, both Windows and forms authentication users should be able to create and use My Sites.

Provider-Specific Features

Providers may have differing characteristics that can impact how you design your solution and implementation. This section describes some of the features of individual providers that you should be aware of when planning your farm.

LDAP Provider

The LDAP membership and role provider is included with Office SharePoint Server 2007. It allows you to use an LDAP v3 directory as the authoritative source for SharePoint users and groups. It is used with many LDAP directories, although most of the examples that are available currently demonstrate how to connect to Active Directory Domain Services. Novell eDirectory, Sun Microsystems SunONE iPlanet (the middleware offerings formerly known as iPlanet and SunONE have been rebranded to Sun Java System), and the Unix OpenLDAP server are also used frequently in extranet scenarios. Following is one example of a membership and role provider configuration section for the web.config file that connects to each.

Configuration Example for Novell eDirectory

XML

Copy

<membership defaultProvider="LdapMembership">

<providers>

<add

name="LdapMembership"

type="Microsoft.Office.Server.Security.LDAPMembershipProvider,

Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71E9BCE111E9429C"

server=" your server name or IP address " port="389" useSSL="false"

userDNAttribute="uniqueID"

userNameAttribute="uid"

userContainer="o=Novell"

userObjectClass="person"

userFilter="(ObjectClass=person)"

scope="Subtree"

/>

</providers>

</membership>

<roleManager defaultProvider="LdapRole" enabled="true" cacheRolesInCookie="false" cookieName=".PeopleDCRole">

<providers>

<add

name="LdapRole"

type="Microsoft.Office.Server.Security.LDAPRoleProvider,

Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71E9BCE111E9429C"

server="your server name or IP address"

port="389"

useSSL="false"

groupContainer="o=Novell"

groupNameAttribute="cn"

groupMemberAttribute="member"

userNameAttribute="cn"

dnAttribute="dn"

groupFilter="(&amp;(ObjectClass=groupOfNames))"

userFilter="(&amp;(ObjectClass=person))"

scope="Subtree"

useUserDNAttribute="false"

/>

</providers>

</roleManager>

Configuration Example for Sun Java System (Formerly iPlanet and SunONE)

XML

Copy

<membership defaultProvider="LdapMembership">

<providers>

<add

name="LdapMembership"

type="Microsoft.Office.Server.Security.LDAPMembershipProvider,

Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71E9BCE111E9429C"

server="myServerName"

port="21801"

useSSL="false"

userDNAttribute="entryDN"

userNameAttribute="uid"

userContainer="dc=CONTOSO,dc=COM"

userObjectClass="Inetorgperson"

userFilter="(ObjectClass=Inetorgperson)"

scope="Subtree"

otherRequiredUserAttributes="sn,givenname,cn"

/>

</providers>

</membership>

 

<roleManager defaultProvider="LdapRole" enabled="true" cacheRolesInCookie="false" cookieName=".PeopleDCRole">

<providers>

<add

name="LdapRole"

type="Microsoft.Office.Server.Security.LDAPRoleProvider,

Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71E9BCE111E9429C"

server="myServerName"

port="21801"

useSSL="false"

groupContainer="dc=CONTOSO,dc=COM"

groupNameAttribute="cn"

groupMemberAttribute="uniqueMember"

userNameAttribute="uid"

dnAttribute="entryDN"

groupFilter="(ObjectClass=groupofuniquenames)"

scope="Subtree"

/>

</providers>

</roleManager>

Configuration Example for OpenLDAP

XML

Copy

<membership defaultProvider="LdapMembership">

<providers>

<add

name="LdapMembership"

type="Microsoft.Office.Server.Security.LDAPMembershipProvider,

Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71E9BCE111E9429C"

server="<server name>"

port="389"

useSSL="false"

useDNAttribute="false"

userNameAttribute="uid"

userContainer="ou=People,dc=domain,dc=org"

userObjectClass="person"

userFilter="(ObjectClass=person)"

scope="Subtree"

otherRequiredUserAttributes="uid,cn"

/>

</providers>

</membership>

 

<roleManager defaultProvider="LdapRole" enabled="true"

cacheRolesInCookie="false" cookieName=".PeopleDCRole">

<providers>

<add

name="LdapRole"

type="Microsoft.Office.Server.Security.LDAPRoleProvider,

Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71E9BCE111E9429C"

server="<server name>"

port="389"

useSSL="false"

groupContainer="dc=domain,dc=org"

userNameAttribute="uid"

useUserDNAttribute="false"

userFilter="(objectClass=person)"

groupNameAttribute="cn"

dnAttribute=""

scope="Subtree"

/>

</providers>

</roleManager>

LDAP Membership and Role Provider Usage Constraints

Be aware of the following constraints when you use the LDAP membership and role provider:

  • Trusted forests If you use the LDAP provider with Active Directory, there are scenarios (such as in an extranet) in which trusted forests might be in use. When a site is configured to use Windows authentication, users from either forest can authenticate and use SharePoint resources. The LDAP provider, however, tries to authenticate against only the forest that the membership provider is configured to check. It does not authenticate against a trusted forest and it does not follow LDAP referrals.

    If you need to authenticate against multiple forests, you should extend SharePoint Products and Technologies into an additional zone for each forest that is used for authentication. Then configure each zone to use a different forest in the membership and role settings of the zone's web.config file.
  • Primary group membership In Active Directory, each user has a primary group. When the LDAP Role provider is used with Active Directory, a user's primary group is not included in the list of roles for the user. By default, a user's primary group is the Domain Users group. As a result, the Domain Users group is not a good choice to add to a SharePoint group when you are provisioning permissions because unless the user's primary group is changed, no user is returned in the membership of that role. For more information, see the primaryGroupID attribute in User Security Attributes.
  • Authenticated binds The release version of SharePoint Products and Technologies supported using only anonymous binds to an LDAP server. Many customers requested support for authenticated binds to an LDAP directory, and it is added in Microsoft Office SharePoint Server 2007 Service Pack 1 (SP1). If you require support for authenticated binds to your LDAP server and want to use the LDAP provider in Office SharePoint Server 2007, you must first apply Office SharePoint Server 2007 SP1.

With Office SharePoint Server SP1, the Membership element and Role provider element in the web.config file support two additional attributes: connectionUsername and connectionPassword. If you provide values for these attributes, the provider attempts to use those credentials when querying the LDAP directory. Following is an example of an entry for a membership provider that uses these new attributes.

XML

Copy

<add

connectionUsername="myDomain\myUser"

connectionPassword="myPassword"

server="myLdapServer"

port="389"

useSSL="false"

userDNAttribute="distinguishedName"

userNameAttribute="sAMAccountName"

userContainer="CN=Users,DC=myforest,DC=com"

userObjectClass="person"

userFilter="(ObjectClass=person)"

scope="Subtree"

otherRequiredUserAttributes="sn,givenname,cn"

name="LdapMembership"

type="Microsoft.Office.Server.Security.LDAPMembershipProvider,

Microsoft.Office.Server, Version=12.0.0.0, Culture=neutral,

PublicKeyToken=71E9BCE111E9429C"

/>

If you are performing authenticated binds to an LDAP directory, you should use the connectionUsername and connectionPassword attributes for both the membership and role provider elements. Notice that these elements are shown in plain text in the web.config file. Although this is generally not a good practice, ASP.NET 2.0 fortunately lets you encrypt configuration sections in the web.config file. There are different ways and options for encrypting sections; however, those are beyond the scope of this article. For more information about encrypting configuration sections by using DPAPI, see How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI. For more information about encrypting by using RSA, see How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA.

In the simplest scenario, you can encrypt the membership and role provider sections by using the aspnet_regiis.exe utility provided with ASP.NET 2.0. You can encrypt the sections by using DPAPI and the local machine keys. You must repeat the process on each front-end Web server; however, because you must also update the membership and role provider entries on each front-end Web server in the farm, you update both at the same time. Following is an example of the command line you can use to encrypt the membership and roleManager sections of the web.config file for a Web application. It uses DPAPI with the local machine key.

Copy

aspnet_regiis.exe -pef "system.web/membership" "C:\Inetpub\wwwroot\wss\VirtualDirectories\99" -prov "DataProtectionConfigurationProvider"

aspnet_regiis.exe -pef "system.web/roleManager" "C:\Inetpub\wwwroot\wss\VirtualDirectories\99" -prov "DataProtectionConfigurationProvider"

In this scenario, the virtual directory for the SharePoint Web application whose web.config sections are being encrypted is mapped to the physical directory C:\Inetpub\wwwroot\wss\VirtualDirectories\99. Also, the aspnet_regiis.exe application is located by default in the path C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727. After the sections are encrypted, they look like the following example (only the membership section is shown here).

Note:

Line breaks in the <CipherData> tag are provided only for readability.

XML

Copy

<membership configProtectionProvider="DataProtectionConfigurationProvider">

<EncryptedData>

<CipherData>

<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAxi12BeT890eeO/wBnFBr

rgQAAAACAAAAAAADZgAAqAAAABAAAACMwGpKV471oWCBmSEw8YDcAAAAAASAAACgAAAAEAA

AAFXOS3tZWyEiBr6O4CRdJ0QwBQAAadCe3M7P75Mr83axr3dTTsrjZBKLF/2GbxxVykjbSj

lH2QJQQHOGdklUQcunOCitfbOsBBvFh+3D/NMYVQoQZdVPFyT6X2uCdLfyPbRAfhEsZISw9

aOOm8jsRbIVmjHyx+T2ZcjlLMp0D8IliSSS/QkZghxi/XXK6rT1V7PxFE/7IGGSvC9tVND8

lw9p1KkGMYNyltMeg/aiXC0SUskrV515lbu4rFk8fcrXWtoccuso3+Tvq37RyX7fdv7nIoD

SxFP0DVqoDfZv4pxQubjUSFP5NlrHOBaPbKTcjx/5OKCL/fZtlYc++0GwthWo12E0usd2W9

6c78IhramW/zBvQFk8pCcsk5q2/njpQHg2103nrrG6UpJwd1tTIZQjiaISe/YUT33yU0WXt

bl/2LLq20dmYJ6mXv+2vge6IocnAYLhG+tbOviJdGGu/NEQLUS/L29440tVqoJGYnqF2oqr

tYe+4KLgf76TqLEV/BRyGtjspaewmwOj1SGcVYmdGMj4DvrmVrVXcJi9IQnExlv+q7KOj0T

2glP+2Ya3T/wPqM/C0xENtgcnQ3DdYxlKr6kJ1gt26FvGYEGsD/EPdMGRAh2a3rKKCd9leE

vKLVviP5o8jhdcY28NY7vh+DPTePOahLmoT/d+uJcNxfSZQ7CgCyz+AvNb6Tf86CtPHqmJR

NZN0OBsheEkNJ8SkgpnO4lYmW2DhqJeP93vEfRQl3eZ++MNvxas5niSyi/xD2Um0F+m/ckH

OagBRXoI9+wWyYS8rpdexG5EaYzqzXMn+72kDdai68OyqL1NusY0zJIBqG+Ipp8Jj1ErDoz

92aH+ttCDVRL/oZXH7wj9ohaL3skxyyDSkZBJoDUNrLyUE6UBIHljqbFAITdVuyVTXb7de3

qxgFMYXFULp0oJrZW5I7SVu6jazQ3ehEc3fxCDAMv0cU+49IdqJGX3nF2vsOLdS5oabj9ID

1xbkbPYli7RE3KoHP+ZkptINXNSHjYLg5RJdcIoS4DNf9m1vFrOhfS3uzCDCAmpVw0WiFcw

axiY2K9l9mFv9/+l4KL0IAUNPZhOda/+dC9/S+ifee3t32sIU9eOu8/7mQtl0PAOvk7dk3/

Qd4kC1oqf5pcQiDA9AR3iWP2O9jZt0memRX5GG6yGaqoMs1TY8t4hPlXC/VJDeJHNcjztEv

+Q5WktOkbSczQdl2PgWp/daOhzGrhcQiavB/2Qxm26prYABx3aUaFXSwPl9z7LDxEKIenrX

/NwFdtssZah5F/JJwziptxjrp8aCsB3VlkXkEWK1jlYmCpPjjoW/sb3rmEKAIq9qILSNAtD

M8mX4ryXYoc6uKtzp8XH56aLi33BM9eghnxanHMKLZNQnxmPEVhhX1BpsqIzNn0P+bbBmdz

Oy03Yl+Pp/EFCgC44p+CvfyGPlisQolHqvvgT03DC29LxX2buGF0PUBQpET7JWmjPcp2F22

zop4UCmW4XDaiWal4KI2SIHC/jorlFul+0OeNXfp3kIWmyWy8YLnMDboRxD7z/yb0Qql4wW

FC6u8AY/yKYtFVhS776Qv/ez4f+rLNZlXLwtcE/ezj3aGTxqboWu7tXy22K/RlkWeeRYucJ

0GwcA8N1bOIaVPMuqqA8DGpDJJOtEhNRzSO0toBt89mCc9qG0fTQSeqJDX4Og3iJOkdgoj4

wcW3iQrT1Jfn4pnQKrcne688yfm5V1PlwoPOkKo90CxVuy887giiG+aj+7KuWobinOD9yDV

XJeDWdvWZQrR2dL+r7zZxb59QUAAAA9atGPbGXe++gGm9Q3XnNhTc/RQM=

</CipherValue>

</CipherData>

</EncryptedData>

</membership>

Fortunately, because these encryption methods are a core part of ASP.NET 2.0, the application does not need to handle these methods differently in order to work. If the credentials or other attributes of the sections must be changed, you can decrypt them by using the same utility. Following is an example of removing encryption from the membership section through the command line.

Copy

aspnet_regiis.exe -pdf "system.web/membership" "C:\Inetpub\wwwroot\wss\VirtualDirectories\99"

Active Directory Membership Provider

The Active Directory provider is designed to let you use forms authentication to capture the credentials of a Windows identity and validate them against Active Directory. However, that does not mean that it provides all of the same Windows functionality and features that are available to a Windows user who is logging onto a Windows desktop. Some of the distinctive differences for the Active Directory Membership provider include:

  • Cannot validate credentials from other domains.  The provider can only validate credentials for the domain (and optionally a container within the domain) against which the provider is configured to work.  The underlying reason is that the provider connects to Active Directory by using an authenticated LDAP bind, and then also validates that the user object exists within the container scope defined by the connection string.  As a result you cannot type in credentials for a user in another domain in the forest. If you use this provider, all user accounts must exist in the same domain.
  • The provider has no way to prompt a user to renew his or her password prior to expiration.  The provider can only validate credentials and tell whether a user account is locked out.

This concludes part 1 of this article series.

Next step: Forms Authentication in SharePoint Products and Technologies (Part 2): Membership and Role Provider Samples.

Additional Resources

For more information about forms authentication, see the following additional resources:

1 - 5 Next