2017-09-20 28 views
5

(Edit - Tìm thấy sửa chữa thích hợp xem dưới đây!)Net Lõi 2.0 Web API sử dụng JWT - Thêm danh tính phá vỡ xác thực JWT

OK - đây là nỗ lực đầu tiên của tôi tại Net Lõi 2.0 và xác thực, mặc dù Tôi đã làm những việc với Web API 2.0 trong quá khứ, và đã làm việc khá rộng rãi trên các dự án MVC và Webforms ASP trong vài năm qua.

Tôi đang cố gắng tạo một dự án API Web API bằng .Net Core. Điều này sẽ tạo thành phần cuối của ứng dụng nhiều người thuê để sản xuất một số báo cáo, vì vậy tôi cần có khả năng xác thực người dùng. Có vẻ như cách tiếp cận thông thường là sử dụng JWT - trước tiên hãy xác thực người dùng để tạo mã thông báo, sau đó chuyển cho khách hàng để sử dụng trên mọi yêu cầu API. Dữ liệu sẽ được lưu trữ và truy xuất bằng EF Core.

Tôi đã theo dõi this post một cách cơ bản để thiết lập cài đặt này và tôi đã thực hiện thao tác này - Tôi có bộ điều khiển chấp nhận tên người dùng/mật khẩu và trả về mã thông báo nếu hợp lệ và một số chính sách ủy quyền được thiết lập dựa trên các tuyên bố.

Điều tiếp theo tôi cần là thực sự quản lý người dùng/mật khẩu/v.v. Tôi nghĩ rằng tôi sẽ chỉ sử dụng. Net Core Identity cho điều này như vậy tôi sẽ có rất nhiều mã sẵn sàng để lo lắng về người dùng/vai trò, mật khẩu, v.v .. Tôi đang sử dụng lớp tùy chỉnh UserUserRole các lớp học bắt nguồn từ tiêu chuẩn IdentityUserIdentityRole lớp học, nhưng tôi đã hoàn nguyên về các lớp chuẩn ngay bây giờ.

Vấn đề tôi có là tôi không thể tìm ra cách để thêm danh tính & đăng ký tất cả các Dịch vụ khác nhau (rolemanager, usermanager, v.v.) mà không vi phạm xác thực - về cơ bản ngay khi tôi thêm dòng này vào Startup.ConfigureServices lớp:

services.AddIdentity<IdentityUser, IdentityRole>() 
    .AddEntityFrameworkStores<MyContext>(); 

Tất cả đều sai, và tôi không còn có thể nhìn thấy bất kỳ khiếu nại khi tôi nhận được yêu cầu, vì vậy tất cả các chính sách chỉ khóa xuống và bạn không thể có được bất cứ điều gì.

Nếu tôi không có các dòng đó, thì tôi sẽ gặp phải các lỗi liên quan đến UserManager, RoleManager, UserStore, v.v. tất cả không được đăng ký cho DI.

Vậy ... làm thế nào (nếu có thể) tôi có thể đăng ký nhận dạng và móc nó lên đúng ngữ cảnh, nhưng tránh/loại bỏ bất kỳ thay đổi nào đối với cơ chế ủy quyền thực tế?

Tôi đã xem xét một chút công bằng trực tuyến, nhưng rất nhiều điều này đã thay đổi kể từ .Net Core 1.x nên rất nhiều hướng dẫn, v.v. không thực sự hợp lệ nữa.

Tôi không dự định ứng dụng API này có bất kỳ mã giao diện người dùng nào, vì vậy tôi không cần bất kỳ xác thực cookie nào cho biểu mẫu hoặc bất kỳ thứ gì cho đến bây giờ.

Sửa
ok, bây giờ tôi đã phát hiện ra rằng trong mã này thiết lập xác thực JWT trong Startup.ConfigureServices() phương pháp:

services.AddAuthentication(
      JwtBearerDefaults.AuthenticationScheme) 
       .AddJwtBearer(options => 
       { 
       >>breakpoint>>> options.TokenValidationParameters = 
         new TokenValidationParameters 
         { 
          ValidateIssuer = true, 
          ValidateAudience = true, 
          ValidateLifetime = true, 
          ValidateIssuerSigningKey = true, 

          ValidIssuer = "Blah.Blah.Bearer", 
          ValidAudience = "Blah.Blah.Bearer", 
          IssuerSigningKey = 
          JwtSecurityKey.Create("verylongsecretkey") 

         }; 
       }); 

Nếu tôi đặt một breakpoint tại dòng ghi (thông qua "> > breakpoint >>> ") sau đó nó bị trúng khi tôi không thêm các dòng để thêm dịch vụ nhận dạng, nhưng nếu tôi thêm các dòng đó thì không bao giờ bị bị trúng. Điều này đúng bất kể ở đâu trong phương pháp tôi đặt lệnh gọi services.AddIdentity().Tôi nhận được rằng điều này chỉ đơn giản là một lambda vì vậy nó được thực hiện tại một điểm sau đó, nhưng có cách nào tôi có thể nhận được các công cụ AddIdentity để không thiết lập xác thực, hoặc làm cho mã ngay lập tức loại bỏ nó? Tôi cho rằng tại một số điểm có một số mã mà bầu không chạy Lambda cho cấu hình tôi đã thiết đó như những thứ nhận dạng đã thiết lập nó ...

