0

我正在尝试在 C# 中为 WMS 2009 创建一个自定义身份验证插件。

我设法实现了一些出于某种原因阻止所有请求的东西......

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

谁能发现为什么会这样?

另外,有什么方法可以查看已经安装在服务器上的标准匿名身份验证插件的代码吗?它在某个地方的集会中吗?

谢谢。

4

1 回答 1

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);

存储从 LogonUser 调用返回的 IntPtr 并实现 GetImpersonationToken 方法,如下所示:

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

不知何故,插件能够将该整数值绑定回真实的 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
}
于 2010-06-02T13:18:37.043 回答