2009-05-18 89 views
0

我正在嘗試在C#中爲WMS 2009創建自定義身份驗證插件。WMS身份驗證插件

我設法實現的東西,由於某種原因,阻止所有的請求......

[ComVisible(true)] 
[Guid("C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE")] 
public class AuthenticationPlugin : IWMSBasicPlugin, IWMSAuthenticationPlugin, IWMSAuthenticationContext 
    private const string SubKey = "SOFTWARE\\Microsoft\\Windows Media\\Server\\RegisteredPlugins\\Authentication\\{C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE}"; 

    [ComRegisterFunction] 
    public static void RegisterFunction(Type t) 
    { 
     try 
     { 
      RegistryKey regHKLM = Registry.LocalMachine; 
      regHKLM = regHKLM.CreateSubKey(SubKey); 
      regHKLM.SetValue(null, "UC WMS Authentication plugin"); 

      RegistryKey regHKCR = Registry.ClassesRoot; 
      regHKCR = regHKCR.CreateSubKey("CLSID\\{C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE}\\Properties"); 
      regHKCR.SetValue("Name", CustomC WMS Authentication plugin"); 
      regHKCR.SetValue("Author", "Me"); 
      regHKCR.SetValue("CopyRight", "Copyright 2009. All rights reserved"); 
      regHKCR.SetValue("Description", "Enables custom WMS authentication"); 
     } 
     catch (Exception error) 
     { 
      Console.WriteLine(error.Message, "Inside RegisterFunction(). Cannot Register."); 
     } 
    } 

    [ComUnregisterFunction] 
    public static void UnRegisterFunction(Type t) 
    { 
     try 
     { 
      RegistryKey regHKLM = Registry.LocalMachine; 
      regHKLM.DeleteSubKey(SubKey); 

      RegistryKey regHKCR = Registry.ClassesRoot; 
      regHKCR.DeleteSubKeyTree("CLSID\\{C0A0B38C-C4FE-43B5-BE9E-C100A83BBCEE}"); 
      regHKCR.DeleteSubKeyTree("CSEventTest.CSEventPlugin"); 
     } 
     catch (Exception error) 
     { 
      Console.WriteLine(error.Message, "Cannot delete a subkey."); 
     } 
    } 

    #region IWMSBasicPlugin Members 

    public void InitializePlugin(IWMSContext serverContext, WMSNamedValues namedValues, IWMSClassObject classFactory) 
    { 
    } 

    public void ShutdownPlugin() 
    { 
    } 

    public void EnablePlugin(ref int flags, ref int heartbeatPeriod) 
    { 
    } 

    public void DisablePlugin() 
    { 
    } 

    public object GetCustomAdminInterface() 
    { 
     return null; 
    } 

    public void OnHeartbeat() 
    { 
    } 

    #endregion 

    #region IWMSAuthenticationPlugin Members 

    public IWMSAuthenticationContext CreateAuthenticationContext() 
    { 
     return (IWMSAuthenticationContext)this; 
    } 

    public int GetFlags() 
    { 
     return Convert.ToInt32(WMS_AUTHENTICATION_FLAGS.WMS_AUTHENTICATION_ANONYMOUS, CultureInfo.InvariantCulture); 
    } 

    public string GetPackageName() 
    { 
     return "Custom WMS Authentication"; 
    } 

    public string GetProtocolName() 
    { 
     return "Basic"; 
    } 

    #endregion 

    #region IWMSAuthenticationContext Members 

    public void Authenticate(object responseBlob, IWMSContext userContext, IWMSContext presentationContext, IWMSCommandContext commandContext, IWMSAuthenticationCallback callBack, object context) 
    { 
     callBack.OnAuthenticateComplete(WMS_AUTHENTICATION_RESULT.WMS_AUTHENTICATION_SUCCESS, null, context); 
    } 

    public IWMSAuthenticationPlugin GetAuthenticationPlugin() 
    { 
     return (IWMSAuthenticationPlugin)this; 
    } 

    public string GetImpersonationAccountName() 
    { 
     return String.Empty; 
    } 

    public int GetImpersonationToken() 
    { 
     return 0; 
    } 

    public string GetLogicalUserID() 
    { 
     return this.GetImpersonationAccountName(); 
    } 

    #endregion 
} 

任何人都可以找出爲什麼會這樣?

此外,有沒有什麼辦法可以看看已經安裝在服務器上的標準匿名身份驗證插件的代碼?它在某個地方是在一個集會嗎?

謝謝。

回答

0

我遇到了同樣的問題。從Authenticate方法返回成功狀態是不夠的。

您實施的方法必須檢索有效Windows登錄的句柄。搜索網上有關如何調用此方法C#示例:http://msdn.microsoft.com/en-us/library/aa378184%28VS.85%29.aspx

