13

Tôi cần tạo ứng dụng C# Web API cho cơ sở dữ liệu MySQL hiện có. Tôi đã quản lý để sử dụng Entity Framework 6 để ràng buộc mọi bảng cơ sở dữ liệu với một RESTful API (cho phép các hoạt động CRUD).Sự nhầm lẫn xác thực DB-Đầu tiên với ASP.NET Web API 2 + EF6

Tôi muốn triển khai hệ thống đăng nhập/đăng ký (để tôi có thể triển khai vai trò và quyền trong tương lai và hạn chế các yêu cầu API nhất định).

Cơ sở dữ liệu MySQL tôi phải sử dụng có một bảng cho người dùng (gọi tắt là user) đó có các cột tự giải thích như sau:

  • id
  • email
  • username
  • password_hash

Dường như tiêu chuẩn xác thực de facto là Nhận dạng ASP.Net. Tôi đã dành giờ cuối cùng cố gắng tìm ra cách làm cho Identity làm việc với một thiết lập DB-First Entity Framework hiện có.

Nếu tôi cố gắng xây dựng ApplicationUser trường hợp lưu trữ user trường (tổ chức từ cơ sở dữ liệu MySQL) để lấy dữ liệu người dùng, tôi nhận được lỗi sau:

The entity type ApplicationUser is not part of the model for the current context.

Tôi giả sử tôi cần phải lưu trữ dữ liệu nhận dạng trong cơ sở dữ liệu MySQL của tôi, nhưng không thể tìm thấy bất kỳ tài nguyên nào về cách thực hiện điều đó. Tôi đã thử gỡ bỏ hoàn toàn lớp ApplicationUser và làm cho lớp thực thể user của mình xuất phát từ IdentityUser, nhưng gọi UserManager.CreateAsync dẫn đến lỗi chuyển đổi LINQ to Entities.

Làm thế nào để xác thực thiết lập trong một ứng dụng Web API 2, có một user thực hiện hành?

Trả lời

19

Bạn nói:

I want to implement a login/registration system (so that I can implement roles and permissions in the future, and restrict certain API requests).

How do I setup authentication in a Web API 2 application, having an existing user entity?

Nó chắc chắn có nghĩa là bạn KHÔNG cần ASP.NET Identity. ASP.NET Identity là một công nghệ để xử lý tất cả các chất liệu của người dùng. Nó thực sự không "làm" cơ chế xác thực. ASP.NET Identity sử dụng cơ chế xác thực OWIN, đó là một thứ khác.

gì bạn đang tìm kiếm không phải là "làm thế nào để sử dụng ASP.NET nhận dạng với bàn của tôi hiện có người dùng", nhưng "Làm thế nào để cấu hình OWIN xác thực sử dụng bảng Người dùng hiện tại của tôi"

Để sử dụng OWIN Auth làm theo các bước sau:

Cài đặt các gói:

Owin 
Microsoft.AspNet.Cors 
Microsoft.AspNet.WebApi.Client 
Microsoft.AspNet.WebApi.Core 
Microsoft.AspNet.WebApi.Owin 
Microsoft.AspNet.WebApi.WebHost 
Microsoft.Owin 
Microsoft.Owin.Host.SystemWeb 
Microsoft.Owin.Security 
Microsoft.Owin.Security.OAuth 

Tạo Startup.cs tập tin bên trong thư mục gốc (examp le):

chắc chắn rằng [assembly: OwinStartup] được cấu hình đúng

[assembly: OwinStartup(typeof(YourProject.Startup))] 
namespace YourProject 
{ 
    public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
      var config = new HttpConfiguration(); 
      //other configurations 

      ConfigureOAuth(app); 
      app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 
      app.UseWebApi(config); 
     } 

     public void ConfigureOAuth(IAppBuilder app) 
     { 
      var oAuthServerOptions = new OAuthAuthorizationServerOptions() 
      { 
       AllowInsecureHttp = true, 
       TokenEndpointPath = new PathString("/api/security/token"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromHours(2), 
       Provider = new AuthorizationServerProvider() 
      }; 

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

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

     public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
     { 
      context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); 

      try 
      { 
       //retrieve your user from database. ex: 
       var user = await userService.Authenticate(context.UserName, context.Password); 

       var identity = new ClaimsIdentity(context.Options.AuthenticationType); 

       identity.AddClaim(new Claim(ClaimTypes.Name, user.Name)); 
       identity.AddClaim(new Claim(ClaimTypes.Email, user.Email)); 

       //roles example 
       var rolesTechnicalNamesUser = new List<string>(); 

       if (user.Roles != null) 
       { 
        rolesTechnicalNamesUser = user.Roles.Select(x => x.TechnicalName).ToList(); 

        foreach (var role in user.Roles) 
         identity.AddClaim(new Claim(ClaimTypes.Role, role.TechnicalName)); 
       } 

       var principal = new GenericPrincipal(identity, rolesTechnicalNamesUser.ToArray()); 

       Thread.CurrentPrincipal = principal; 

       context.Validated(identity); 
      } 
      catch (Exception ex) 
      { 
       context.SetError("invalid_grant", "message"); 
      } 
     } 
    } 
} 

