1

私は、認証にActive Directoryを使用するかなり単純なイントラネットアプリケーションを作成しようとしており、AspNetRolesテーブルを使用して、ユーザーが特定のアプリケーションロールにいるかどうかを確認します。このアプリは、一部のユーザーがイベント/コンテストを作成して、他のユーザーがコンテストにエントリーを提出することができる社内宝くじです。 、 「コンテスト」の実体にGET操作を行うことができます - 「イベント」または 「コンテスト」の実体 ASP.NETコアWindowsの認証とアプリケーションのロール

  • 出場者にCRUD操作を行うことができます -

    • 管理者:私は2つの基本的な役割で出始めと思っています新しい「エントリ」エンティティを作成することができます。

    ここで私は固執しています:Windows認証は、コントローラからは、私がUser.Identity.Nameを実行し、私のドメインログイン名を見ることができるという意味で働いています。さらに、User.IsInRole("Domain Users")を実行して、アカウントがドメイングループに所属していることを確認できます。アプリケーションの役割ごとに新しいADグループを作成したくない場合(道路の設計変更で追加の役割が必要になった場合)、コントローラで承認を使用してアプリケーションの役割を確認するにはどうすればよいですか?ここで

    は、私が使用したいコントローラ例です:次のように私のStartup.csで

    [Route("api/[controller]")] 
    [Authorize(Roles = "Contestant")] 
    public class EventTypesController : Controller 
    { 
        private IRaffleRepository _repository; 
        private ILogger<EventTypesController> _logger; 
    
        public EventTypesController(IRaffleRepository repository, ILogger<EventTypesController> logger) 
        { 
         _repository = repository; 
         _logger = logger; 
        } 
    
        [HttpGet("")] 
        public IActionResult Get() 
        { 
         try 
         { 
          var results = _repository.GetAllEventTypes(); 
          return Ok(Mapper.Map<IEnumerable<EventTypeViewModel>>(results)); 
         } 
         catch (Exception ex) 
         { 
          _logger.LogError($"Failed to get all event types: {ex}"); 
          return BadRequest("Error occurred"); 
         } 
        } 
    } 
    

    、ConfigureServicesで、私はアイデンティティをアップ配線しています:

    services.AddIdentity<RaffleUser, ApplicationRole>() 
          .AddEntityFrameworkStores<RaffleContext>(); 
    

    マイRaffleUserクラスが実際にありますIdentityUserのデフォルトの実装:

    public class RaffleUser : IdentityUser 
    { 
    
    } 
    

    My ApplicationRole cla ssはIdentityRoleのデフォルト実装です。私もシードクラスにいくつかのデータを播種してみました:

    if (!await _roleManager.RoleExistsAsync("Administrator")) 
    { 
        var adminRole = new ApplicationRole() 
        { 
         Name = "Administrator" 
        }; 
        await _roleManager.CreateAsync(adminRole); 
        await _context.SaveChangesAsync(); 
    } 
    
    if (await _userManager.FindByNameAsync("jmoor") == null) 
    { 
        using (var context = new PrincipalContext(ContextType.Domain)) 
        { 
         var principal = UserPrincipal.FindByIdentity(context, "DOMAIN\\jmoor"); 
         if (principal != null) 
         { 
          var user = new RaffleUser() 
          { 
           Email = principal.EmailAddress, 
           UserName = principal.SamAccountName 
          }; 
    
          await _userManager.CreateAsync(user); 
          await _context.SaveChangesAsync(); 
    
          var adminRole = await _roleManager.FindByNameAsync("Administrator"); 
          if (adminRole != null) 
          { 
           await _userManager.AddToRoleAsync(user, adminRole.Name); 
           await _context.SaveChangesAsync(); 
          } 
         } 
        } 
    } 
    

    データをテーブルにしますが、それは単にコントローラレベルでのように思える、私はIdentityUserに認証されたユーザーを変換する必要があります。私のためにこれを行うためにミドルウェアクラスが必要ですか?それがすべてのコントローラで許可を再利用できるようにする最良の方法でしょうか?

  • 答えて

    0

    Windows認証を使用するには、DefaultChallangeSchemeを追加する必要があります。これは私のやり方ですが、もし誰かがもっと良い解決策を持っていれば、私はすべての耳です:)

    私は現在のアプリケーションで次の設定を使用します。

    services.AddIdentity<ApplicationUser, ApplicationRole>() 
          .AddEntityFrameworkStores<SecurityDbContext>() 
          .AddDefaultTokenProviders(); 
    
    services.AddAuthentication(options => 
    { 
          options.DefaultChallengeScheme = IISDefaults.AuthenticationScheme; 
    }); 
    

    それから私は、変圧器で自分のアプリケーションの特許請求の範囲に入れました。

    services.AddTransient<IClaimsTransformation, ClaimsTransformer>(); 
    

    これは正しい方向にあなたを得ることを望みます。

    +0

    oops。あなたの質問の日付が見えませんでした。私はあなたがそれをずっと前に解決したことを願っている – Peter

    +0

    私はすべてのコントローラを徹底的にテストしていませんが、これは私が探していたものを達成するように見えます。私は、新しいポリシーベースの認証を使用している、私が思いついた代替案を投稿します。 –

    0

    最初に、私は、UserClaimsとRoleClaimsで設定されたClaimsPrincipalを返すカスタムClaimsTransformerを作成しました(私のアプリケーションをリファクタリングした後、ポリシーベースの承認を取得することにしました。ユーザーレベル):私はStartup.csにそれを有線

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context) 
    { 
        var identity = (ClaimsIdentity)context.Principal.Identity; 
        var userName = identity.Name; 
        if (userName != null) 
        { 
         var user = await _userManager.FindByLoginAsync("ActiveDirectory", userName); 
         if (user != null) 
         { 
          identity.AddClaims(await _userManager.GetClaimsAsync(user)); 
          var roles = await _userManager.GetRolesAsync(user); 
          identity.AddClaims(await GetRoleClaims(roles)); 
         } 
        } 
        return context.Principal; 
    } 
    
    private async Task<List<Claim>> GetRoleClaims(IList<string> roles) 
    { 
        List<Claim> allRoleClaims = new List<Claim>(); 
        foreach (var role in roles) 
        { 
         var rmRole = await _roleManager.FindByNameAsync(role); 
         var claimsToAdd = await _roleManager.GetClaimsAsync(rmRole); 
         allRoleClaims.AddRange(claimsToAdd); 
        } 
        return allRoleClaims; 
    } 
    

    services.AddScoped<IClaimsTransformer, Services.ClaimsTransformer>(); 
    

    は、私はまた、ポリシーベースの認証と一緒に行きました:

    services.AddAuthorization(options => 
    { 
        options.AddPolicy("Administrator", policy => policy.RequireClaim("AccessLevel", "Administrator")); 
        options.AddPolicy("Project Manager", policy => policy.RequireClaim("AccessLevel", "Project Manager")); 
    }); 
    

    したがって、ユーザーまたは役割には、 "AccessLevel"という名前と値を指定したクレームセットを設定できます。すべてを終了するために、CreateAsyncの間にActiveDirectoryの追加の詳細をUserオブジェクトに入力するカスタムUserManagerも作成しました。

    関連する問題