2013-08-28 42 views
0

我一直在試圖弄清楚這一點,現在閱讀很多博客,MSDN文檔,示例代碼和其他stackoverflow問題,並且尚未得到此上班。在Web角色和客戶端應用程序之間共享ASP.NET簡單會員身份驗證

這是我的場景:

我使用Windows Azure來承載兩個Web角色。一個是我的MVC4 web API,另一個是我使用web API的MVC4 web應用程序。我還有許多使用.NET的客戶端應用程序,它們將訪問Web API。

所以我的主要組成部分是:

  • 的Web API
  • Web App的
  • .NET客戶端

我想使用在Web應用程序 '託管' 的形式驗證。我正在使用內置的simplemembership身份驗證機制,它工作得很好。我可以創建並登錄到Web App中的帳戶。

現在我還想使用這些相同的帳戶從Web應用程序和任何.NET客戶端應用程序對Web API進行身份驗證。

我讀過很多方法來做到這一點,最簡單的似乎是在Web API上使用基本身份驗證。目前我正在處理這個代碼,因爲它似乎解決了我的確切問題:Mixing Forms Authentication, Basic Authentication, and SimpleMembership

我無法得到這個工作。我成功登錄到我的Web應用程序(127.0.0.1:81),並且當我嘗試調用需要驗證的Web API(例如127.0.0.1:8081/api/values)時,調用失敗,出現401(未授權)迴應。在單步執行代碼時,WebSecurity.IsAuthenticated返回false。 WebSecurity.Initialized返回true。

我實現了這個代碼,我試圖打電話給我的Web API從我的Web應用程序使用下面的代碼(登錄後):

using (var handler = new HttpClientHandler()) 
{ 
    var cookie = FormsAuthentication.GetAuthCookie(User.Identity.Name, false); 
    handler.CookieContainer.Add(new Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain)); 

    using (var client = new HttpClient()) 
    { 
     //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
     // "Basic", 
     // Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
     // string.Format("{0}:{1}", User.Identity.Name, "123456")))); 
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
      "Cookie", 
      Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(User.Identity.Name))); 

     string response = await client.GetStringAsync("http://127.0.0.1:8080/api/values"); 

     ViewBag.Values = response; 
    } 
} 

正如你所看到的,我都嘗試使用該cookie以及用戶名/密碼。很明顯,我想使用cookie,但在這一點上,如果有任何工作,這將是一個很好的步驟!

我ValuesController在我的Web API正確裝飾:

// GET api/values 
[BasicAuthorize] 
public IEnumerable<string> Get() 
{ 
    return new string[] { "value1", "value2" }; 
} 

在我在我的Web API的Global.asax.cs,我初始化SimpleMembership:

// initialize our SimpleMembership connection 
try 
{ 
    WebSecurity.InitializeDatabaseConnection("AzureConnection", "User", "Id", "Email", autoCreateTables: false); 
} 
catch (Exception ex) 
{ 
    throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex); 
} 

這種成功和WebSecurity後說它已經初始化,所以我猜這部分工作正常。

我的配置文件具有匹配的驗證設置,根據需要按照MSDN

這裏是API配置:

<authentication mode="Forms"> 
<forms protection="All" path="/" domain="127.0.0.1" enableCrossAppRedirects="true" timeout="2880" /> 
</authentication> 
<machineKey decryption="AES" decryptionKey="***" validation="SHA1" validationKey="***" /> 

這裏是Web應用程序配置:

<authentication mode="Forms"> 
<forms loginUrl="~/Account/Login" protection="All" path="/" domain="127.0.0.1" enableCrossAppRedirects="true" timeout="2880" /> 
</authentication> 
<machineKey decryption="AES" decryptionKey="***" validation="SHA1" validationKey="***" /> 

注意,我在當地嘗試這種(因此127.0.0.1域),但引用數據庫託管在Azure上。

我沒有必要從.NET客戶端應用程序嘗試這些,因爲我甚至無法在Web角色之間使用它。對於客戶端應用程序,理想情況下,我將進行網絡通話,傳遞用戶名/密碼,檢索cookie,然後使用cookie進一步提供Web API請求。

我想得到我工作的東西,因爲它看起來非常簡單並且符合我的要求。

我還沒有嘗試其他解決方案,如Thinktecture,因爲它具有比我需要的更多功能,而且似乎沒有必要。

我錯過了什麼?

+0

我已經多次閱讀過這個問題,但我仍然不確定問題是什麼,或者發生了什麼故障。當您嘗試使用服務器端代碼從Web應用程序調用Web API時,它失敗嗎?什麼是失敗?您是否收到任何錯誤或是否是意外的行爲? –

+1

對於初學者,我不建議從服務器端代碼調用Web API。這是不必要的網絡流量。看看這個建議的架構[http://stackoverflow.com/questions/14887871/creating-a-service-layer-for-my-mvc-application/14896644#14896644],它可以讓你直接訪問你的應用程序域。您仍然可以使用自定義ClaimsAuthorizationManager在沒有Web API調用的情況下處理授權。 –

+0

對不起,不把我的具體錯誤在那裏。我花了很多時間試圖把所有的細節都放進去,並且錯過了最重要的一個細節。從服務器端代碼調用時,確實無法使用Web API進行授權。 –

回答

1

好吧,這很尷尬。我的主要問題是一個簡單的代碼錯誤。這是正確的代碼。告訴我,你可以發現我的問題中的代碼的差異。

using (var handler = new HttpClientHandler()) 
{ 
    var cookie = FormsAuthentication.GetAuthCookie(User.Identity.Name, false); 
    handler.CookieContainer.Add(new Cookie(cookie.Name, cookie.Value, cookie.Path, cookie.Domain)); 

    using (var client = new HttpClient(handler)) 
... 
} 

一旦被固定,我開始403 Forbidden錯誤。所以我跟蹤了這​​一點,並對BasicAuthorizeAttribute類進行了小改動,以便在沒有指定角色時正確支持[BasicAuthorize]屬性。

下面是修改代碼:

private bool isAuthorized(string username) 
{ 
    // if there are no roles, we're good! 
    if (this.Roles == "") 
     return true; 

    bool authorized = false; 

    var roles = (SimpleRoleProvider)System.Web.Security.Roles.Provider; 
    authorized = roles.IsUserInRole(username, this.Roles); 
    return authorized; 
} 

與該改變基本身份驗證通過傳遞形式的cookie的作品!

現在讓非web客戶端應用程序工作,然後按照建議重構Web應用程序。

我希望這可以幫助未來的人!

相關問題