This will quite possibly be a very naive question about the NetworkCredential class. Excuse my inexperience please...
I create a NetworkCredential using a username, password, and domain. I then use HttpWebRequest to interact with a URI. The NetworkCredential is used to authenticate against this URI by setting HttpWebRequest.Credentials. This has been working fine.
Throwing some redirection into the mix has caused problems however. I'm now getting 401's returned. Does this mean that my credential object is tied only to a specific URI? Where does that happen? I don't see anywhere in the NetworkCredential class that this happens.
Maybe the process of setting HttpWebRequest.Credentials ties that credential to just the URI that was specified in the constructor of HttpWebRequest...
If this is the case, how does one get around this problem?
FYI, the authentication scheme is Kerberos. I would use the DefaultCredentials except the user may be using a local user account (not in Kerberos). The user will however be entering a valid Kerberos account into the program (using a login dialog I've written).
I've written a method that will walk through the redirects manually to create a NetworkCredential that points to the same hostname (but not exact URI) I plane to use. Code below:
/// <summary>
/// Get a NetworkCredentials instance associated with location.
/// </summary>
/// <param name="location">A URI to test user credentials against.</param>
/// <param name="userName">Username.</param>
/// <param name="password">Password.</param>
/// <param name="domain">开发者_开发百科;Domain.</param>
/// <param name="throwExceptions">Throws exceptions on error if true.</param>
/// <returns>On success a NetworkCredential instance is returned. If throwExceptions equals
/// true all exceptions will propogate up the stack, otherwise null is returned.</returns>
public static NetworkCredential GetCredential(Uri location, string userName,
SecureString password, string domain, bool throwExceptions = true)
{
NetworkCredential ret = null;
try
{
Uri uri = location;
bool redirected = false;
do
{
HttpWebRequest request = WebRequest.Create(uri) as HttpWebRequest;
ret = new NetworkCredential(userName, password, domain);
request.UseDefaultCredentials = false;
request.Credentials = ret;
request.AllowAutoRedirect = false;
HttpWebResponse resp = request.GetResponse() as HttpWebResponse;
if (resp.StatusCode == HttpStatusCode.Redirect)
{
uri = new Uri(resp.GetResponseHeader("Location"));
redirected = true;
}
else
{
redirected = false;
}
} while (redirected);
}
catch
{
if (throwExceptions)
{
throw;
}
ret = null;
}
return ret;
}
// NetworkCredential stores authentication to a single internet resource
// supplies credentials in password-based authentication schemes such as basic, digest, NTLM, and Kerberos.
NetworkCredential networkCredential = new NetworkCredential("username", "password");
WebRequest webRequest = HttpWebRequest.Create("www.foobar.com");
webRequest.Credentials = networkCredential;
// to use the same credential for multiple internet resources...
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(new Uri("www.foobar.com"), "Basic", networkCredential);
credentialCache.Add(new Uri("www.example.com"), "Digest", networkCredential);
// now based on the uri and the authetication, GetCredential method would return the
// appropriate credentials
webRequest.Credentials = credentialCache;
More info at here and here
精彩评论