2009-05-18 5 views
0

J'essaye de créer un plugin d'authentification personnalisé pour WMS 2009 en C#.Plugin d'authentification WMS

j'ai réussi à mettre en œuvre quelque chose que pour certains blocs raison toutes les demandes ...

[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 
} 

Quelqu'un peut-il repérer pourquoi cela se passe?

De plus, est-ce qu'il y a un moyen de voir le code pour le plugin Anonymous Authentication standard déjà installé sur le serveur? Est-ce dans une assemblée quelque part?

Merci.

Répondre

0

J'ai rencontré le même problème. Il ne suffit pas de renvoyer le statut de réussite à partir de la méthode Authenticate.

Votre méthode implémentée doit récupérer un handle vers une connexion Windows valide. Recherche sur le net pour des exemples C# de comment appeler cette méthode: 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); 

magasin IntPtr vous revenez de l'appel LogonUser et mettre en œuvre la méthode GetImpersonationToken comme ceci:

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

D'une certaine façon le plug- dans est capable de lier cette valeur entière à un compte Windows réel. J'ai créé un compte local sur le serveur qui était dans le groupe Utilisateurs avec pouvoir et utilisé son nom d'utilisateur et mot de passe dans la méthode LogonUser avec le serveur étant le domaine. Une fois qu'il est capable de le faire, le média devrait être diffusé.

Mon tout est IWMSAuthenticationPlugin comme suit (il utilise l'authentification de base):

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

Désolé pour le retard massif - semble à peu près juste, bien que je ne l'ai pas essayé (ne fonctionne pas sur ce projet plus). Merci. – charisk