2013-09-24 15 views
8

我試圖擴展服務堆棧的身份驗證和註冊功能。我有認證和註冊工作正常,但我需要爲每個用戶添加一些自定義數據。從Service Stack的文檔和各種其他文章中,我發現您可以使用內置到UserAuth表中的MetaData列來添加自己的數據。擴展服務堆棧身份驗證 - 使用自定義用戶身份驗證元數據填充用戶會話

我創建了一個CustomAuthRepository這樣我就可以設置USERAUTH的元數據屬性,這裏是我的自定義回購:

public class CustomAuthRepository : OrmLiteAuthRepository, IUserAuthRepository 
{ 
    public UserAuth CreateUserAuth(UserAuth newUser, string password) 
    { 
     newUser.Set(new LoginInfo 
     { 
      IsActive = false, 
      PasswordNeedsReset = true 
     }); 
     return base.CreateUserAuth(newUser, password); 
    } 
} 

這是用於設置的元數據工作的偉大,我最終的序列化版本UserAuth表的元數據列中的LoginInfo對象。

現在我想要做的是當用戶驗證我需要根據某些元數據更改AuthResponse。例如,如果用戶還沒有激活,我想返回一個帶有屬性的AuthResponse IsActive = get value from custom meta data

我想我可以做到這一點,如果我可以讓我的自定義元數據進入AuthSession。這樣,在我的自定義證書身份驗證提供者,我可以基於什麼是在AuthSession改變響應對象:

public class CustomCredentialsAuthProvider : CredentialsAuthProvider 
{ 
    public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request) 
    { 
     var customUserAuthSession = (CustomUserAuthSession)session; 

     if (!customUserAuthSession.LoginInfo.IsActive) 
     { 
      return new 
      { 
       UserName = customUserAuthSession.UserName, 
       IsActive = customUserAuthSession.LoginInfo.IsActive 
      }; 
     } 

     var isAuthenticated = base.Authenticate(authService, session, request); 

     return isAuthenticated; 
    } 
} 

我要對這個正確的方式,還是有更好的方式來存儲和檢索自定義元數據?

如何根據用戶的自定義元數據更改AuthResponse?

如何將自定義元數據導入AuthSession?

編輯 我越來越接近我想要做的事情。在我CustomAuthSession OnAuthenticated()方法:

public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo) 
    { 
     var customUserAuthSession = (CustomUserAuthSession) session; 

     var userAuth = authService.ResolveService<IUserAuthRepository>().GetUserAuth(session, null); 
     customUserAuthSession.LoginInfo = userAuth.Get<LoginInfo>(); 

     authService.SaveSession(customUserAuthSession); 

     base.OnAuthenticated(authService, session, tokens, authInfo); 
    } 

我,重新獲取USERAUTH和填充有我需要的數據會話。基於自定義用戶會話的服務堆棧documentation,您需要在使用一些自定義數據填充會話後保存會話。我正在那樣做,但似乎並沒有挽救。 在我的CustomCredentialsAuthProvider,Authenticate方法中,我沒有看到我添加到會話的自定義數據。

編輯 我的第一個編輯的問題上面是用戶通過驗證,那麼我們得到的CustomAuthSession代碼,我可以檢查它們是否活躍與否。在他們不活躍的情況下,我需要將他們註銷,而不是理想的。

我發現我可以在我的自定義CredentialsAuthProvider的Authenticate方法中完成所有這些。

public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request) 
    { 
     var userAuthRepo = authService.ResolveService<IUserAuthRepository>(); 
     var userAuth = userAuthRepo.GetUserAuthByUserName(request.UserName); 
     var loginInfo = userAuth.Get<LoginInfo>(); 

     if (!loginInfo.IsActive) 
     { 
      return new CustomAuthResponse 
      { 
       UserName = userAuth.UserName, 
       ResponseStatus = new ResponseStatus("500"), 
       IsActive = loginInfo.IsActive 
      }; 
     } 

     var authResponse = (AuthResponse)base.Authenticate(authService, session, request); 

     return authResponse; 
    } 

