2014-01-22 133 views
35

我對OWIN身份驗證完全陌生,而且我必須誤解所有的工作方式,但是我無法在任何地方找到它。不同域名的登錄頁面

我想要的只是能夠使用中央域進行身份驗證。如果有人在未通過身份驗證時試圖訪問apps.domain.com,則會將其重定向到accounts.domain.com/login,以便將所有身份驗證分離爲其自己的域和應用程序。使用MVC 4表單身份驗證非常簡單,您可以在其中指定完整的URL,但似乎與OWIN無關。

Startup.Auth.cs

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    LoginPath = new PathString("/account/login") 
} 

這很容易與CookieDomain選項設置cookie時指定的域。但是,當您指定要重定向到的登錄路徑時,它必須與當前應用程序相關,那麼如何實現MVC 4表單身份驗證中的如此簡單的操作?

沒有太深入的OWIN認證是關於什麼,我找不到任何解決這個問題後幾個小時的搜索。

回答

42
public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationMode = AuthenticationMode.Active, 
      LoginPath = new PathString("/account/login"), 
      LogoutPath = new PathString("/account/logout"), 
      Provider = new CookieAuthenticationProvider 
      { 
       OnApplyRedirect = ApplyRedirect 
      }, 
     }); 
    } 

    private static void ApplyRedirect(CookieApplyRedirectContext context) 
    { 
     Uri absoluteUri; 
     if (Uri.TryCreate(context.RedirectUri, UriKind.Absolute, out absoluteUri)) 
     { 
      var path = PathString.FromUriComponent(absoluteUri); 
      if (path == context.OwinContext.Request.PathBase + context.Options.LoginPath) 
      { 
       context.RedirectUri = "http://accounts.domain.com/login" + 
        new QueryString(
         context.Options.ReturnUrlParameter, 
         context.Request.Uri.AbsoluteUri); 
      } 
     } 

     context.Response.Redirect(context.RedirectUri); 
    } 
} 

如果apps.domain.com是唯一返回URL基地可能的話,你應該認真考慮context.Request.PathBase + context.Request.Path + context.Request.QueryString更換context.Request.Uri.AbsoluteUri和驗證服務器建立絕對回報的網址,以保護您的應用中濫用重定向。

希望這有助於;)

編輯:你可能會問自己,爲什麼我不使用context.RedirectUri財產直接申請重定向。事實上,ICookieAuthenticationProvider.ApplyRedirect負責多個重定向,對應於登錄和註銷流程(是的,我知道,它打破了單一責任原則......)。但更糟糕的是:context.RedirectUri可以在cookie被有效地發送回瀏覽器時,在登錄流程的開始或最終瀏覽器的目的地(即真正的相對「返回URL」)中代表認證端點的絕對URL ...這就是爲什麼我們需要確保context.RedirectUri是絕對的,並且對應於註冊的context.Options.LoginPath

+0

非常感謝你的回答!它看起來不錯,今晚我回家時我會試試看。 –

+0

感謝Tracher,我糾正了一個小錯誤,它可以防止在使用PathBase時(例如通過app.Map)阻止這種工作。請參閱更新的代碼。 – Pinpoint

+0

工程就像一個魅力,再次感謝:) –

3

我正在通過https://github.com/IdentityServer/IdentityServer3的例子工作,而我有不同的答案。在https://www.scottbrady91.com/Identity-Server/Identity-Server-3-Standalone-Implementation-Part-2的示例中,他們展示了一個使用獨立IdP和Cookie身份驗證的MVC應用程序。這個例子並沒有包括讓401重定向工作,但我偶然發現了一條路。

基本的方案是在AccountController中創建一個用於登錄的動作。

public ActionResult SignIn() { 
    // set up some bookkeeping and construct the URL to the central auth service 
    return Redirect(authURL); 
} 

現在你可以在啓動時使用本地URL

public class Startup { 
    public void Configuration(IAppBuilder app) { 
    app.UseCookieAuthentication(new CookieAuthenticationOptions 
    { 
     AuthenticationType = "Cookies", 
     LoginPath = new PathString("/Account/SignIn") 
    }); 
} 

你也有,你可以把一個動作鏈接登入在菜單欄上,供人額外的好處誰想要在401之前登錄。我們在這裏完成的工作是解決當未經身份驗證的用戶從獲得身份驗證的方式請求資源時應採取的措施。

+0

我更喜歡這個解決方案,因爲它按照預期使用框架,而不是用自定義邏輯覆蓋'ApplyRedirect'。 – infl3x