my.net

My Photo
Name:
Location: United States

Saturday, June 16, 2007

cms 101

cms 2002 installation complete with dev tools (on .NET 2003)

- setup cmsguest, cmssys, cmsadmin domain accounts
- create website cms101.com
- create virtual directory cms101.com
- create empty database
- use dca to create cms tables (specify admin account) (step#b)
- use sca to make the site as cms site (step#a)
- use sca to allow guest login as cmsguest
- create webctrl_client(folder) at the website root
- create cms virtual directory and point to ..\program files\cms\server\iis_cms\
- mcms and nr virtual directories are automatically created in step#a
- can use only one cms database for a cms site (switch to different database using dca)
- run site manager under admin (specified in step#b)

Monday, June 04, 2007

Forms Authentication thru AD


using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security;
using System.Security.Permissions;

public partial class Client_Novelis_Login : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
Image image = new Image();
tdTopMiddle.Style.Add("background-image", image.ResolveClientUrl("~/Client/Novelis/Images/table_side_top.gif"));
tdSideLeft.Style.Add("background-image", image.ResolveClientUrl("~/Client/Novelis/Images/table_side_left.gif"));
tdSideRight.Style.Add("background-image", image.ResolveClientUrl("~/Client/Novelis/Images/table_side_right.gif"));
tdBottomMiddle.Style.Add("background-image", image.ResolveClientUrl("~/Client/Novelis/Images/table_side_bottom.gif"));
}
protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
{
string ADskipaccount = "admin";
string ADDomain = "mydomain";
string ASPNETDefPasswd = "mypass999";
Impersonator oImper = null;
e.Authenticated = false; //not authenticated.
try
{
Login oLogin = (Login)sender;
if (oLogin.UserName.ToLower().StartsWith(ADskipaccount))
//if valid skip account, auth thru ASPNET
e.Authenticated = Membership.ValidateUser(oLogin.UserName, oLogin.Password);
else
{
oImper = new Impersonator(oLogin.UserName, ADDomain, oLogin.Password);
oImper.Impersonate();
MembershipUserCollection oUserCol = Membership.FindUsersByName(oLogin.UserName);
MembershipUser oUser;
if (oUserCol.Count == 0) //if not found, create user with default password
{
oUser = Membership.CreateUser(oLogin.UserName, ASPNETDefPasswd);
if (oUser != null)
{
//Log "create user success"
}
else
{
//Log "create user failed"
}
}
else
{
oUser = oUserCol[oLogin.UserName];
}
if (Membership.ValidateUser(oLogin.UserName, ASPNETDefPasswd))
{
e.Authenticated = oUser.IsApproved;
}
}
}
catch(Exception ex)
{
//Log "AD Authentication failed"
e.Authenticated = false;
oImper.Undo();
}
}
protected void Login1_LoggedIn(object sender, EventArgs e)
{
string desiredUrl = Request.QueryString[QS.RETURN_URL];
if (desiredUrl != null)
{
Response.Redirect("~" + desiredUrl.Replace(Request.ApplicationPath, ""));
}

}

protected void UserName_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
TextBox tb = (TextBox)sender;
tb.Focus();
}
}
}
public class Impersonator
{
// private members for holding domain user account credentials
private string username = String.Empty;
private string password = String.Empty;
private string domain = String.Empty;
// this will hold the security context for reverting back to the client after impersonation operations are complete
private WindowsImpersonationContext impersonationContext = null;

// disable instantiation via default constructor
private Impersonator()
{ }

public Impersonator(string username, string domain, string password)
{
// set the properties used for domain user account
this.username = username;
this.domain = domain;
this.password = password;
}

private WindowsIdentity Logon()
{
IntPtr handle = new IntPtr(0);
handle = IntPtr.Zero;

const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;

// attempt to authenticate domain user account
bool logonSucceeded = LogonUser(this.username, this.domain, this.password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref handle);

if (!logonSucceeded)
{
// if the logon failed, get the error code and throw an exception
int errorCode = Marshal.GetLastWin32Error();
throw new Exception("User logon failed. Error Number: " + errorCode);
}

// if logon succeeds, create a WindowsIdentity instance
WindowsIdentity winIdentity = new WindowsIdentity(handle);

// close the open handle to the authenticated account
CloseHandle(handle);

return winIdentity;
}


public void Impersonate()
{
// authenticates the domain user account and begins impersonating it
this.impersonationContext = this.Logon().Impersonate();
}


public void Undo()
{
if (this.impersonationContext != null)
// rever back to original security context which was store in the WindowsImpersonationContext instance
this.impersonationContext.Undo();
}

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);

}

Sunday, June 03, 2007

LastLoginDate" is not supported by the Active Directory Membership Provider

For keeping track of auditable data like login time, you will need to add code to your login page to store this audit data. The SqlMembershipProvider supports storing the last login time for users - however the ActiveDirectoryMembershipProvider does not. The reason for this discrepancy is that the AD provider relies on directory attributes on the user object in AD. Not all user object attributes are replicated across domain controllers. So even though the AD schema for a user object includes an attribute for the last time a user logged in, that value doesn't get replicated. As a result, in any environment running two or more domain controllers the AD provider can't get an authoritative answer as to when a user last logged in.

If you try to retrieve the last login time from a MembershipUser instance returned by the AD provider you will get an exception instead. We chose to throw an exception rather than having the provider query each domain controller in an attempt to merge the values and determine the correct value. We figured that approach would generate excessive network traffic, and probably wouldn't work in more complex extranets where web servers intentionally aren't allowed access to every domain controller on a network.

How to add attributes to user class of ADAM

more at: http://www.developerland.com/CSharpGeneral/ActiveDirectory/124.aspx

You can also register the object and attribute ID's so no one else can reuse them. For more information go to the MSDN article Obtaining an Object Identifier from Microsoft [^]. Next we assign the attribute type "HomeURL" to the new object type "UserProperties". This unfortunately can not be done through ADAM ADSI Edit. The logical choice would be to open the properties of the "UserProperties" object type and then add the attribute to the "allowedProperties" property. But this will give you the following error message "Modification of a constructed attribute is not allowed". This needs to be done through the "ADAM Schema" MMC snap-in. Go to "Start | Run" and type in "mmc /a". This opens an empty Management Console and allows you to add different snap-ins. Go to the menu "File | Add/Remove Snap-in", click on the add button and select the "ADAM Schema" snap-in. When done this shows you an entry called "ADAM Schema" in the list on the left side. Right click on it and select "Change ADAM Server" from the popup menu. Enter the ADAM server and the port address where the ADAM instance is running on, for example "localhost" and "389". When done you see two entries in the list – "Classes" and "Attributes". You can quite actually also create object and attribute types through this snap-in. You enter the same values but the user interface is different.

Now find your object type under "Classes", right click on it and select properties. Go to the Attributes tab, click the Add button, select the "HomeURL" attribute and click ok. You can add as many attributes to the optional attributes list as required but you can not add mandatory attributes. If you need mandatory attributes then create the object type in the "ADAM Schema" snap-in and select them while creating the object type itself. When done click ok. Click on the object type and see on the right side all the attributes belonging to it. You see if they are system attributes, whether it is mandatory or optional and also which class they have been added to. So this view shows you also all the inherited attributes. You see now also the attribute you just added. Going back to ADSI Edit and looking at the property "allowedAttributes" of the object type UserProperties does unfortunately not show this new attribute we just added. This shortcoming in ADSI Edit can unfortunately be rather inconvenient!


http://erlend.oftedal.no/blog/?blogid=6