jetzhuo

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

http://forums.asp.net/908050/ShowThread.aspx

Overview:

Many consumers of DNN and CS have been eagerly awaiting a solution for integrating the two products.

 There are two broad visions (options) for such a solution.

Option 1. Fully integrate CS into DNN by converting it into a DNN module.
Option 2. Integrate/share the membership database only and therefore the membership functionality.

Both options are valid and complete approaches. Both options share the goal of a Single Sign On (SSO).
This method (in this post) aims to achieve only the SSO portion of these,
I do not consider this a "complete" solution (the membership databases will only be synchronised,
not shared and core code changes are required).
 Note: there are no database alterations made,
changes may be reversed to run the applications separately (or to switch to an alternate method, upgrade etc). 

The reason for this approach is as follows: a).
the DNN module is already being developed (re-invention), b).
 the membership providers and implementations are yet to standardise (not the same yet,
maybe too early to implement sharing) and c). we all want something that works *now* (impatience).

The title of this piece contains the word "Developers" because if you are not confident about changing core code and configurations then this is not for you. I wouldn't like to see anyone implement this in a production environment in it's current state. But that's what this is all about - let's test and develop this together from this point forward.


How does this work then?

The keys to this implementation are as follows:

1. The use of identical machine keys between the two applications
2. The use of identical forms authentication name values
3. The use of secure web services to synchronise the membership databases


Environment:

The environment used for this development:
- 1 PC
- Windows XP Professional (IIS v5.1)
- Visual Studio .NET 2003
- MSDE 2000 REL A
- Web Services Enhancements 2.0 SP3

If your development environment differs, you may need to alter the following instructions to suit.


General Process

The general steps to set this up for development are (see detailed steps below before starting):

1. install DNN 3.0.13
2. modify DNN and CS config files
3. install CS 1.0 (build 50218) with build support
4. install Web Services Enhancements 2.0 SP3
5. add web service to CS
6. add code to UserController in DNN
7. modify CS urls and UI element


Specific Steps

The specific steps are as follows:

1. Create databases
- Create DNN database e.g. DNN3013
- Create CS database e.g. CS50218
- Add the ASPNET Windows account to the SQL Server logins
- Assign the db_owner role on the ASPNET account for both databases

2. Extract files
- Extract/copy DNN files to a folder e.g. C:\Inetpub\DotNetNuke3013
- Grant the ASPNET account modify access to the folder
- Extract/copy the source code files (all files in the src folder) for CS to a folder e.g. C:\Inetpub\CS50218
- Copy the .dll files in the /Web/bin folder from the CS runtime version to the /Web/bin folder of the source code version in the location above (replace files is ok) e.g. copy to C:\Inetpub\CS50218\Web\bin
- Grant the ASPNET account modify access to the /Web/blogs and /Web/photos folders

3. Install DNN 3.0.13
- Set the database connection string in the web.config file e.g. set the SiteSqlServer appSettings key to Server=(local);Database=DNN3013;Trusted_Connection=True;
- Add a virtual directory to IIS e.g. Alias: dotnetnuke, Directory: C:\Inetpub\DotNetNuke3013
- Browse to http://localhost/dotnetnuke
- NOTE: The MachineValidationKey and the MachineDecryptionKey in the appSettings section of the web.config file will be changed by the DNN installer

4. Modify the DNN and CS web.config files (e.g. C:\Inetpub\DotNetNuke3013\Web.config and C:\Inetpub\CS50218\Web\Web.config)
- Copy the MachineValidationKey and the MachineDecryptionKey values from the DNN config file to the CS config file to replace the CS values
- Add the following to the <system.web> section in both config files using the values from the previous step:

  <!-- ADDED FOR DNN CS SINGLE LOGIN -->
  <machineKey
  validationKey="INSERT-MACHINEVALIDATIONKEY-VALUE-FROM-PREVIOUS-STEP"
  decryptionKey="INSERT-MACHINEDECRYPTIONKEY-VALUE-FROM-PREVIOUS-STEP"
  validation="SHA1"
  />