Sử dụng [Authorize] thuộc tính cho phép các hành động.

Gọi api/security/token với GrantType, UserNamePassword để nhận mã thông báo mang. Như thế này:

"grant_type=password&username=" + username + "&password=" password; 

Gửi token trong HttpHeader Authorization như Bearer "YOURTOKENHERE". Như thế này:

headers: { 'Authorization': 'Bearer ' + token } 

Hy vọng điều đó sẽ hữu ích!

+0

Cảm ơn, đây là những gì tôi đang tìm kiếm. Xin lỗi nếu câu hỏi của tôi là không rõ ràng, nhưng tôi đã nhầm lẫn bởi "vai trò" của ASP.NET Identity. –

+0

Bạn là người bạn đời thân thiết. Nếu bạn gặp khó khăn trong quá trình thực hiện, đừng ngần ngại bình luận ở đây –

+1

Xin chào, bạn có thể cho tôi biết đối tượng userService trong mã của bạn ở trên không? Chỉ cần một đối tượng lớp tùy chỉnh mà sẽ kết nối với bối cảnh DB của tôi và trả lại người dùng tùy chỉnh của tôi từ DB? Người dùng không phải kế thừa sau IUser hay bất cứ thứ gì? – Savail

7

Từ giản đồ DB của bạn không tương thích với mặc định UserStore Bạn phải thực hiện của riêng bạn UserStoreUserPasswordStore lớp sau đó tiêm họ UserManager. Hãy xem xét ví dụ này đơn giản:

đầu tiên viết lớp người sử dụng tùy chỉnh của bạn và thực hiện IUser giao diện:

class User:IUser<int> 
{ 
    public int ID {get;set;} 
    public string Username{get;set;} 
    public string Password_hash {get;set;} 
    // some other properties 
} 

Bây giờ tác giả tùy chỉnh của bạn UserStoreIUserPasswordStore lớp như thế này:

public class MyUserStore : IUserStore<User>, IUserPasswordStore<User> 
{ 
    private readonly MyDbContext _context; 

    public MyUserStore(MyDbContext context) 
    { 
     _context=context; 
    } 

    public Task CreateAsync(AppUser user) 
    { 
     // implement your desired logic such as 
     // _context.Users.Add(user); 
    } 

    public Task DeleteAsync(AppUser user) 
    { 
     // implement your desired logic 
    } 

    public Task<AppUser> FindByIdAsync(string userId) 
    { 
     // implement your desired logic 
    } 

    public Task<AppUser> FindByNameAsync(string userName) 
    { 
     // implement your desired logic 
    } 

    public Task UpdateAsync(AppUser user) 
    { 
     // implement your desired logic 
    } 

    public void Dispose() 
    { 
     // implement your desired logic 
    } 

    // Following 3 methods are needed for IUserPasswordStore 
    public Task<string> GetPasswordHashAsync(AppUser user) 
    { 
     // something like this: 
     return Task.FromResult(user.Password_hash); 
    } 

    public Task<bool> HasPasswordAsync(AppUser user) 
    { 
     return Task.FromResult(user.Password_hash != null); 
    } 

    public Task SetPasswordHashAsync(AppUser user, string passwordHash) 
    { 
     user.Password_hash = passwordHash; 
     return Task.FromResult(0); 
    } 
} 

Bây giờ bạn có rất riêng cửa hàng người dùng chỉ cần tiêm nó cho người quản lý người dùng:

public class ApplicationUserManager: UserManager<User, int> 
{ 
    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    { 
     var manager = new ApplicationUserManager(new MyUserStore(context.Get<MyDbContext>())); 
     // rest of code 
    } 
} 

Cũng xin lưu ý rằng bạn phải trực tiếp kế thừa lớp Ngữ cảnh DB của bạn từ DbContext không phải IdentityDbContext vì bạn đã triển khai cửa hàng người dùng riêng.

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