2011-04-12 91 views
24

我正在嘗試編寫一個ASP.NET MVC應用程序,該應用程序是我們擁有SOAP Web服務的CRM的前端。我希望用戶使用他們的CRM用戶名和密碼登錄我的Web應用程序,然後通過CRM進行身份驗證,在頁面上進行Web服務調用等。ASP.NET MVC Forms對外部Web服務的身份驗證

我開始使用Forms身份驗證並實現自定義成員資格提供者 - 我可以實現所需的所有方法,例如ValidateUser(),但是我遇到的問題是,登錄到CRM Web服務後,您將獲得一個令牌,並且必須隨每次後續Web服務調用都傳遞該令牌,而我不知道我可以在哪裏存儲這個。

所以我的問題是:

  • 是窗體身份驗證去這裏的路呢,還是要更直接地處理所有的認證自己和存儲在會話令牌。
  • 如果表單身份驗證是要走的路,我應該在哪裏以及如何存儲這樣的附加信息。它似乎喜歡使用表單身份驗證,但隨後將額外的信息(與身份驗證相關)加載到cookie之外或者會話之外會有點混亂?

任何意見,將不勝感激

回答

36

您可以將認證令牌存儲在窗體身份驗證cookie的用戶數據的一部分。這樣它就可以在每個請求中使用。

因此,例如,一旦你驗證用戶的憑據可以查詢Web服務,以獲得令牌和手動創建並放出窗體身份驗證Cookie:

[HttpPost] 
public ActionResult LogOn(string username, string password) 
{ 
    // TODO: verify username/password, obtain token, ... 
    // and if everything is OK generate the authentication cookie like this: 

    var authTicket = new FormsAuthenticationTicket(
     2, 
     username, 
     DateTime.Now, 
     DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes), 
     false, 
     "some token that will be used to access the web service and that you have fetched" 
    ); 
    var authCookie = new HttpCookie(
     FormsAuthentication.FormsCookieName, 
     FormsAuthentication.Encrypt(authTicket) 
    ) 
    { 
     HttpOnly = true 
    }; 
    Response.AppendCookie(authCookie); 

    // ... redirect 
} 

然後,你可以寫一個自定義授權屬性這將讀取該信息並設置自定義通用的身份:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     var isAuthenticated = base.AuthorizeCore(httpContext); 
     if (isAuthenticated) 
     { 
      string cookieName = FormsAuthentication.FormsCookieName; 
      if (!httpContext.User.Identity.IsAuthenticated || 
       httpContext.Request.Cookies == null || 
       httpContext.Request.Cookies[cookieName] == null) 
      { 
       return false; 
      } 

      var authCookie = httpContext.Request.Cookies[cookieName]; 
      var authTicket = FormsAuthentication.Decrypt(authCookie.Value); 

      // This is where you can read the userData part of the authentication 
      // cookie and fetch the token 
      string webServiceToken = authTicket.UserData; 

      IPrincipal userPrincipal = ... create some custom implementation 
              and store the web service token as property 

      // Inject the custom principal in the HttpContext 
      httpContext.User = userPrincipal; 
     } 
     return isAuthenticated; 
    } 
} 

最後裝點你的控制器/需要與這個屬性認證操作:

[MyAuthorize] 
public ActionResult Foo() 
{ 
    // HttpContext.User will represent the custom principal you created 
    // and it will contain the web service token that you could use to 
    // query the remote service 
    ... 
} 
+0

謝謝,這太棒了。我會去那裏。 – 2011-04-12 09:46:44

+1

加上w/s令牌在表單票據中得到加密,所以不能被盜或讀(理論上) – 2011-04-12 15:31:15

+0

好極了,但是我把「base.AuthorizeCore(httpContext);」到方法的末尾,就我們想要在角色檢查之前設置主體而言。 – mikalai 2012-07-26 09:20:12