- In the CS web.config change:

  <authentication mode="Forms">
   <forms name=".CommunityServer" protection="All" timeout="60" loginUrl="login.aspx" />
  </authentication>

- To the same name as DNN:

  <authentication mode="Forms">
   <forms name=".DOTNETNUKE" protection="All" timeout="60" loginUrl="login.aspx" />
  </authentication>

5. Install CS (build 50218)
- Edit the web/installer/default.aspx file and change "bool INSTALLER_ENABLED = false;" to true
- Add a virtual directory to IIS e.g. Alias: cs, Directory: C:\Inetpub\CS50218\Web
- Browse to http://localhost/cs/installer
- Welcome screen > Next > Read and I Agree > Next > Database Login (local) and Windows > Next > Choose CS50218 > Next > All options checked > Next > set the admin password to the same as DNN i.e. admin > Next > when the installation completes follow the instructions pertaining to the SQL connection string and the CS installer

6. Install Web Services Enhancements 2.0 SP3
- Download Web Services Enhancements 2.0 SP3 from http://msdn.microsoft.com/webservices/building/wse/default.aspx
- Install as "Visual Studio Developer"

7. Add the web service to CS
- Open the Community Server solution in Visual Studio e.g. double click the following sln file C:\Inetpub\CS50218\Community Server.sln
- Right click the CommunityServerWeb project and select WSE Settings 2.0...
- Check "Enable this project for Web Services Enhancements"
- Check "Enable Microsoft Web Services Enhancement Soap Extensions"
- Click OK
- Note: this will make changes to the web.config file and add a reference to Microsoft.Web.Services2.dll
- Note: it seems you may also need to correct the MemberRole reference in this project, delete the reference and add it back in e.g. browse to C:\Inetpub\CS50218\Web\bin\MemberRole.dll
- Right click the CommunityServerWeb project and select Add > Add Web Service, name it UserService.asmx
- Change to the code view for the UserService.asmx file and replace the entire content with the following:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using CommunityServer;
using CommunityServer.Components;
using CommunityServer.Components.Enumerations;
using Microsoft.ScalableHosting.Security;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
namespace CommunityServerWeb
{
 /// <summary>
 /// Summary description for UserService.
 /// </summary>
 public class UserService : System.Web.Services.WebService
 {
  /// <summary>
  ///
  /// </summary>
  public UserService()
  {
   //CODEGEN: This call is required by the ASP.NET Web Services Designer
   InitializeComponent();
  }
  #region Component Designer generated code
  
  //Required by the Web Services Designer
  private IContainer components = null;
    
