2014-09-25 51 views
26

我開始爲移動應用程序構建web api,而且我很難實現身份驗證。我使用承載,雖然一切都應該沒問題,但我無法從控制器中獲取當前用戶的行爲。 HttpContext.Current.User.Identity.Name爲null(與HttpContext.Current.User.Identity.GetUserId()的結果相同)。這裏是重要的代碼片段:owin身份驗證中的當前用戶

Startup.cs:

public partial class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      var config = new HttpConfiguration(); 
      ConfigureAuth(app); 
      WebApiConfig.Register(config); 
      app.UseWebApi(config); 
     } 
    } 

Startup.Auth.cs

public partial class Startup 
{ 
     static Startup() 
     { 
      OAuthOptions = new OAuthAuthorizationServerOptions 
      { 
       TokenEndpointPath = new PathString("/token"), 
       Provider = new ApplicationOAuthProvider(), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
       AllowInsecureHttp = true 
      }; 

      OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); 
     } 

     public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } 
     public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } 


     public static string PublicClientId { get; private set; } 

     public void ConfigureAuth(IAppBuilder app) 
     { 
      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions 
      { 
       AccessTokenProvider = new AuthenticationTokenProvider() 
      }); 
      app.UseOAuthBearerTokens(OAuthOptions); 

      app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 

     } 
} 

ApplicationOAuthProvider.cs:

 public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
     { 

      string clientId, clientSecret; 

      if (!context.TryGetBasicCredentials(out clientId, out clientSecret)) 
      { 
       return SetErrorAndReturn(context, "client error", ""); 
      } 

      if (clientId == "secret" && clientSecret == "secret") 
      { 
       context.Validated(); 
       return Task.FromResult<object>(null); 
      } 

      return SetErrorAndReturn(context, "client error", ""); 
     } 

     public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     { 

      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); 

      using (AuthRepository _repo = new AuthRepository()) 
      { 
       IdentityUser user = await _repo.FindUser(context.UserName, context.Password); 

       if (user == null) 
       { 
        context.SetError("invalid_grant", "The user name or password is incorrect."); 
        return; 
       } 
      } 

      var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
      identity.AddClaim(new Claim("sub", context.UserName)); 
      identity.AddClaim(new Claim("role", "user")); 

      context.Validated(identity); 
     } 


     public override Task TokenEndpoint(OAuthTokenEndpointContext context) 
     { 
      foreach (KeyValuePair<string, string> property in context.Properties.Dictionary) 
      { 
       context.AdditionalResponseParameters.Add(property.Key, property.Value); 
      } 

      return Task.FromResult<object>(null); 
     } 

AuthRepository.cs:

public class AuthRepository : IDisposable 
    { 
     private readonly AuthContext _ctx; 

     private readonly UserManager<IdentityUser> _userManager; 

     public AuthRepository() 
     { 
      _ctx = new AuthContext(); 
      _userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>(_ctx)); 
     } 

     public async Task<IdentityResult> RegisterUser(UserModel userModel) 
     { 
      var user = new IdentityUser 
      { 
       UserName = userModel.UserName 
      }; 

      var result = await _userManager.CreateAsync(user, userModel.Password); 

      return result; 
     } 

     public async Task<IdentityUser> FindUser(string userName, string password) 
     { 
      IdentityUser user = await _userManager.FindAsync(userName, password); 
      return user; 
     } 

     public void Dispose() 
     { 
      _ctx.Dispose(); 
      _userManager.Dispose(); 

     } 
    } 

AuthContext.cs:

public class AuthContext : IdentityDbContext<IdentityUser> 
    { 
     public AuthContext() 
      : base("AuthContext") 
     { 

     } 
    } 

而且finnaly ValuesController.cs:

[Authorize] 
public class ValuesController : ApiController 
{ 

    public IEnumerable<string> Get() 
    { 
     return new String[] {HttpContext.Current.User.Identity.Name, HttpContext.Current.User.Identity.GetUserId(),ClaimsPrincipal.Current.Identity.Name}; 
    } 
} 

當我去這個動作,我得到空的3倍。儘管如此,整個身份驗證過程似乎沒有問題 - 只有當我發送一個好的令牌時,我纔有權訪問。有人知道這裏有什麼問題嗎?

+0

你是否在'return new String [] {HttpContext ...''上設置了斷點?第一個null在哪裏? – user1477388 2014-09-25 19:23:51

+0

最後一個非null值是Identity(所以我沒有得到一個錯誤,但作爲一個返回值爲空) – user3558203 2014-09-25 19:26:10

+0

'GetUserId()'也爲空? – user1477388 2014-09-25 19:32:26

回答

55

在方法GrantResourceOwnerCredentials一旦你確認你需要添加此要求的用戶名密碼後添加的權利要求:

identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); 

通過這樣做的用戶ID,當你調用保護控制器內User.Identity.Name將被填充。 希望這可以解決您的問題。

+1

不幸的是,它沒有幫助。我仍然得到空。我不確定我是否瞭解與保護控制器順便說一句的部分。我所做的只是在identity.AddClaim(新索賠(「角色」,「用戶」))之後添加你的行。 – user3558203 2014-09-25 20:53:51

+2

我的意思是受保護的控制器與[授權]的控制器屬性,如果您檢查值User.Identity.IsAuthenticated是它設置爲true,並且User.Identity.Name添加此聲明後總是空的? – 2014-09-25 21:24:20

+3

也想感謝您的上述解決方案!只是爲了澄清user55的說法..你必須在提供者中添加聲明,然後重新登錄創建一個新的令牌,然後才能看到更改(我使用現有令牌刷新頁面,並想知道爲什麼我不能看不到用戶名,哈) – alimac83 2014-12-27 22:32:59