2014-09-25 15 views
26

Tôi bắt đầu xây dựng api trên web cho các ứng dụng dành cho thiết bị di động và tôi đang gặp khó khăn trong việc triển khai xác thực. Tôi sử dụng Bearer và mặc dù tất cả mọi thứ được cho là tốt, tôi không thể có được người dùng hiện tại từ hành động trong bộ điều khiển. HttpContext.Current.User.Identity.Name là null (cùng là kết quả của HttpContext.Current.User.Identity.GetUserId()). Dưới đây là các mảnh mã quan trọng:Người dùng hiện tại trong xác thực nợ

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") 
     { 

     } 
    } 

Và 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}; 
    } 
} 

Khi tôi đi đến hành động này, tôi nhận được null 3 lần. Mặc dù vậy, toàn bộ quá trình xác thực dường như vẫn ổn - chỉ khi tôi gửi một mã thông báo tốt, tôi có quyền truy cập. Có ai có ý tưởng gì sai ở đây không?

+0

Bạn có thiết lập điểm ngắt trên 'return new String [] {HttpContext ...'? Đâu là null đầu tiên? – user1477388

+0

Giá trị cuối cùng không null là Identity (vì vậy tôi không nhận được một lỗi, nhưng null là một giá trị trả lại) – user3558203

+0

Là 'GetUserId()' cũng null? – user1477388

Trả lời

55

On GrantResourceOwnerCredentials phương pháp một khi bạn thêm tuyên bố sau khi xác nhận mật khẩu tên bạn cần phải thêm tuyên bố này:

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

Bằng cách này UserId sẽ được lấp đầy khi bạn gọi User.Identity.Name bên trong bộ điều khiển bảo vệ. Hy vọng điều này sẽ giải quyết được vấn đề của bạn.

+1

Thật không may, nó không giúp được gì. Tôi vẫn nhận được null. Tôi không chắc chắn tôi hiểu phần với btw điều khiển bảo vệ. Những gì tôi đã làm chỉ đơn giản là thêm dòng của bạn sau khi identity.AddClaim (new Claim ("role", "user")); – user3558203

+2

Tôi có nghĩa là bởi bộ điều khiển được bảo vệ một thuộc tính điều khiển với [Ủy quyền], nếu bạn đã kiểm tra giá trị User.Identity.IsAuthenticated là nó được đặt thành true và User.Identity.Name luôn rỗng sau khi thêm xác nhận quyền sở hữu này? –

+3

Cũng muốn cảm ơn bạn vì giải pháp trên! Chỉ cần làm rõ những gì user55 đã nói .. bạn phải thêm yêu cầu trong nhà cung cấp và sau đó đăng nhập lại để tạo mã thông báo mới trước khi bạn thấy thay đổi (tôi đã làm mới trang bằng mã thông báo hiện tại của mình và tự hỏi tại sao tôi không thể không thấy tên người dùng, ha) – alimac83

Các vấn đề liên quan