bool result = LogonAPI.LogonUser("username", "domain", "password", LogonAPI.LOGON32_LOGON_NETWORK, LogonAPI.LOGON32_PROVIDER_DEFAULT, ref _userToken); 

Store中的IntPtr你從LogonUser的回調並實現GetImpersonationToken方法,像這樣:

public int GetImpersonationToken() 
{ 
    return _userToken.ToInt32(); 
} 

莫名其妙的插件in能夠將該整數值返回到真實的Windows帳戶。我在Power Users組中的服務器上創建了一個本地帳戶,並在服務器是域的情況下使用LogonUser方法中的用戶名和密碼。一旦能夠這樣做,媒體應該流。

我的整個IWMSAuthenticationPlugin如下(它使用基本身份驗證):

public class AuthenticationContext : IWMSAuthenticationContext 
{ 
#region IWMSAuthenticationContext Members 

private WMS_AUTHENTICATION_RESULT _result; 

private readonly IWMSAuthenticationPlugin _plugin; 
private Credentials _credentials; 
private IntPtr _userToken; 

public AuthenticationContext(IWMSAuthenticationPlugin plugin) 
{ 
    _plugin = plugin; 
} 

public void Authenticate(object responseBlob, IWMSContext pUserCtx, IWMSContext pPresentationCtx, IWMSCommandContext pCommandContext, IWMSAuthenticationCallback pCallback, object context) 
{ 
    // must be Unicode. If it isn't, the 
    // challenge isn't sent correctly 
    Encoding enc = Encoding.Unicode; 
    byte[] response; 
    byte[] challenge = enc.GetBytes(""); 

    try 
    { 
     response = (byte[])responseBlob; 
     if (response.Length == 0) 
     { 
      // The client requested authentication; prepare the 
      // challenge response to send to the client. In order to 
      // do Basic authentication, be sure to return "Basic" from 
      // your implementation of IWMSAuthenticationPlugin.GetProtocolName() 
      string challengeTxt = "WWW-Authenticate: Basic realm=\"Domain\""; 
      challenge = enc.GetBytes(challengeTxt); 

      _result = WMS_AUTHENTICATION_RESULT.WMS_AUTHENTICATION_CONTINUE; 
     } 
     else 
     { 
      // parses Base64 encoded response and gets passed in credentials 
      SetCredentials(enc.GetString(response)); 

      LdapConnection ldc = new LdapConnection("Domain"); 
      NetworkCredential nc = new NetworkCredential(_credentials.Username, _credentials.Password, "Domain"); 
      ldc.Credential = nc; 
      ldc.AuthType = AuthType.Negotiate; 
      ldc.Bind(nc); // user has authenticated at this point, as the credentials were used to login to the dc. 

      // must log in with a local windows account and get a handle for the account. 
      // even if success is returned, the plugin still needs a valid windows account 
      // to stream the file.      
      bool result = LogonAPI.LogonUser("local username", "local domain", "local password", LogonAPI.LOGON32_LOGON_NETWORK, LogonAPI.LOGON32_PROVIDER_DEFAULT, ref _userToken); 
      _result = WMS_AUTHENTICATION_RESULT.WMS_AUTHENTICATION_SUCCESS; 
     } 
    } 
    catch (LdapException e) 
    { 
     _result = WMS_AUTHENTICATION_RESULT.WMS_AUTHENTICATION_DENIED; 
    } 
    catch (Exception e) 
    { 
     _result = WMS_AUTHENTICATION_RESULT.WMS_AUTHENTICATION_ERROR; 
    } 
    finally 
    { 
     pCallback.OnAuthenticateComplete(_result, challenge, context); 
    } 
} 

public IWMSAuthenticationPlugin GetAuthenticationPlugin() 
{ 
    return _plugin; 
} 

public string GetImpersonationAccountName() 
{ 
    return "Domain\\" + _credentials.Username; 
} 

public int GetImpersonationToken() 
{ 
    // somehow the plugin knows how this integer ties to a windows account. 
    return _userToken.ToInt32(); 
} 

public string GetLogicalUserID() 
{ 
    return GetImpersonationAccountName(); 
} 

public void SetCredentials(string responseStr) 
{ 
    // for whatever reason, the responseStr has an extra character 
    // tacked on the end that blows up the conversion. When converting 
    // from the Base64 string, remove that last character. 
    string decoded = new UTF8Encoding().GetString(Convert.FromBase64String(responseStr.Substring(0, responseStr.Length - 1))); 

    // now that the string has been decoded and is now in the format 
    // username:password, parse it further into a Username and Password 
    // struct. 
    _credentials = new Credentials(decoded); 
} 

#endregion 
} 
+0

對不起,大規模延遲 - 比較合適,雖然我還沒有嘗試過(不工作在這個項目了)。謝謝。 – charisk 2010-07-09 10:35:44