當請求到來時,我可以使用的用戶名在請求中獲取USERAUTH,並檢查用戶IsActive與否。如果沒有,那麼我可以在Service Stack驗證它們之前返回一些錯誤。

我認爲這對我正在嘗試做的工作足夠好。我應該能夠向客戶端返回一個錯誤,表示用戶不活躍。

如果有人有一個更清潔的方式來做到這一點,那就太好了。

+0

也許這個鏈接可以幫助你[定製IAuthProvider的ServiceStack.net - 分步](http://enehana.nohea.com/general/customizing-iauthprovider-for-servicestack-net-step-by-step/ ) – stefan2410

+0

感謝您的鏈接沒有讀過那一個。不幸的是,他不顯示如何從UserAuth表中的元數據列中獲取/設置自定義元數據。他確實在CustomCredentialsAuthProvider的OnAuthenticated方法中將一些自定義數據添加到自定義用戶會話中,但他的示例顯示'some_firstname_from_db'。如果我能弄清楚如何從數據庫中再次獲取用戶,我可以用這種方法填充會話。似乎並不很乾淨,因爲當這個方法被稱爲服務棧已經取得我的用戶驗證他們的信用,並稱這個方法後驗證 – officert

+0

還有其他的聯繫。如果你沒有找到他們,[這裏](https://github.com/ServiceStack/ServiceStack/wiki/Authentication-and-authorization#custom-authentication-and-authorization)和[here](http:// rossipedia。 com/blog/2013/03/simple-api-key-authentication-with-servicestack /),[here](http://dylanbeattie.blogspot.gr/2013/08/building-servicestack-based-oauth2.html) ,[這裏](http://joeriks.com/2013/01/12/cors-basicauth-on-servicestack-with-custom-authentication/)大多數人在SO-servicestack中很活躍,所以也許以後要回答你的問題。 – stefan2410

回答

8

這是我迄今爲止的答案。它可以工作,我可以做我想做的事情,但我很樂意聽到一些服務協議組織的人士提出這是否是最好的方法。

保存自定義元數據

創建子類的OrmLiteAuthRepository一個新的類。在我的情況下,我只想使用內置Sql數據庫持久性的服務堆棧,並讓它創建所需的表。

重新實現CreateUserAuth方法來保存任何自定義元數據:

public UserAuth CreateUserAuth(UserAuth newUser, string password) 
    { 
     newUser.Set(new AccountStatus 
     { 
      IsActive = false, 
      PasswordNeedsReset = true 
     }); 
     return base.CreateUserAuth(newUser, password); 
    } 

抓取自定義元數據

創建子類的CredentialsAuthProvider一個新的類。重寫Authenticate方法。

public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request) 
    { 
     var userAuthRepo = authService.ResolveService<IUserAuthRepository>(); 
     var userAuth = userAuthRepo.GetUserAuthByUserName(request.UserName); 
     var accountStatus= userAuth.Get<AccountStatus>(); 

     if (!accountStatus.IsActive) 
     { 
      throw new InvalidOperationException(string.Format("User {0} is not activated.", request.UserName)); 
     } 
     if (!accountStatus.PasswordNeedsReset) 
     { 
      throw new InvalidOperationException("Your password needs to be reset before you can login."); 
     } 

     var authResponse = (AuthResponse)base.Authenticate(authService, session, request); 

     return authResponse; 
    } 

當一個認證請求進入這個方法時,獲取UserAuth和自定義元數據。如果用戶處於不活動狀態,或者他們的密碼需要重置,則拋出一個帶有錯誤消息的InvalidOperationException。

在我的客戶端應用程序的登錄控制器中,我可以檢查從服務返回的錯誤消息,並將用戶重定向到某個頁面,說明帳戶尚未激活,或者需要重置密碼才能進行身份驗證。