2017-07-08 30 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

相关问题