我一直在学习ASP.Net WebApi中的授权是如何工作的,我在另一个帖子(ASP.NET Web API Authentication)中遇到了Darin Dimitrov的答案,我需要帮助理解为什么我会得到401。
遵循Darin的代码,我创建了一个WebApi项目并添加了以下控制器和模型:
AccountController.cs
using System.Web.Http;
using System.Web.Security;
using AuthTest.Models;
namespace AuthTest.Controllers
{
public class AccountController : ApiController
{
public bool Post(LogOnModel model)
{
if (model.Username == "john" && model.Password == "secret")
{
FormsAuthentication.SetAuthCookie(model.Username, false);
return true;
}
return false;
}
}
}
UsersController.cs
using System.Web.Http;
namespace AuthTest.Controllers
{
[Authorize]
public class UsersController : ApiController
{
public string Get()
{
return "This is top secret material that only authorized users can see";
}
}
}
LogOnModel.cs
namespace AuthTest.Models
{
public class LogOnModel
{
public string Username { get; set; }
public string Password { get; set; }
}
}
我创建了一个Web窗体应用程序,其中包含两个按钮和一个用于测试目的的标签。
Default.aspx.cs
using System;
using System.Net.Http;
using System.Threading;
namespace AuthTestWebForms
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ButtonAuthorizeClick(object sender, EventArgs e)
{
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsJsonAsync(
"http://localhost/authtest/api/account",
new { username = "john", password = "secret" },
CancellationToken.None
).Result;
response.EnsureSuccessStatusCode();
bool success = response.Content.ReadAsAsync<bool>().Result;
if (success)
{
//LabelResponse.Text = @"Credentials provided";
var secret = httpClient.GetStringAsync("http://localhost/authtest/api/users");
LabelResponse.Text = secret.Result;
}
else
{
LabelResponse.Text = @"Sorry, you provided the wrong credentials";
}
}
}
protected void ButtonTestAuthClick(object sender, EventArgs e)
{
using (var httpClient = new HttpClient())
{
var secret = httpClient.GetStringAsync("http://localhost/authtest/api/users");
LabelResponse.Text = secret.Result;
}
}
}
}
当我单击按钮并运行ButtonAuthorizeClick()时,它会触发Account的控制器,然后为用户激活控制器,一切都很好。
如果我然后单击ButtonTestAuthClick(),我会收到401(未经授权)错误。
当我在Chrome或FireFox中查找ASPXAUTH cookie时,我没有看到它,所以我不能100%确定为什么ButtonAuthorizeClick()有效以及我需要做什么来使ButtonTestAuthClick()工作。
感谢任何人可以帮助我的任何帮助。
答案 0 :(得分:6)
我遇到了类似的问题,但不是通过Web窗体客户端页面,而是使用JavaScript和AJAX调用。事实证明我已经离开了在“无”的web.config中的身份验证模式。显然,您必须在此处打开Forms Authentication才能使FormsAuthentication.SetAuthCookie()方法产生任何效果。
<authentication mode="Forms" />
一旦我解决了这个疏忽,一切都开始正常。 : - )
答案 1 :(得分:1)
您正在调用中间身份验证的web api。为什么不通过ajax在客户端对用户进行身份验证?
这里的问题是每当你通过HttpClient向web api发送请求时,它实际上是由服务器处理的新web请求。所有cookie信息都不会保存在当前请求中。为了支持这种情况,您需要自己处理cookie。
例如:如果响应具有,则在ButtonAuthorizeClick方法中将cookie ASPXAUTH设置为asp.net头。 将cookie ASPXAUTH设置为HttpRequestMessage并通过HttpClient发送。
Web api最近添加了一个支持,使用HttpServer创建进程内服务器,并可以直接向当前进程中的当前消息处理程序发送请求。所以你可以编写如下代码:
HttpClient c = new HttpClient(new HttpServer(GlobalConfiguration.DefaultHandler));
c.GetStringAsync("http://localhost/api/Values").Wait();
要在进程中发送请求,以便在web api操作中设置的cookie标头仍将在当前请求的管道中。办理登机手续似乎不在RTM版本中。您可以尝试每晚构建http://aspnetwebstack.codeplex.com/discussions/353867。
答案 2 :(得分:0)
虽然已经很晚了,但ButtonTestAuthClick中的客户端不是浏览器。这是httpClient对象。因此,您需要以编程方式设置从其他按钮生成的cookie。