2013-10-29 85 views
2

我有一個使用ServiceStack構建的REST API。我在調用REST API時沒有任何問題使用BasicAuthentication(我正在註冊AuthFeatureBasicAuthProvider)。如何使用ServiceStack進行Web瀏覽器請求的基本身份驗證?

現在我正在嘗試構建一些HTML管理頁面。這些也應該被認證。

[授權]屬性重定向到/登錄頁面,所以我創建了下面的DTO和匹配服務來處理登錄:

[DefaultView("Login")] 
    public class SiteLoginService : EnshareServiceBase 
    { 
     public object Get(SiteLoginRequest req) 
     { 
      return new SiteLoginRequest(); 
     } 

     public object Post(SiteLoginRequest req) 
     { 
      //I am trying to use the registered IAuthProvider, which is the BasicAuthProvider 
      var authProvider = ResolveService<IAuthProvider>(); 
      authProvider.Authenticate(this, EnshareSession, 
             new ServiceStack.ServiceInterface.Auth.Auth() 
             { 
              Password = req.Password, 
              UserName = req.UserName 
             }); 
      return HttpResult.Redirect(req.Redirect); 
     } 
    } 

    [Route("/login")] 
    public class SiteLoginRequest : IReturn<SiteLoginRequest> 
    { 
     public string Redirect { get; set; } 
     public string Password { get; set; } 
     public string UserName { get; set; } 
    } 

然而,BasicAuthProvider總是拋出HttpError:「無效的基本驗證憑據」的時候我在「登錄」視圖頁面上填寫用戶名和密碼,並將它們發佈到SiteLoginService。這可能是因爲Web瀏覽器沒有填寫基本身份驗證標頭,但我不知道如何使用填寫的用戶名和密碼進行身份驗證。

如何根據AuthProvider正確驗證站點用戶是否適用於現有的REST API?

+0

當您註冊** AuthFeature **時,是否包含'new BasicAuthProvider()'? – mythz

+0

最初我包含了從BasicAuthProvider繼承的我的CustomAuthProvider。解決方案還包括CredentialsAuthProvider - 我在下面發佈了我自己的答案。 – Marek

回答

1

我想我還需要在AuthFeature中包含CredentialsAuthProvider,它將公開/ auth/credentials服務,我將它發佈到表單後。

 //this inherits the BasicAuthProvider and is used to authenticate the REST API calls 
     var myCustomAuthProvider = new CustomAuthProvider(appSettings); 
     var credentialsProvider = new CredentialsAuthProvider(appSettings); 
     container.Register<IAuthProvider>(myCustomAuthProvider); 
     container.Register<CredentialsAuthProvider>(credentialsProvider); 
     var authFeature = new AuthFeature(() => new EnshareSession(new MongoTenantRepository()), 
              new IAuthProvider[] { 
                    myCustomAuthProvider, 
                    credentialsProvider 
                   }) 

所以我指定我的登錄表單/認證/證書的作用,同時提供所需的用戶名和密碼字段。

 <form action="/auth/credentials" method="post"> 
      <p class="entryfield"> 
       @Html.LabelFor(m => m.UserName, "Login name:") 
       @Html.TextBoxFor(u => u.UserName) 
      </p> 
      <p class="entryfield"> 
       @Html.LabelFor(m => m.Password) 
       @Html.PasswordFor(m => m.Password) 
      </p> 
      <input class="formbutton" type="submit" value="Login" /> 
     </form> 

當窗體發佈,它擊中的驗證碼正確流(TryAuthenticate叫我IUserAuthRepository並返回true)。

最終,請求收到302,我的登錄表單將在/ login重新顯示。

HTTP/1.1 302 Found 
    Server: ASP.NET Development Server/10.0.0.0 
    Date: Wed, 30 Oct 2013 08:15:54 GMT 
    X-AspNet-Version: 4.0.30319 
    X-Powered-By: ServiceStack/3,969 Win32NT/.NET 
    Location: http://localhost:64944/login?redirect=%2fadmin 
    Set-Cookie: X-UAId=3; expires=Sun, 30-Oct-2033 08:15:54 GMT; path=/; HttpOnly 

它設置會話cookie(X-AUId)並且用戶被正確驗證。隨後對使用Authenticate屬性裝飾的服務的Web瀏覽器請求成功。

所以唯一缺少的部分是如何確保用戶在發佈到/auth/credentials後正確重定向。

爲了確保重定向的正常工作,快速查看一下已經顯示的預期是Continue參數。

所以這是登錄表單需要怎樣的樣子(我重用從ServiceStack的驗證類模型):

@inherits ViewPage<ServiceStack.ServiceInterface.Auth.Auth> 
    @{ 

     Layout = "AdminLayout"; 
    } 

    <form action="/auth/credentials" method="post"> 
     <p class="entryfield"> 
      @Html.LabelFor(m => m.UserName, "Login name:") 
      @Html.TextBoxFor(u => u.UserName) 
     </p> 
     <p class="entryfield"> 
      @Html.LabelFor(m => m.Password) 
      @Html.PasswordFor(m => m.Password) 
     </p> 
     @Html.HiddenFor(m => m.Continue) 
     <input type="submit" value="Login" /> 
    </form> 

將繼續屬性填充在其模型中的重定向物業服務。

1

如果您將用戶名&密碼作爲帖子傳遞,則您懷疑您沒有進行基本身份驗證。

This article解釋瞭如何使用JavaScript進行基本認證。從文章:

function login() { 
    var username = document.getElementById(this.id + "-username").value; 
    var password = document.getElementById(this.id + "-password").value; 
    this.http.open("get", this.action, false, username, password); 
    this.http.send(""); 
    if (http.status == 200) { 
     document.location = this.action; 
    } else { 
     alert("Incorrect username and/or password."); 
    } 
    return false; 
} 

ServiceStack還支持其他形式的認證,包括通過發送一個POST用戶名和密碼,如果這是你想要的。如果你解釋你的要求,我們可以提出一些建議。

+0

我不想使用JavaScript進行身份驗證。我想從HTML表單中做一個普通的http post。 – Marek

相關問題