开发者

Webbrowser control authenticate not working when access file folder

I have a .Net 2.0 WinForm application, it has a WebBrowser control which is used to access a secured network drive, this network drive only granted access to a few special account and the application needs to impersonate one reader account to read the PDF file.

I used the LogonUser and the application was able to impersonate the reader account to see the file names under the folder, but then when I use webBrowser1.Navigate(new Uri(filePath))m, I got access denied.

So after research, I know that I must do the COM stuff which I have never used before. Ok, after many hours online and trial/error, I used IAuthenticate,IOleClientSite, IServiceProvider, I got the struture worked out to where it will work fine for using the supplied user credential to access a secure website, it won't popup box ask for Username and password and will open the website correctly.

Yet, if I replace the website URL to the secure file path, it doesn't work at all.

The LogOnUser impersonate stuff is actually not needed for the webbrowser to access the secure websites here. But I didn't know if it was needed for accessing file folders.I tried to add the LogOnUser and wrap the webbrowser.Navigate(path), It didn't help.

Why this works for website and not file folders?

The full test code I used are pasted here:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Security.Principal; // WindowsImpersonationContext
using System.Security.Permissions; // PermissionSetAttribute
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;
using System.Security;


namespace WebAuthenticateTest
{
    #region COM Interfaces

    [ComImport,
    Guid("00000112-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleObject
    {
        void SetClientSite(IOleClientSite pClientSite);
        void GetClientSite(IOleClientSite ppClientSite);
        void SetHostNames(object szContainerApp, object szContainerObj);
        void Close(uint dwSaveOption);
        void SetMoniker(uint dwWhichMoniker, object pmk);
        void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk);
        void InitFromData(IDataObject pDataObject, bool
        fCreation, uint dwReserved);
        void GetClipboardData(uint dwReserved, IDataObject开发者_如何学C ppDataObject);
        void DoVerb(uint iVerb, uint lpmsg, object pActiveSite,
        uint lindex, uint hwndParent, uint lprcPosRect);
        void EnumVerbs(object ppEnumOleVerb);
        void Update();
        void IsUpToDate();
        void GetUserClassID(uint pClsid);
        void GetUserType(uint dwFormOfType, uint pszUserType);
        void SetExtent(uint dwDrawAspect, uint psizel);
        void GetExtent(uint dwDrawAspect, uint psizel);
        void Advise(object pAdvSink, uint pdwConnection);
        void Unadvise(uint dwConnection);
        void EnumAdvise(object ppenumAdvise);
        void GetMiscStatus(uint dwAspect, uint pdwStatus);
        void SetColorScheme(object pLogpal);
    }

    [ComImport,
    Guid("00000118-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleClientSite
    {
        void SaveObject();
        void GetMoniker(uint dwAssign, uint dwWhichMoniker, object ppmk);
        void GetContainer(object ppContainer);
        void ShowObject();
        void OnShowWindow(bool fShow);
        void RequestNewObjectLayout();
    }

    [ComImport,
    GuidAttribute("6d5140c1-7436-11ce-8034-00aa006009fa"),
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown),
    ComVisible(false)]
    public interface IServiceProvider
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int QueryService(ref Guid guidService, ref Guid riid, out IntPtr
        ppvObject);
    }

    [ComImport, GuidAttribute("79EAC9D0-BAF9-11CE-8C82-00AA004BA90B"),
    InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown),
    ComVisible(false)]
    public interface IAuthenticate
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int Authenticate(ref IntPtr phwnd,
        ref IntPtr pszUsername,
        ref IntPtr pszPassword
        );
    }

    #endregion
    public partial class Form1 : Form, IOleClientSite, IServiceProvider, IAuthenticate
    {

        public static Guid IID_IAuthenticate = new Guid("79eac9d0-baf9-11ce-8c82-00aa004ba90b");
        public static Guid SID_IAuthenticate = new Guid("79eac9d0-baf9-11ce-8c82-00aa004ba90b");
        public const int INET_E_DEFAULT_ACTION = unchecked((int)0x800C0011);
        public const int S_OK = unchecked((int)0x00000000);
        private WindowsIdentity impersonateID; //impersonate user to access Picis PDF file folder.
        private bool logonFail = false;

        public Form1()
        {
            InitializeComponent();
            GetImpersonateID();

            string oURL = "about:blank";
            webBrowser1.Navigate(oURL);

            object obj = webBrowser1.ActiveXInstance;
            IOleObject oc = obj as IOleObject;
            oc.SetClientSite(this as IOleClientSite);

            System.IntPtr ppvServiceProvider;
            IServiceProvider sp = obj as IServiceProvider;
            sp.QueryService(ref SID_IAuthenticate, ref IID_IAuthenticate, out ppvServiceProvider);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            using (WindowsImpersonationContext impersonatedUser = impersonateID.Impersonate())
            {
                string oURL = "\\\\mydrive\\Reports\\Test\\Test.PDF";                
                webBrowser1.Navigate(new Uri(oURL));
            }
        }

        #region IOleClientSite Members

        public void SaveObject()
        {
            // TODO: Add Form1.SaveObject implementation
        }

        public void GetMoniker(uint dwAssign, uint dwWhichMoniker, object
        ppmk)
        {
            // TODO: Add Form1.GetMoniker implementation
        }

        public void GetContainer(object ppContainer)
        {
            ppContainer = this;
        }

        public void ShowObject()
        {
            // TODO: Add Form1.ShowObject implementation
        }

        public void OnShowWindow(bool fShow)
        {
            // TODO: Add Form1.OnShowWindow implementation
        }

        public void RequestNewObjectLayout()
        {
            // TODO: Add Form1.RequestNewObjectLayout implementation
        }

        #endregion

        #region IServiceProvider Members

        public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
        {
            int nRet = guidService.CompareTo(IID_IAuthenticate); // Zero returned if the compared objects are equal
            if (nRet == 0)
            {
                nRet = riid.CompareTo(IID_IAuthenticate); // Zero returned if the compared objects are equal
                if (nRet == 0)
                {
                    ppvObject = Marshal.GetComInterfaceForObject(this,
                    typeof(IAuthenticate));
                    return S_OK;
                }
            }
            ppvObject = new IntPtr();
            return INET_E_DEFAULT_ACTION;
        }

        #endregion

        #region IAuthenticate Members

        public int Authenticate(ref IntPtr phwnd, ref IntPtr pszUsername, ref IntPtr pszPassword)
        {
            IntPtr sUser = Marshal.StringToCoTaskMemAuto("Read");
            IntPtr sPassword = Marshal.StringToCoTaskMemAuto("mypwd");

            pszUsername = sUser;
            pszPassword = sPassword;
            return S_OK;
        }

        #endregion


        #region Impersonate  code
        //create  a impersonate context

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
            int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

        /* [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
         public extern static bool CloseHandle(IntPtr handle);*/

        /// <summary>
        /// Prepare a WindowsIdentity that has read access to the PDF file folder
        /// </summary>
        private void GetImpersonateID()
        {
            SafeTokenHandle safeTokenHandle = null;
            string user = "Read";
            string domainName = "mydomain";
            string pwd = "mypwd";
            try
            {
                const int LOGON32_PROVIDER_DEFAULT = 0;
                //This parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_INTERACTIVE = 2;

                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(user, domainName, pwd,
                    LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                    out safeTokenHandle);

                if (returnValue)//user successfully logon
                {
                    impersonateID = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());

                }
                else //error impersonate identity
                {
                    int ret = Marshal.GetLastWin32Error();
                    throw new System.ComponentModel.Win32Exception(ret);
                }
            }
            catch (Exception ex)
            {

                logonFail = true;
            }
            finally
            {
                if (safeTokenHandle != null)
                {
                    //safeTokenHandle.Dispose();
                    int i = 1;
                }
            }
        }

        #endregion
    }


    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true)
        {
        }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}


The webrowser only query for IAuthenticate when hosting MSHTML document. If the document is defview, try WNetAddConnection3 with explicit user credentials

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