  /// <summary>
  /// Required method for Designer support - do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
  }
  /// <summary>
  /// Clean up any resources being used.
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if(disposing && components != null)
   {
    components.Dispose();
   }
   base.Dispose(disposing);  
  }
  
  #endregion
  /// <summary>
  ///
  /// </summary>
  /// <returns></returns>
  [WebMethod()]
  public string GetSecretMessage()
  {
   return "Only authenticated users can view this secret message!";
  }
  /// <summary>
  ///
  /// </summary>
  /// <param name="username"></param>
  /// <param name="email"></param>
  /// <returns></returns>
  [WebMethod]
  public string CanCreateUser(string username, string email)
  {
   string result = "Success";
   // Check if username already exists
   User usernameLookup = Users.FindUserByUsername( username );
   if (usernameLookup.UserID != 0)
    result = "DuplicateUserName";
   // Check if email already exists
   User emailLookup = Users.FindUserByEmail(email);
   if (emailLookup.Member.Email != null)
    result = "DuplicateEmail";
   // Check if username is disallowed
   if ( DisallowedNames.NameIsDisallowed(username) == true )
    result = "InvalidUserName";
   
   // Otherwise return success
   return result;
  }
  /// <summary>
  ///
  /// </summary>
  /// <param name="username"></param>
  /// <param name="password"></param>
  /// <param name="email"></param>
  /// <returns></returns>
  [WebMethod]
  public string CreateUser(string username, string password, string email)
  {
CommunityServer.Components.AccountActivation activation = SiteSettingsManager.GetSiteSettings().AccountActivation;
   string output = "";
   MembershipCreateStatus status = MembershipCreateStatus.ProviderError;
   // try to create the new user account
   User user = new User();
   user.Username = username;   
   user.Email = email;
   user.Password = password.Trim();
   user.PasswordFormat = SiteSettingsManager.GetSiteSettings().PasswordFormat;
   // Does the user require approval?
   //
   if (activation == AccountActivation.AdminApproval)
    user.AccountStatus = UserAccountStatus.ApprovalPending;
   else
    user.AccountStatus = UserAccountStatus.Approved;
           
   // Set the Anonymous flag to false
   //
   user.IsAnonymous = false;
   // Attempt to create the user
   //
   if (user.Username == "Anonymous")
   {
    status = MembershipCreateStatus.DuplicateUserName;
   }
   else
   {
    try 
    {
     if (Users.Create(user, true) == CreateUserStatus.Created)
      status = MembershipCreateStatus.Success;
    }
    catch (MembershipCreateUserException exception)
    {
     status = exception.StatusCode;
    }
   }
   // Determine if the account was created successfully
   //
   switch (status)
   {
     // Username already exists!
    case MembershipCreateStatus.DuplicateUserName:
     output = CommunityServer.Components.ResourceManager.GetString("CreateNewAccount_CreateUserStatus_DuplicateUsername");
     break;
     // Email already exists!
    case MembershipCreateStatus.DuplicateEmail:
     output = CommunityServer.Components.ResourceManager.GetString("CreateNewAccount_CreateUserStatus_DuplicateEmailAddress");
     break;
     // Unknown failure has occurred!
    case MembershipCreateStatus.ProviderError:
     output = CommunityServer.Components.ResourceManager.GetString("CreateNewAccount_CreateUserStatus_UnknownFailure");
     break;
     // Username is disallowed
    case MembershipCreateStatus.UserRejected:
     output = CommunityServer.Components.ResourceManager.GetString("CreateNewAccount_CreateUserStatus_DisallowedUsername");
     break;
    case MembershipCreateStatus.InvalidAnswer:
    case MembershipCreateStatus.InvalidQuestion:
     output = "invalid answer or question";
     break;
     // Everything went off fine, good
    case MembershipCreateStatus.Success:
    switch (activation) 
    {
     case AccountActivation.AdminApproval:
      output = "admin approved activation";
      break;
     case AccountActivation.Email:
      output = "email activation";
      break;
     case AccountActivation.Automatic:
      // Are we allowing login?
      output = "automatic activation";
      break;
    }
     break;
   }
 
   return output;
  }
  /// <summary>
  ///
  /// </summary>
  /// <param name="username"></param>
  /// <param name="password"></param>
  /// <param name="newPassword"></param>
  /// <returns></returns>
  [WebMethod]
  public bool ChangePassword(string username, string password, string newPassword)
  {
   bool status = false;
   try
   {
    User user = Users.FindUserByUsername(username);
    status = user.Member.ChangePassword(password, newPassword);
    return status;
   }
   catch
   {
    return status;
   }
  }
  /// <summary>
  ///
  /// </summary>
  /// <param name="username"></param>
  /// <param name="email"></param>
  /// <param name="approved"></param>
  /// <returns></returns>
  [WebMethod]
  public bool UpdateUser(string username, string email, string approved)
  {
   bool status = false;
   try
   {
    User user = Users.FindUserByUsername(username);
    user.Email = email;
    if (approved == "True")
    {
     user.AccountStatus = UserAccountStatus.Approved;
    }
    else
    {
     user.AccountStatus = UserAccountStatus.Disapproved;
    }
    Users.UpdateUser(user);
    status = true;
    return status;
   }
   catch
   {
    return status;
   }
  }
  /// <summary>
  ///
  /// </summary>
  /// <param name="username"></param>
  /// <returns></returns>
  [WebMethod]
  public bool DeactivateUser(string username)
  {
   bool status = false;
   try
   {
    User user = Users.FindUserByUsername(username);
    user.Email = user.UserID.ToString() + ".inactive@host.local";
    user.AccountStatus = UserAccountStatus.Disapproved;
    user.Member.ResetPassword();
    user.ForceLogin = true;
    Users.UpdateUser(user);
    status = true;
    return status;
   }
   catch
   {
    return status;
   }
  }
 }
 /// <summary>
 ///
 /// </summary>
 public class AuthenticationManager : UsernameTokenManager
 {
  // This method returns the password for the provided username
  // WSE will make the determination if they match
  /// <summary>
  ///
  /// </summary>
  /// <param name="token"></param>
  /// <returns></returns>
  protected override string AuthenticateToken( UsernameToken token )
  {
   string username = token.Username;
   // The following may be substituted with a more complex lookup routine...
   if (String.Compare("INSERT-UNIQUE-USERNAME", username, true) == 0)
    return "INSERT-UNIQUE-PASSWORD";
   else
    return String.Empty;
  }
 }
}

