【问题标题】:Basic authorization in WEB API C# using HttpWebRequestWEB API C# 中使用 HttpWebRequest 的基本授权
【发布时间】:2019-08-27 03:29:03
【问题描述】:

我已经使用 httpweb 请求查找了有关 web api 中基本授权的所有问题,但都没有解决我的问题。我有一个 web api(用 C# 编写),我想为 api 建立基本授权。我还有一个用来调用 api 的网页。但是,它一直返回“(401)未经授权”,我不知道我做错了什么。现在我在代码中使用用户名和密码,但我希望有一个弹出窗口询问凭据。

这是我的网页代码,调用 api:

string url = String.Format("http://example.com");
HttpWebRequest requestObj = (HttpWebRequest)WebRequest.Create(url);
requestObj.Method = "Get";
requestObj.Credentials = new NetworkCredential("testing", "123456");

HttpWebResponse responseObj = null;
responseObj = (HttpWebResponse)requestObj.GetResponse();
string strresult = null;
using (Stream stream = responseObj.GetResponseStream())
{
    StreamReader sr = new StreamReader(stream);
    strresult = sr.ReadToEnd();
    sr.Close();
}

在我的 api 中,我打开了一个名为 BasicAuthenticationAttribute 的类并写了这个:

public class BasicAuthenticationAttribute : AuthorizationFilterAttribute
{
    public static bool IsAuthorizedUser(string Username, string Password)
    {
        return Username == "testing" && Password == "123456";
    }
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        base.OnAuthorization(actionContext);
        if (actionContext.Request.Headers.Authorization != null)
        {
            var authToken = actionContext.Request.Headers.Authorization.Parameter;
            var decodeauthToken = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
            var arrUserNameandPassword = decodeauthToken.Split(':');
            if (IsAuthorizedUser(arrUserNameandPassword[0], arrUserNameandPassword[1]))
            {
                Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(arrUserNameandPassword[0]), null);
            }
            else
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
        }
        else
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        }
    }
}

在我的控制器中,我有这个:

 [BasicAuthentication]
 public class EventsController : ApiController
 {
 }

这是我收到的错误: 远程服务器返回错误:(401) Unauthorized.

【问题讨论】:

  • 你用调试器检查过decodeauthToken吗?
  • 您不需要将“Basic”替换为 String.Empty 吗?我一直认为 Basic Authentication 以 Basic 为名。需要找到我之前复制的例子。
  • @JohnPete22 我的想法完全正确 - 只是想让 OP 使用调试器来解决它:) 假设它完全达到了这一点。
  • @fredrik 我没有,我该怎么做?
  • @JohnPete22 不太确定要替换什么,您认为问题在哪里?

标签: c# html asp.net-web-api httpwebrequest asp.net-authorization


【解决方案1】:

尝试使用授权类型将凭据添加到凭据缓存,而不是直接使用缓存。

    string url = String.Format("http://example.com");
    CredentialCache credentialCache = new CredentialCache();
    credentialCache.Add(new Uri(url), "Basic", new NetworkCredential("testing", "123456"));
    HttpWebRequest requestObj = (HttpWebRequest)WebRequest.Create(url);
    requestObj.PreAuthenticate = true;
    requestObj.Method = "Get";
    requestObj.Credentials = **credentialCache**;
    HttpWebResponse responseObj = null;
    responseObj = (HttpWebResponse)requestObj.GetResponse();
    string strresult = null;
    using (Stream stream = responseObj.GetResponseStream())
    {
        StreamReader sr = new StreamReader(stream);
        strresult = sr.ReadToEnd();
        sr.Close();
    }

【讨论】:

  • 我刚试过你写的,仍然给我同样的信息......有没有办法让弹出窗口询问凭据?
  • 弹出窗口仅在 Windows 授权和域内可用。
  • 一般可以解决。你能调查一下actionContext.Request.Headers.Authorization 的值吗?
  • 好的。在我的代码中缺少requestObj.PreAuthenticate = true;
  • 尝试添加 requestObj.PreAuthenticate = true;它没有改变任何东西
【解决方案2】:

如上述消息中所述,我认为问题在于您没有从身份验证标头中删除“基本”。 https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/basic-authentication

我会怎么做...

string authToken = actionContext.Request.Headers.Authorization.Parameter;
authToken = authToken.Replace("Basic", string.Empty);
var decodeauthToken = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(authToken));

当你分开时试试这个。关于你的实现中唯一与我多次做过的不同的事情。

var arrUserNameandPassword = decodeauthToken.Split(':'c);

【讨论】:

  • 我添加了它,但它仍然给我同样的信息。我确信 api 本身可以工作,因为在我尝试添加身份验证之前一切都很好。
  • 您尝试访问的文件/文件夹是否存在权限问题?请在调试时发布 authTokendecodedAuthToken 是什么,因为这可能会给您更多的洞察力。
  • 文件没有权限问题...但是我无法调试 api,因为它一直告诉我我未经授权。我需要在 url 中发送凭据吗?
  • 是的,使用 PostMan...真正容易添加标题和授权。还为我的代码添加了一点点。不过老实说,你做的基本就是我实现了十几次基本授权。