WMS认证插件

发布于 2024-07-20 04:06:17 字数 3738 浏览 5 评论 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
}

任何人都可以发现为什么会发生这种情况吗?

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

谢谢。

I'm trying to create a custom authentication plugin for WMS 2009 in C#.

I managed to implement something that for some reason blocks all requests...

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

Can anyone spot why this is happening?

Also, is there any way I could have a look at the code for the standard Anonymous Authentication plugin already installed on the server? Is it in an assembly somewhere?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别低头,皇冠会掉 2024-07-27 04:06:17

我遇到了同样的问题。 从 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
}

I ran into the same issue. It isn't enough to return success status from the Authenticate method.

Your implemented method must retrieve a handle to a valid Windows Login. Search the net for C# examples of how to call this method: 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 the IntPtr you get back from the LogonUser call and implement the GetImpersonationToken method like so:

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

Somehow the plug-in is able to tie that integer value back to a real windows account. I created a local account on the server that was in the Power Users group and used its username and password in the LogonUser method with the server being the domain. Once it is able to do so, the media should stream.

My whole IWMSAuthenticationPlugin is as follows (it uses basic authentication):

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文