2016-10-28 10 views
1

Сценарий......................................Заполнение пользовательских требований от SQL с помощью Windows Authenticated app. .Net Core

Успех на сегодняшний день - Пользователь аутентифицирован и заявки на окна доступны (имя и группы). Identity.Name может использоваться для возврата модели пользователя домена из базы данных с расширенными свойствами.

Проблема и вопрос. Я пытаюсь затем заполнить одно свойство претензий «Идентификатор» и иметь доступ к глобальному доступу через ClaimsPrincipal. Я долгое время смотрел в ClaimsTransformation. В других статьях я прочитал, что вы ДОЛЖНЫ добавить претензии до входа в систему, но может ли это действительно быть правдой? Это означает, что полная зависимость от AD для выполнения всех требований, действительно ли это так?

Ниже приведен мой простой код на данный момент в HomeController. Я ударяю базу данных, а затем пытаюсь заполнить ClaimsPrincipal, но затем верну его модель пользователя домена. Я думаю, что это может быть, где моя проблема, но я новичок в авторизации в .net и изо всех сил пытаюсь склонить голову к утверждениям.

Большое спасибо за все помощь получили

Текущий код:

public IActionResult Index() 
     { 
      var user = GetExtendedUserDetails(); 
      User.Claims.ToList(); 
      return View(user); 
     } 

     private Models.User GetExtendedUserDetails() 
     { 
      var user = _context.User.SingleOrDefault(m => m.Username == User.Identity.Name.Remove(0, 6)); 
      var claims = new List<Claim>(); 

      claims.Add(new Claim("Id", Convert.ToString(user.Id), ClaimValueTypes.String)); 
      var userIdentity = new ClaimsIdentity("Intranet"); 
      userIdentity.AddClaims(claims); 
      var userPrincipal = new ClaimsPrincipal(userIdentity); 

      return user; 
     } 

UPDATE:

Я зарегистрировал ClaimsTransformation

app.UseClaimsTransformation(o => new ClaimsTransformer().TransformAsync(o)); 

и построен ClaimsTransformer, как показано ниже в строке с t его GitHub запрос

https://github.com/aspnet/Security/issues/863

public class ClaimsTransformer : IClaimsTransformer 
{ 
    private readonly TimesheetContext _context; 
    public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context) 
    { 

     System.Security.Principal.WindowsIdentity windowsIdentity = null; 

     foreach (var i in context.Principal.Identities) 
     { 
      //windows token 
      if (i.GetType() == typeof(System.Security.Principal.WindowsIdentity)) 
      { 
       windowsIdentity = (System.Security.Principal.WindowsIdentity)i; 
      } 
     } 

     if (windowsIdentity != null) 
     { 
      //find user in database 
      var username = windowsIdentity.Name.Remove(0, 6); 
      var appUser = _context.User.FirstOrDefaultAsync(m => m.Username == username); 

      if (appUser != null) 
      { 

       ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Id", Convert.ToString(appUser.Id))); 

       /*//add all claims from security profile 
       foreach (var p in appUser.Id) 
       { 
        ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(p.Permission, "true")); 
       }*/ 

      } 

     } 
     return await System.Threading.Tasks.Task.FromResult(context.Principal); 
    } 
} 

Но я получаю NullReferenceException: Ссылка на объект не указывает на экземпляр объекта ошибки, несмотря на возвратившись модель предметной области ранее.

С STARTUP.CS

using System; 
using Microsoft.AspNetCore.Builder; 
using Microsoft.AspNetCore.Hosting; 
using Microsoft.Extensions.Configuration; 
using Microsoft.Extensions.DependencyInjection; 
using Microsoft.Extensions.Logging; 
using Birch.Intranet.Models; 
using Microsoft.EntityFrameworkCore; 

namespace Birch.Intranet 
{ 
    public class Startup 
    { 
     public Startup(IHostingEnvironment env) 
     { 
      var builder = new ConfigurationBuilder() 
       .SetBasePath(env.ContentRootPath) 
       .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 
       .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) 
       .AddEnvironmentVariables(); 
      Configuration = builder.Build(); 
     } 

     public IConfigurationRoot Configuration { get; } 

     // This method gets called by the runtime. Use this method to add services to the container. 
     public void ConfigureServices(IServiceCollection services) 
     { 
      services.AddAuthorization(); 

      // Add framework services. 
      services.AddMvc(); 
      // Add database 
      var connection = @"Data Source=****;Initial Catalog=Timesheet;Integrated Security=True;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"; 
      services.AddDbContext<TimesheetContext>(options => options.UseSqlServer(connection)); 

      // Add session 
      services.AddSession(options => { 
       options.IdleTimeout = TimeSpan.FromMinutes(60); 
       options.CookieName = ".Intranet"; 
      }); 
     } 

     // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
     { 
      loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
      loggerFactory.AddDebug(); 

      if (env.IsDevelopment()) 
      { 
       app.UseDeveloperExceptionPage(); 
       app.UseBrowserLink(); 
      } 
      else 
      { 
       app.UseExceptionHandler("/Home/Error"); 
      } 

      app.UseClaimsTransformation(o => new ClaimsTransformer().TransformAsync(o)); 

      app.UseSession(); 
      app.UseDefaultFiles(); 
      app.UseStaticFiles(); 

      app.UseMvc(routes => 
      { 
       routes.MapRoute(
        name: "default", 
        template: "{controller=Home}/{action=Index}/{id?}"); 
      }); 
     } 
    } 
} 
+0

Не могли бы вы опубликовать startup.cs? –

+0

@ademcaglin сделано в приведенном выше правиле. Я обнаружил, что dbcontext стал недоступным в классе ..., который бы сильно ударил db. :-) Не знаю, почему. – K7Buoy

ответ

4

Вы должны использовать IClaimsTransformer с инъекцией зависимостей.

app.UseClaimsTransformation(async (context) => 
    { 
     IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>(); 
     return await transformer.TransformAsync(context); 
    }); 

    // Register 
    services.AddScoped<IClaimsTransformer, ClaimsTransformer>(); 

И нужно вводить DbContext в ClaimsTransformer

public class ClaimsTransformer : IClaimsTransformer 
{ 
    private readonly TimesheetContext _context; 
    public ClaimsTransformer(TimesheetContext dbContext) 
    { 
     _context = dbContext; 
    } 
    // .... 
} 
+0

Контекст базы данных (_context) по-прежнему является нулевым в классе ClaimTransformer, но это происходит по правильной линии. – K7Buoy

+0

Вы добавили последнюю часть моего ответа? –

+0

хорошо. это неловко! нет, я этого не делал. Я не могу вас поблагодарить, потерял время. – K7Buoy