예제 #1
0
        public static void AddResponseCookiesToContainer(WinHttpRequestState state)
        {
            HttpRequestMessage request         = state.RequestMessage;
            SafeWinHttpHandle  requestHandle   = state.RequestHandle;
            CookieContainer    cookieContainer = state.Handler.CookieContainer;

            Debug.Assert(state.Handler.CookieUsePolicy == CookieUsePolicy.UseSpecifiedCookieContainer);
            Debug.Assert(cookieContainer != null);

            // Get 'Set-Cookie' headers from response.
            char[] buffer = null;
            uint   index  = 0;
            string cookieHeader;

            WinHttpTraceHelper.Trace("WINHTTP_QUERY_SET_COOKIE");
            while (WinHttpResponseParser.GetResponseHeader(
                       requestHandle, Interop.WinHttp.WINHTTP_QUERY_SET_COOKIE, ref buffer, ref index, out cookieHeader))
            {
                WinHttpTraceHelper.Trace(cookieHeader);
                try
                {
                    cookieContainer.SetCookies(request.RequestUri, cookieHeader);
                    WinHttpTraceHelper.Trace(cookieHeader);
                }
                catch (CookieException)
                {
                    // We ignore malformed cookies in the response.
                    WinHttpTraceHelper.Trace("Ignoring invalid cookie: {0}", cookieHeader);
                }
            }
        }
예제 #2
0
        public void CheckResponseForAuthentication(
            WinHttpRequestState state,
            ref uint proxyAuthScheme,
            ref uint serverAuthScheme)
        {
            uint supportedSchemes   = 0;
            uint firstSchemeIgnored = 0;
            uint authTarget         = 0;
            Uri  uri = state.RequestMessage.RequestUri;

            state.RetryRequest = false;

            // Check the status code and retry the request applying credentials if needed.
            var statusCode = (HttpStatusCode)WinHttpResponseParser.GetResponseHeaderNumberInfo(
                state.RequestHandle,
                Interop.WinHttp.WINHTTP_QUERY_STATUS_CODE);

            switch (statusCode)
            {
            case HttpStatusCode.Unauthorized:
                if (state.ServerCredentials == null || state.LastStatusCode == HttpStatusCode.Unauthorized)
                {
                    // Either we don't have server credentials or we already tried
                    // to set the credentials and it failed before.
                    // So we will let the 401 be the final status code returned.
                    break;
                }

                state.LastStatusCode = statusCode;

                // Determine authorization scheme to use. We ignore the firstScheme
                // parameter which is included in the supportedSchemes flags already.
                // We pass the schemes to ChooseAuthScheme which will pick the scheme
                // based on most secure scheme to least secure scheme ordering.
                if (!Interop.WinHttp.WinHttpQueryAuthSchemes(
                        state.RequestHandle,
                        out supportedSchemes,
                        out firstSchemeIgnored,
                        out authTarget))
                {
                    // WinHTTP returns an error for schemes it doesn't handle.
                    // So, we need to ignore the error and just let it stay at 401.
                    break;
                }

                // WinHTTP returns the proper authTarget based on the status code (401, 407).
                // But we can validate with assert.
                Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_SERVER);

                serverAuthScheme = ChooseAuthScheme(supportedSchemes);
                if (serverAuthScheme != 0)
                {
                    if (SetWinHttpCredential(
                            state.RequestHandle,
                            state.ServerCredentials,
                            uri,
                            serverAuthScheme,
                            authTarget))
                    {
                        state.RetryRequest = true;
                    }
                }

                break;

            case HttpStatusCode.ProxyAuthenticationRequired:
                if (state.LastStatusCode == HttpStatusCode.ProxyAuthenticationRequired)
                {
                    // We tried already to set the credentials.
                    break;
                }

                state.LastStatusCode = statusCode;

                // If we don't have any proxy credentials to try, then we end up with 407.
                ICredentials proxyCreds = state.Proxy == null ?
                                          state.DefaultProxyCredentials :
                                          state.Proxy.Credentials;
                if (proxyCreds == null)
                {
                    break;
                }

                // Determine authorization scheme to use. We ignore the firstScheme
                // parameter which is included in the supportedSchemes flags already.
                // We pass the schemes to ChooseAuthScheme which will pick the scheme
                // based on most secure scheme to least secure scheme ordering.
                if (!Interop.WinHttp.WinHttpQueryAuthSchemes(
                        state.RequestHandle,
                        out supportedSchemes,
                        out firstSchemeIgnored,
                        out authTarget))
                {
                    // WinHTTP returns an error for schemes it doesn't handle.
                    // So, we need to ignore the error and just let it stay at 401.
                    break;
                }

                // WinHTTP returns the proper authTarget based on the status code (401, 407).
                // But we can validate with assert.
                Debug.Assert(authTarget == Interop.WinHttp.WINHTTP_AUTH_TARGET_PROXY);

                proxyAuthScheme    = ChooseAuthScheme(supportedSchemes);
                state.RetryRequest = true;
                break;

            default:
                if (state.PreAuthenticate && serverAuthScheme != 0)
                {
                    SaveServerCredentialsToCache(uri, serverAuthScheme, state.ServerCredentials);
                }
                break;
            }
        }