2013-04-23 87 views
5

更新:訪問用戶數據

我已經改變了我的代碼FormsAuthentication.SetAuthCookie(_model.UserName, true);。我有2個Web.config文件,1個用於MVC,另一個用於WebAPI。在MVC配置中,我定義了

<authentication mode="Forms"> 
    <forms loginUrl="~/Account/Login" timeout="2880" /> 
</authentication> 

這兩個應用程序在同一個域中。


更新:如果我們甚至在使用的WebAPI餅乾?


目前,我有一個使用表單身份驗證和WebAPI項目的MVC項目。問題是我無法讓WebAPI項目中的請求與用戶相關聯。我認爲這是可能的,或者實施是錯誤的?

注意:我把cookie代碼放在WebAPI控制器方法中作爲一個測試,它不是它應該在的地方。

MVC - 處理登錄請求,創建auth票證。

// 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

所以cookie是空的? – 2013-04-23 09:24:21

+0

是的,該cookie爲空。 – user1883004 2013-04-23 09:25:26

+1

這兩個網站在同一個域名上? – 2013-04-23 09:48:38

回答

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 s和ApiController s。另外,如果您的MVC應用程序和WebAPI應用程序託管在Web服務器(或不同服務器上)的不同節點上,則MVC項目和WebAPI項目的web.config文件中必須具有相同的machineKey 。它們也必須位於同一個域中,但如果它們是具有單獨web.config文件的獨立應用程序,則它們必須具有相同的值decryption,decryptionKey,validationvalidationKey。這些是驗證,加密和解密.ASPXAUTH cookie所需的值。

我們是否應該在WebAPI中使用cookie?

如果使用上述模式,則不應手動獲取任何cookie,至少對於認證/授權。 Cookies是HTTP規範的一部分,同時還有方法,頭文件,響應代碼等等。WebAPI有它們在那裏是有原因的。如果你需要它們,請使用它們。如果你不需要它們,請不要使用它們。

你應該儘量避免通過這樣做讓他們:

HttpCookie authCookie = HttpContext.Current.Request.Cookies["name"]; 

你可以到餅乾從ApiController像這樣:

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; 
    } 
} 

更新

我總是使用這一代工具:http://aspnetresources.com/tools/machineKey

只需單擊「生成密鑰」按鈕,然後將結果<machineKey ../>部分粘貼到兩個web.config文件的<system.web>部分下的某個位置。

更新

有可能取決於誰有權查看你的web.config文件的安全問題。如果您像這樣將它簽入您的源代碼控制庫,任何可以訪問您的源代碼的人都可以看到驗證和加密密鑰。

我的工作有點複雜,但它保證了這些字符串的安全。您可以改爲將validationKeyencryptionKey的值存儲在appSettings中,然後加密配置文件的appSettings部分(使用類似CloudConfigCrypto的東西)。這意味着任何無權訪問加密證書私鑰的人都無法讀出這些值。然後可以使用Microsoft.Web.Administration.ServerManager類在Application_Start期間在運行時更改machineKey值。雖然這個問題的更多細節超出了這個問題的範圍。

另一種方法是隻保留這些源代碼管理,但是隨後您必須在每次部署時手動更新web.config。

+0

我更新了我的代碼以反映您的建議(請參閱OP),但「User.Identity.Name」保持空白。你說這兩個Web配置應該有相同的機器鍵值,但是沒有一個配置文件包含這個元素。我如何去產生這個? – user1883004 2013-04-23 13:50:28

+0

我更新了我的答案。有幾個工具,只是谷歌「生成machineKey」。由此產生的''元素屬於'',因此作爲您的''元素的兄弟。 – danludwig 2013-04-23 13:58:00

+0

將機器密鑰添加到Web配置工作中,我現在可以訪問User.Identity並填充期望的數據。謝謝!儘管如此,將驗證密鑰存儲爲像這樣的長字符串有多大關係?是否有任何安全問題? – user1883004 2013-04-23 14:16:19

0

我發現最簡單的方式使用窗體身份驗證與Web API和MVC應用程序通過WebMatrix.WebData名稱空間中使用WebSecurity類。它提供了對最常用操作的非常簡單的訪問,例如創建用戶帳戶,登錄和登出用戶,重置或更改密碼。而且您不必親自處理會話cookie。

我在類似於你的設置中使用它,我們必須爲Web API和MVC應用程序使用Forms Authentication。

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應用工作。