2017-07-08 17 views
0

我的Web API正與AngularJS。我幾天前實現了Web API令牌機制,並能夠使用訪問令牌登錄應用程序。我用外部數據庫表而不是ASP.NET身份表來授權用戶。如何存儲在一個地方的多個Web API控制器登錄和訪問後用戶信息

我要存儲用戶信息類,以便它可以很容易地從不同控制器的用戶登錄後訪問。目前我使用的控制器類ClaimsIdentity來獲取用戶信息。

UserIdentityViewModel.cs

public class UserIdentityViewModel 
    { 
     public string UserName { get; set; } 
     public Guid UserId { get; set; } 
    } 

Startup.cs

public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     {     
      app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 
      var myProvider = new AuthorizationServerProvider(); 
      OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions 
      { 
       AllowInsecureHttp = true, 
       TokenEndpointPath = new PathString("/Token"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
       Provider = myProvider 
      }; 
      app.UseOAuthAuthorizationServer(options); 

      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 
     } 
    } 

AuthorizationServerProvider.cs

public class AuthorizationServerProvider : OAuthAuthorizationServerProvider 
    { 
     public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
     { 
      context.Validated(); // 
     } 

     public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     {   
      string userId = context.UserName; 
      string password = context.Password; 

      EmployeeAccessBLL chkEmpAccessBLL = new EmployeeAccessBLL(); 
      EmployeeAccessViewModel vmEmployeeAccess = chkEmpAccessBLL.CheckEmployeeAccess(Convert.ToInt32(userId), password); 

      if(vmEmployeeAccess != null) 
      { 
       var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
       identity.AddClaim(new Claim("username", vmEmployeeAccess.EmpName)); 
       identity.AddClaim(new Claim("userid", Convert.ToString(vmEmployeeAccess.EmployeeId))); 

       UserIdentityViewModel vmUser = new UserIdentityViewModel(); 
       vmUser.UserId = vmEmployeeAccess.EmployeeId; 
       vmUser.UserName = vmEmployeeAccess.EmpName; 

       context.Validated(identity); 
      } 
      else 
      { 
       context.SetError("invalid_grant", "Provided username and password is incorrect"); 
       return; 
      } 
     }  
    } 

EventController.cs

public class StreamEventController : ApiController 
    { 
     [Authorize] 
     [Route("api/addevent")] 
     [HttpPost] 
     public List<string> AddEvent(StreamEventViewModel vmEvent) 
     { 
      //Able to get User Information from Identity.Claims 
      var identity = (ClaimsIdentity)User.Identity; 
      string userId = identity.Claims 
          .Where(c => c.Type == "userid") 
          .Select(c => c.Value).FirstOrDefault(); 

      //Not able to get User Information from following as new object instance gets created 
      UserIdentityViewModel vmUser = new UserIdentityViewModel(); 

      vmEvent.CreatedBy = vmUser.UserId; 
      vmEvent.ModifiedBy = vmUser.UserId; 
     } 
} 

而不是寫「Identity.Claims」,在每個控制器我想用簡單的get/set方法或任何其他方法來獲取用戶信息的每個方法。使用靜態類的也是在我看來不好的,因爲它會存儲用戶和多用戶登錄信息的一個信息可能會錯過。

請幫助我,並與我分享已在其他Web API項目進行登錄使用過的最好的辦法。

回答

1

您可以添加將在控制器的構造函數中設置一個私有變量,就像這樣:

// Should only be used in protected methods. 
private ClaimsIdentity ThisUser = null; 

public MyController() 
{ 
    if (User.Identity.IsAuthenticated) 
     ThisUser = (ClaimsIdentity)User.Identity; 
} 

[Authorize] 
[Route("api/addevent")] 
[HttpPost] 
public List<string> AddEvent(StreamEventViewModel vmEvent) 
{ 
    string userId = ThisUser.FindFirstValue("userid"); 

} 

或者創建一個User類在這裏裝載的所有屬性:

private UserClass ThisUser = null; 

public MyController() 
{ 
    if (User.Identity.IsAuthenticated) 
     ThisUser = new UserClass(User); 
} 

[Authorize] 
[Route("api/addevent")] 
[HttpPost] 
public List<string> AddEvent(StreamEventViewModel vmEvent) 
{ 
    string userId = ThisUser.UserId; 

} 

在哪裏UserClass是這樣的:

public class UserClass 
{ 
    public string UserId { get; private set; } 

    public UserClass(IPrincipal user) 
    { 
     UserId = user.FindFirstValue("userid"); 
    } 
} 

但是,這只是同樣的事情開銷。 你可以考慮到的東西轉移到一個擴展。在這種情況下你喜歡的東西:

public static class RequestExtensions 
{ 
    public static UserClass GetUser(this HttpRequestMessage request) 
    { 
     return new UserClass(request.GetOwinContext().Authentication.User); 
    } 

    public static ClaimsIdentiy GetUser2(this HttpRequestMessage request) 
    { 
     return new (ClaimsIdentity)request.GetOwinContext().Authentication.User; 
    } 
} 

,你可以撥打:

[Authorize] 
[Route("api/addevent")] 
[HttpPost] 
public List<string> AddEvent(StreamEventViewModel vmEvent) 
{ 
    string userId = Request.GetUser.UserId; 

    string userId2 = Request.GetUser2.FindFirstValue("userid"); 

} 

我想我會去Request.GetUser2.FindFirstValue("userid");

的代碼是爲了給你一個想法。我沒有測試代碼,但我認爲它應該可以工作。

+0

謝謝你給了我最好的選擇一噸Ruard。正如你所提到的,我嘗試使用擴展方法獲得成功的結果。 – user1843970

相關問題