- Note: The GetSecretMessage method is for testing the security provided by WSE 2.0, you may choose to remove it.
- Save the file
- Right click the CommunityServerWeb project and select WSE Settings 2.0...
- Click the Security tab
- In the Security Tokens Managers section, click Add
- Enter the following values: 
   - Type: CommunityServerWeb.AuthenticationManager, CommunityServer.Web 
   - Namespace: http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd 
   - Qname: wsse:UsernameToken
- Click OK
- Click the Policy tab
- Check Enable Policy
- Click Add
- Accept the default for the Endpoint URI by clicking OK
- In the Security Settings Wizard, select "Secure a service application" > Next >
Check Require signatures in the Request Method section, uncheck all others > Next >
Select Username > Next > Next >
Finish (these settings are used only to fullfill the requirement of completing the wizard)
- Click OK on the main WSE Settings dialog
- Open the policyCache.config file created by the Security Settings Wizard
- Replace the entire contents with the following:

<?xml version="1.0" encoding="utf-8"?>
<policyDocument xmlns="http://schemas.microsoft.com/wse/2003/06/Policy">
  <mappings xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy">
    <defaultEndpoint>
      <defaultOperation>
        <request policy="#Sign-Username" />
        <response policy="" />
        <fault policy="" />
      </defaultOperation>
    </defaultEndpoint>
  </mappings>
  <policies xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <wsp:Policy wsu:Id="Sign-Username"
      xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy"
      xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" >
      <SecurityToken wsp:Usage="wsp:Required" xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
        <TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</TokenType>
      </SecurityToken>
      <wssp:Confidentiality wsp:Usage="wsp:Required"
        xmlns:wssp="http://schemas.xmlsoap.org/ws/2002/12/secext">
        <wssp:KeyInfo>
          <SecurityToken xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
            <wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</wssp:TokenType>
            <wssp:Claims>
              <wssp:SubjectName MatchType="wssp:Exact">
                INSERT-UNIQUE-USERNAME</wssp:SubjectName>
              <wssp:UsePassword Type="wssp:PasswordDigest"
                wsp:Usage="wsp:Required" />
            </wssp:Claims>
          </SecurityToken>
        </wssp:KeyInfo>
        <wssp:MessageParts Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
          wsp:Body()
        </wssp:MessageParts>
      </wssp:Confidentiality>
      <wssp:Integrity wsp:Usage="wsp:Required"
        xmlns:wssp="http://schemas.xmlsoap.org/ws/2002/12/secext">
        <wssp:TokenInfo>
          <SecurityToken xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
            <wssp:TokenType>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken</wssp:TokenType>
            <wssp:Claims>
                <wssp:SubjectName MatchType="wssp:Exact">
                  INSERT-UNIQUE-USERNAME</wssp:SubjectName>
                <wssp:UsePassword Type="wssp:PasswordDigest"
                  wsp:Usage="wsp:Required" />
            </wssp:Claims>
          </SecurityToken>
        </wssp:TokenInfo>
        <wssp:MessageParts Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
          wsp:Body() wsp:Header(wsa:To) wsp:Header(wsa:Action)
          wsp:Header(wsa:MessageID) wsp:Header(wsa:From)
        </wssp:MessageParts>
      </wssp:Integrity>
    </wsp:Policy>
  </policies>
