【问题标题】:.NET Core 3.1 web application with React - how to prevent access based on Active Directory group.NET Core 3.1 Web 应用程序与 React - 如何防止基于 Active Directory 组的访问
【发布时间】:2020-08-07 14:20:25
【问题描述】:

我有一个 .NET Core 3.1 Web 应用程序,带有使用 Windows 身份验证的 React。 当用户输入他们的 Active Directory 凭据时,我想在允许访问 React 应用程序之前验证他们是否属于特定的 Active Directory 组。

我尝试将默认端点设置为登录控制器以验证用户的组,但如果他们确实有有效的组,我不知道如何重定向到 React 应用程序。

Startup.cs:

app.UseEndpoints(endpoints =>
  {                
      endpoints.MapControllerRoute(
          name: "default",
          pattern: "{controller}/{action=Index}/{id?}",
          defaults: new { Controller = "Login", action = "Index" });
  });

登录控制器:

public IActionResult Index()
{
        if (HttpContext.User.Identity.IsAuthenticated)
        {
            string[] domainAndUserName = HttpContext.User.Identity.Name.Split('\\');
             //AuthenticateUser verifies if the user is in the correct Active Directory group
            if (AuthenticateUser(domainAndUserName[0], domainAndUserName[1]))
            {
                //This is where i would like to redirect to the React app
                return Ok(); //This does not go to the react app
                return LocalRedirect("http://localhost:50296/"); //This will keep coming back to this method
            }
            return BadRequest();            
        }
}

是否可以从控制器重定向到 React 应用程序? 有没有更好的方法来验证活动目录组,可能是通过 authorizationService.js?

【问题讨论】:

  • 您可以在授权过滤器中处理它。
  • 您能否提供任何细节或链接,以帮助我找到正确的方向?
  • 代替 return LocalRedirect(string),使用 return Page()return RedirectToPage("/Index") 或任何您的默认页面。
  • 不。我上面错了。我认为这条线应该为你做 :) return RedirectPermanent("http://localhost:50296/");

标签: reactjs asp.net-core


【解决方案1】:

我以前遇到过这种情况,并通过自定义实现 IClaimsTransformation 解决了它。这种方法也可以与 OpenId Connect 和其他需要额外授权的身份验证系统一起使用。

通过这种方法,您可以在为您的 React 应用程序提供服务的控制器上使用 authorize 属性

[Authorize(Roles = "HasAccessToThisApp")]

User.IsInRole("HasAccessToThisApp")

代码中的其他地方。

实施。请注意,每次请求都会调用 TransformAsync,如果有任何耗时的调用,建议进行一些缓存。

public class YourClaimsTransformer : IClaimsTransformation
{
    private readonly IMemoryCache _cache;

    public YourClaimsTransformer(IMemoryCache cache)
    {
        _cache = cache;
    }

    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal incomingPrincipal)
    {
        if (!incomingPrincipal.Identity.IsAuthenticated)
        {
            return Task.FromResult(incomingPrincipal);
        }

        var principal = new ClaimsPrincipal();

        if (!string.IsNullOrEmpty(incomingPrincipal.Identity.Name)
             && _cache.TryGetValue(incomingPrincipal.Identity.Name, out ClaimsIdentity claimsIdentity))
        {
            principal.AddIdentity(claimsIdentity);
            return Task.FromResult(principal);
        }

        // verifies that the user is in the correct Active Directory group
        var domainAndUserName = incomingPrincipal.Identity.Name?.Split('\\');
        if (!(domainAndUserName?.Length > 1 && AuthenticateUser(domainAndUserName[0], domainAndUserName[1])))
        {
            return Task.FromResult(incomingPrincipal);
        }

        var newClaimsIdentity = new ClaimsIdentity(
            new[]
            {
                new Claim(ClaimTypes.Role, "HasAccessToThisApp", ClaimValueTypes.String)

                // copy other claims from incoming if required

            }, "Windows");

        _cache.Set(incomingPrincipal.Identity.Name, newClaimsIdentity,
            DateTime.Now.AddHours(1));

        principal.AddIdentity(newClaimsIdentity);
        return Task.FromResult(principal);
    }
}

在启动#ConfigureServices 中

services.AddSingleton<IClaimsTransformation, YourClaimsTransformer>();

【讨论】:

  • 用更简单的方法更新了我的答案。你实际上不需要 IUserRepo 来解决这个问题。
  • 这很好用!谢谢你。你能分享一下你是如何缓存这个来减少调用的吗?
  • 做了一个小的改进,以减少对 AuthenticateUser 的调用次数。
猜你喜欢
  • 2022-01-01
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 2020-04-27
  • 1970-01-01
  • 1970-01-01
  • 2021-04-11
  • 2020-05-30
相关资源
最近更新 更多