更新
我已将代码更改为FormsAuthentication.SetAuthCookie(_model.UserName, true);
。我有2个Web.config文件,1个用于MVC,另一个用于WebAPI。在MVC配置中,我定义了
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
两个应用程序都位于同一个域中。
更新:我们是否应该在WebAPI中使用Cookie?
目前,我有一个使用表单身份验证和WebAPI项目的MVC项目。问题是我无法在WebAPI项目中获得与请求关联的用户。我认为这是可能的,或者实施可能是错误的?
注意:我将cookie代码放在WebAPI控制器方法中作为测试,它不在应有的位置。
MVC - 处理登录请求,创建身份验证票。
// POST: /Account/Login
[AllowAnonymous]
[HttpPost]
public ActionResult Login(LoginModel _model, string _returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(_model.UserName, _model.Password))
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(_model.UserName, true, 15);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
Response.Cookies.Add(cookie);
// set redirect
}
}
// If we got this far, something failed, redisplay form
return View(_model);
}
WebAPI - 处理更新请求
[AcceptVerbs("PUT")]
public HttpResponseMessage UpdateInfo(int _id, ExampleModel _model)
{
try
{
HttpCookie authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
string encTicket = authCookie.Value;
if (!String.IsNullOrEmpty(encTicket))
{
// decrypt the ticket if possible.
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(encTicket);
var userData = ticket.UserData;
}
}
// do update
return Request.CreateResponse(HttpStatusCode.OK, data, GlobalConfiguration.Configuration);
}
catch (Exception err)
{
m_logger.Error(err);
throw;
}
}
答案 0 :(得分:9)
为什么要手动创建表单身份验证票据呢?为什么你不能这样做?
if (Membership.ValidateUser(_model.UserName, _model.Password))
{
FormsAuthentication.SetAuthCookie(_model.UserName, true);
// set redirect
}
要控制超时,可以在web.config中设置:
<authentication mode="Forms">
<forms timeout="15" />
</authentication>
如果您这样做,则不必检查cookie以获取用户名。它应该自动设置在控制器的User.Identity.Name
属性上。这适用于MVC Controller
和ApiController
s。
此外,如果您的MVC应用程序和WebAPI应用程序托管在Web服务器(或不同服务器)上的不同节点上,则MVC项目和WebAPI项目必须在其Web中具有相同的machineKey
.config文件。它们也必须位于同一个域中,但如果它们是具有单独web.config文件的单独应用程序,则它们必须具有相同的machineKey
值(decryption
,decryptionKey
,{{1} }和validation
)。这些是验证,加密和解密.ASPXAUTH cookie所需的值。
我们是否应该在WebAPI中使用Cookie?
如果您使用上述模式,则不必手动获取任何cookie,至少对于身份验证/授权。 Cookie是HTTP规范的一部分,还包括方法,标题,响应代码等.WebAPI将它们放在那里是有原因的。如果您需要它们,请使用它们。如果您不需要它们,请不要使用它们。
你应该尽量避免这样做:
validationKey
您可以从ApiController获取Cookie,如下所示:
HttpCookie authCookie = HttpContext.Current.Request.Cookies["name"];
<强>更新强>
我总是使用这个生成工具:http://aspnetresources.com/tools/machineKey
只需点击“生成密钥”按钮,然后将生成的IEnumerable<CookieHeaderValue> cookies = this.Request.Headers.GetCookies("name");
if (cookies.Any())
{
IEnumerable<CookieState> cookie = cookies.First().Cookie;
if (cookie.Any())
{
string value = cookie.First().Value;
}
}
部分粘贴到两个web.config文件的<machineKey ../>
部分下的某个位置。
<强>更新强>
可能存在安全问题,具体取决于谁有权查看您的web.config文件。如果您将其检查到源控制存储库中,那么任何可以访问源代码的人都可以看到验证和加密密钥。
我所做的事情有点令人费解,但它确保了这些字符串的安全性。您可以将<system.web>
和validationKey
值存储在encryptionKey
中,然后加密配置文件的appSettings
部分(使用CloudConfigCrypto之类的内容)。这意味着无法访问加密证书私钥的任何人都无法读取这些值。然后,您可以在appSettings
期间使用Microsoft.Web.Administration.ServerManager
类在运行时更改machineKey
值。关于这一点的更多细节不在这个问题的范围之内。
另一个选择是保持这些不受源代码控制,但是每次部署时都必须手动更新web.config。
答案 1 :(得分:0)
我找到了使用WebMatrix.WebData
命名空间中的WebSecurity
类将表单身份验证与Web API和MVC应用程序一起使用的最简单方法。它提供了对大多数常用操作的非常简单的访问,例如创建用户帐户,登录和注销用户,重置或更改密码。而且您不必自己处理会话cookie。
我在类似于你的设置中使用它,我们必须对Web API和MVC应用程序使用Forms身份验证。
API示例
登录:
if(WebSecurity.Login(username, password))
{
return Request.CreateErrorResponse(
HttpStatusCode.Forbidden, "Invalid credentials");
}
else
{
return Request.CreateResponse(HttpStatusCode.OK);
}
寄存器:
if(WebSecurity.UserExists(username))
{
return Request.CreateErrorResponse(
HttpStatusCode.BadRequest, "Username already exists");
}
WebSecurity.CreateUserAndAccount(username, password, data);
HttpResponseMessage response = Request.CreateResponse(
HttpStatusCode.Created, yourUserObject);
response.Headers.Location = new Uri(
Url.Link("DefaultApi",
new { controller = "users", id = WebSecurity.GetUserId(username) }));
return response;
相同的调用适用于MVC应用程序。