</policyDocument>

- Save the file
- Right click the CommunityServerWeb project > Rebuild

8. Add code to DNN
- Open the DotNetNuke solution in Visual Studio e.g. double click the following sln file C:\Inetpub\DotNetNuke3013\DotNetNuke.sln
- Right click the DotNetNuke project and select WSE Settings 2.0...
- Check "Enable this project for Web Services Enhancements"
- Check "Enable Microsoft Web Services Enhancement Soap Extensions"
- Click OK
- Note: this will make changes to the web.config file and add a reference to Microsoft.Web.Services2.dll

- In the DotNetNuke project, right click Web References and click Add Web Reference
- Enter the URL http://localhost/cs/userservice.asmx and click GO
- Change the Web reference name to CommunityServer
- Click Add Reference

- Open the file /components/Users/UserController.vb
- Add the following Imports statements:
Imports Microsoft.Web.Services2.Security
Imports Microsoft.Web.Services2.Security.Tokens

- In the Private Methods Region, in Private Function DeleteUser, add the following code before the line "Return CanDelete"

                ''' -------------------------------------------------------------------------
                ''' Start Community Server Deactivate User
                ''' -------------------------------------------------------------------------
                Dim token As UsernameToken = New UsernameToken("INSERT-UNIQUE-USERNAME", "INSERT-UNIQUE-PASSWORD", PasswordOption.SendHashed)
                Dim cs As CommunityServer.UserServiceWse = New CommunityServer.UserServiceWse
                cs.RequestSoapContext.Security.Timestamp.TtlInSeconds = 300
                cs.RequestSoapContext.Security.Tokens.Add(token)
                cs.RequestSoapContext.Security.Elements.Add(New EncryptedData(token))
                ' sign the UsernameToken
                cs.RequestSoapContext.Security.Elements.Add(New MessageSignature(token))
                If CanDelete Then
                    Dim result As Boolean
                    result = cs.DeactivateUser(objUser.Membership.Username)
                End If
                ''' -------------------------------------------------------------------------
                ''' End Community Server Deactivate User
                ''' -------------------------------------------------------------------------

- In the Public Methods Region, in Public Function AddUser (the second function of this name), add the following code after the line "Try"

                ''' -------------------------------------------------------------------------
                ''' Start Community Server Check CanCreateUser
                ''' -------------------------------------------------------------------------
                Dim token As UsernameToken = New UsernameToken("INSERT-UNIQUE-USERNAME", "INSERT-UNIQUE-PASSWORD", PasswordOption.SendHashed)
                Dim cs As CommunityServer.UserServiceWse = New CommunityServer.UserServiceWse
                cs.RequestSoapContext.Security.Timestamp.TtlInSeconds = 300
                cs.RequestSoapContext.Security.Tokens.Add(token)
                cs.RequestSoapContext.Security.Elements.Add(New EncryptedData(token))
                ' sign the UsernameToken
                cs.RequestSoapContext.Security.Elements.Add(New MessageSignature(token))
                Dim result As String
                result = cs.CanCreateUser(objUser.Membership.Username, objUser.Membership.Email)
                ' end processing and return result if CS would reject this new user
                If result = "DuplicateUserName" Then
                    Return -1 * CType(MembershipCreateStatus.DuplicateUserName, Integer)
                End If
                If result = "DuplicateEmail" Then
                    Return -1 * CType(MembershipCreateStatus.DuplicateEmail, Integer)
                End If
                If result = "InvalidUserName" Then
                    Return -1 * CType(MembershipCreateStatus.InvalidUserName, Integer)
                End If
                ''' -------------------------------------------------------------------------
                ''' End Community Server Check CanCreateUser
                ''' -------------------------------------------------------------------------

