문제

I have a simple ASP.NET MVC site with a single controller and some actions in it. A user needs to log in to access any action (Windows Authentication, 'Authorize' attribue on the controller class).

When accessing the site via a browser everything works fine.

On the client, I would also like to access the site via System.Net.WebClient. I set the credentials and all actions that return a View work just fine.

But when I try to access an action that tries to make a redirect (using Controller's Rediret() method) the server returns a 401 Unauthorized.

I've read about problems with WebClient and Windows authentication but the stuff I found does not seem to apply here, because everything works except for the redirects.

도움이 되었습니까?

해결책

So after some weeks I had some time to come back to this problem and as it turns out, it has nothing to do with ASP.NET at all and it's WebClient's fault. WebClient clears its credentials before following a redirect, so in this case the original request was successful but the error the occurred when WebClient tried to access the page it had been redirected to, because authentication is necessary for the target, too.

Unfortunately, you cannot just toggle this behavior via a Property. So my solution looks like this.

//Credentials necessary for the request(s)
var cred = new NetworkCredential(username, password);

//Create initial request
var request = (HttpWebRequest)WebRequest.Create(url);
request.AllowAutoRedirect = false;
request.Credentials = cred;

//Get response to first request
var response = (HttpWebResponse)request.GetResponse();

//Follow redirects
while (response.StatusCode == HttpStatusCode.Redirect && maxRedirects > 0)
{
    //Build new URI for redirect target
    var uri = response.ResponseUri;
    url = String.Format("{0}://{1}:{2}{3}", uri.Scheme, uri.Host, uri.Port, response.GetResponseHeader("Location"));    

    //Create new request
    request = (HttpWebRequest)WebRequest.Create(url);
    request.AllowAutoRedirect = false;
    request.Credentials = cred;

    //Get new response
    response = request.GetResponse() as HttpWebResponse;

    maxRedirects--;
}

//Get the response's content
var sReader = new StreamReader(response.GetResponseStream());
string responseStr = sReader.ReadToEnd();

Instead of using WebClient, I'm using HttpWebRequest and HttpWebResponse and follow the Redirect manually. Before making the request, I set the credentials necessary to complete the request

다른 팁

I found a comment in the HttpWebRequest code that describes how to solve this issue:

// Do _not_ automatically reuse the credential object on a redirection unless
// it is specifically a CredentialCache or SystemNetworkCredential object.
//
// The CredentialCache object stores credentials for specific URIs and
// authentication schemes.  Therefore the application has given explicit
// permission to use/send those credentials to a specific site using a
// specific authentication scheme.
//
// A SystemNetworkCredential object represents current default credentials.
// It is deemed safe to reuse them on an automatic redirection since the
// authentication SSP are trusted to only use safe authentication schemes
// for default credentials.

So all I had to do to get my credentials to work on redirects is create a CredentialCache object instead of just a NetworkCredential object.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top