Thanks for reading tất cả những gì nếu bạn có :)

EDIT - tìm thấy một câu trả lời
ok, tôi cuối cùng đã tìm thấy vấn đề này GH mà về cơ bản là chính xác vấn đề này: https://github.com/aspnet/Identity/issues/1376

Về cơ bản những gì tôi phải làm là tăng gấp đôi:

Ens ure rằng cuộc gọi đến services.AddIdentity<IdentityUser, IdentityContext() đã được thực hiện đầu tiên

Thay đổi cuộc gọi để thêm auth từ:

services.AddAuthentication(
      JwtBearerDefaults.AuthenticationScheme) 
       .AddJwtBearer(options => 
... 

Để:

services.AddAuthentication(options => 
     { 
      options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 
      options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 
     }) 
      .AddJwtBearer(options => 
... 

này khó chịu dẫn đến một cookie được tạo ra, nhưng điều này không được sử dụng để xác thực như xa như tôi có thể nói - nó hoàn toàn sử dụng mã thông báo mang về các yêu cầu đối với bộ điều khiển/hành động có số ít nhất là [Authorize(Policy = "Administrator")] hoặc ít nhất.

Tôi cần kiểm tra thêm và tôi sẽ cố gắng quay lại đây cập nhật nếu tôi thấy nó không hoạt động theo một cách nào đó.

(Edited - đưa giải pháp thích hợp trong như một câu trả lời bây giờ)

+0

bạn đã lưu tôi. cảm ơn –

+0

bạn nên xem xét việc chia nhỏ câu hỏi này thành một câu hỏi và sau đó tự trả lời câu hỏi đó như một câu trả lời đúng. – alwayslearning

+0

@alwayslearning không phải là một ý tưởng tồi ... vì vậy tôi đã làm như vậy. – GPW

Trả lời

3

tôi cuối cùng đã cùng nhau đưa các giải pháp, vì vậy trên gợi ý của người sử dụng alwayslearning tôi đã chỉnh sửa bài viết của tôi và tôi đặt này trong như một thực tế câu trả lời.

ok, Điều này có thể được thực hiện đúng cách. Trước tiên, bạn cần sử dụng các tùy chọn Xác thực mà tôi đã chỉ ra trong bản chỉnh sửa ở trên - điều đó là tốt. Sau đó, bạn cần sử dụng services.AddIdentityCore<TUser>() thay vì services.AddIdentity<TUser>(). Tuy nhiên, điều này không thêm một loạt các thứ để quản lý vai trò, và dường như thiếu nhà xây dựng thích hợp để cung cấp cho nó kiểu Vai trò mà bạn muốn sử dụng. Điều này có nghĩa rằng trong trường hợp của tôi, tôi đã phải làm điều này:

IdentityBuilder builder = services.AddIdentityCore<IdentityUser>(opt => 
     { 
      opt.Password.RequireDigit = true; 
      opt.Password.RequiredLength = 8; 
      opt.Password.RequireNonAlphanumeric = false; 
      opt.Password.RequireUppercase = true; 
      opt.Password.RequireLowercase = true; 
     } 
     ); 
     builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services); 
     builder 
      .AddEntityFrameworkStores<MyContext>(); 
     //.AddDefaultTokenProviders(); 

     builder.AddRoleValidator<RoleValidator<IdentityRole>>(); 
     builder.AddRoleManager<RoleManager<IdentityRole>>(); 
     builder.AddSignInManager<SignInManager<IdentityUser>>(); 

Sau khi làm điều đó, điều tiếp theo là để đảm bảo rằng khi xác nhận một người dùng đăng nhập (trước khi gửi một mã thông báo), bạn hãy chắc chắn để sử dụng phương pháp SignInManager CheckPasswordSignInAsynckhôngPasswordSignInAsync:

public async Task<IdentityUser> GetUserForLogin(string userName, string password) 
    { 
     //find user first... 
     var user = await _userManager.FindByNameAsync(userName); 

     if (user == null) 
     { 
      return null; 
     } 

     //validate password... 
     var signInResult = await _signInManager.CheckPasswordSignInAsync(user, password, false); 

     //if password was ok, return this user. 
     if (signInResult.Succeeded) 
     { 
      return user; 
     } 

     return null; 
    } 

nếu bạn sử dụng phương pháp PasswordSignInAsync sau đó bạn sẽ nhận được một lỗi thời gian chạy lại. Không có IAuthenticationSignInHandler được định cấu hình.

Tôi hy vọng điều này sẽ giúp ai đó tại một số thời điểm.

+0

Bạn chắc chắn đã giúp tôi. Cảm ơn rất nhiều. Có rất nhiều hướng dẫn đã lỗi thời trên internet khi bạn không có kinh nghiệm với JWT hoặc Identity thật khó để tìm ra giải pháp. –

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