- In the same function, add the following before the line "Return UserId"

                ''' -------------------------------------------------------------------------
                ''' Start Community Server Create User
                ''' -------------------------------------------------------------------------
                If UserId <> -1 Then
                    result = cs.CreateUser(objUser.Membership.Username, objUser.Membership.Password, objUser.Membership.Email)
                End If
                ''' -------------------------------------------------------------------------
                ''' End Community Server Create User
                ''' -------------------------------------------------------------------------

- In the Public Methods Region, in Public Function SetPassword (the second function of this name), add the following code before the line "Catch ex As Exception"

                ''' -------------------------------------------------------------------------
                ''' Start Community Server Change Password
                ''' -------------------------------------------------------------------------
                If confirmPassword = newPassword Then
                    Dim token As UsernameToken = New UsernameToken("INSERT-UNIQUE-USERNAME", "INSERT-UNIQUE-PASSWORD", PasswordOption.SendHashed)
                    Dim cs As CommunityServer.UserServiceWse = New CommunityServer.UserServiceWse
                    cs.RequestSoapContext.Security.Timestamp.TtlInSeconds = 300
                    cs.RequestSoapContext.Security.Tokens.Add(token)
                    cs.RequestSoapContext.Security.Elements.Add(New EncryptedData(token))
                    ' sign the UsernameToken
                    cs.RequestSoapContext.Security.Elements.Add(New MessageSignature(token))
                    Dim result As Boolean
                    result = cs.ChangePassword(objUser.Membership.Username, oldPassword, newPassword)
                End If
                ''' -------------------------------------------------------------------------
                ''' End Community Server Change Password
                ''' -------------------------------------------------------------------------

- In the Public Methods Region, in Public Sub UpdateUser, add the following code before the line "Catch ex As Exception"

                ''' -------------------------------------------------------------------------
                ''' Start Community Server Update User
                ''' -------------------------------------------------------------------------
                Dim token As UsernameToken = New UsernameToken("INSERT-UNIQUE-USERNAME", "INSERT-UNIQUE-PASSWORD", PasswordOption.SendHashed)
                Dim cs As CommunityServer.UserServiceWse = New CommunityServer.UserServiceWse
                cs.RequestSoapContext.Security.Timestamp.TtlInSeconds = 300
                cs.RequestSoapContext.Security.Tokens.Add(token)
                cs.RequestSoapContext.Security.Elements.Add(New EncryptedData(token))
                ' sign the UsernameToken
                cs.RequestSoapContext.Security.Elements.Add(New MessageSignature(token))
                Dim result As Boolean
                result = cs.UpdateUser(objUser.Membership.Username, objUser.Membership.Email, objUser.Membership.Approved.ToString)
                ''' -------------------------------------------------------------------------
                ''' End Community Server Update User
                ''' -------------------------------------------------------------------------

- Right click the DotNetNuke project > Rebuild

9. Modify CS URLS and UI
- In the CommunityServerWeb project open the file /Themes/default/Skins/Skin-EditProfile.ascx
- Switch to the HTML view and search for id="PrivateEmail"
- Add Enabled="False" to this TextBox
- Save the file

- In the CommunityServerWeb project open the file SiteUrls.config (see the User paths section)
- Direct the CS Registration link to the DNN address e.g:
 - Change:  <url name="user_Register" location = "user" path="CreateUser.aspx?ReturnUrl={0}" />
 - To:  <url name="user_Register" location = "" path="http://localhost/dotnetnuke/Home/tabid/36/ctl/Register/Default.aspx" />
- Direct the CS Password link to the DNN address e.g:
 - Change: <url name="user_ChangePassword" location = "user" path="ChangePassword.aspx" />
 - To:  <url name="user_ChangePassword" location = "" path="http://localhost/dotnetnuke/Home/tabid/36/ctl/Register/Default.aspx" />
- Save the file

10. Add a menu link
- Login to http://localhost/dotnetnuke using the admin account
- Add a page named Community, allow All Users to view the page, set the Link Url to "URL" and set the Location to http://localhost/cs

** NOTE: The values INSERT-UNIQUE-USERNAME and INSERT-UNIQUE-PASSWORD should be changed
to your own values but could be left as-is for development environments, they are used in:
- CS, UserService.asmx.cs, once each
- CS, policyCache.config, username only in two different places
- DNN, UserController.vb, once each for each DNN function changed

** You should now be able to:
- Register a new user using DNN, the new user will also be added to CS
- Login (from DNN or CS) without the "Remember Login" option and remain logged into both CS and DNN using the same browser window (or same thread/process)
- Login (from DNN or CS) with the "Remember Login" option and remain logged into both CS and DNN indefinately using any browser window
- Logout from CS or DNN
- Change the user password using the DNN interface with the change being synchronised in CS (CS page will redirect to DNN)
- Change the user email address using the DNN interface with the change being synchronised in CS (CS TextBox is now disabled)
- Remove the user Authorization in DNN and have the change synchronised in CS (this will not synch if changed in CS)
- Delete the user using the DNN interface (deleted from DNN) and have the user disapproved
in CS with their email address changed to "[MemberID].inactive@host.local" and the
password reset (users cannot be deleted from CS). The username will not be able to be
registered a second time in DNN or CS

** The functionality of this SSO Method has received very limited testing.
Testing has been confined to the environment and changes outlined in this post.
For example, testing was not carried out using Private or Verified User Registration

I look forward to your comments, suggestions and improvements.

Regards,
gsc4 (Steve).




UPDATE: fatatiba has made a post about how to share the membership database here:
http://www.communityserver.org/forums/481547/ShowPost.aspx - It is good to see that
sharing the membership database in this way is possible, I can't wait to try it
out and see what the data looks like. However, no change has been made to the DNN
or CS data using the method outlined above, it is only synchronised.
I feel this may be a cleaner approach with regard to the data which may allow for
an easier move to a different solution later (I haven't tried fatatiba's method yet).
I'm sure each method has relative strengths and weaknesses depending on the
environment or requirement it is applied to, and let's not forget that a module is
on the way and so are changes to Membership.

THANKS, to John Hodgkinson for the idea.

UPDATE: I have added the following to the CanCreateUser WebMethod in UserService.asmx.cs in the CommunityServerWeb project:

// Check escape character

if ( Regex.IsMatch(username,@"[\\]+") )

result = "InvalidUserName";

 

The whole function becomes:

[WebMethod]

public string CanCreateUser(string username, string email)

{

string result = "Success";

// Check if username already exists

User usernameLookup = Users.FindUserByUsername( username );

if (usernameLookup.UserID != 0)

result = "DuplicateUserName";

// Check if email already exists

User emailLookup = Users.FindUserByEmail(email);

if (emailLookup.Member.Email != null)

result = "DuplicateEmail";

// Check if username is disallowed

if ( DisallowedNames.NameIsDisallowed(username) == true )

result = "InvalidUserName";

// Check if username meets site regular expression

if ( !Regex.IsMatch(username,"^" + SiteSettingsManager.GetSiteSettings().UsernameRegex) )

result = "InvalidUserName";

 

// Check escape character

if ( Regex.IsMatch(username,@"[\\]+") )

result = "InvalidUserName";

// Otherwise return success

return result;

}

EDIT: You may need to add the following along with the existing using statements at the begining of the file:
  using System.Text.RegularExpressions;



posted on 2006-04-05 12:05  飓风之眼  阅读(484)  评论(0编辑  收藏  举报