gpt4 book ai didi

c# - ASP.NET Core Web API 自定义 AuthorizeAttribute 问题

转载 作者:行者123 更新时间:2023-12-05 02:44:17 29 4
gpt4 key购买 nike

我正在研究 ASP.NET Core Web API。我正在尝试创建自定义 Authorize 属性,但我被卡住了。我不明白我错过了什么。我有以下代码用于 Authorize 属性和过滤器:

public class AuthorizeAttribute : TypeFilterAttribute
{
public AuthorizeAttribute(params string[] claim) : base(typeof(AuthorizeFilter))
{
Arguments = new object[] { claim };
}
}

public class AuthorizeFilter : IAuthorizationFilter
{
readonly string[] _claim;

public AuthorizeFilter(params string[] claim)
{
_claim = claim;
}

public void OnAuthorization(AuthorizationFilterContext context)
{
var IsAuthenticated = context.HttpContext.User.Identity.IsAuthenticated;
var claimsIndentity = context.HttpContext.User.Identity as ClaimsIdentity;

if (IsAuthenticated)
{
bool flagClaim = false;
foreach (var item in _claim)
{
if (context.HttpContext.User.HasClaim("Role", item))
flagClaim = true;
}

if (!flagClaim)
{
//if (context.HttpContext.Request.IsAjaxRequest())
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; //Set HTTP 403
//else
// context.Result = new RedirectResult("~/Login/Index");
}
}
else
{
//if (context.HttpContext.Request.IsAjaxRequest())
//{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; //Set HTTP 401 -
//}
//else
//{
// context.Result = new RedirectResult("~/Login/Index");
//}
}
return;
}
}

我从某处复制了这段代码并注释掉了不必要的行。

这是我的 Controller 类,我想把它放在这里:

[Route("api/[controller]/[action]")]
[ApiController]
[Authorize]
public class JobController : ControllerBase
{
// GET: api/<JobController>
[HttpGet]
[ActionName("GetAll")]
public List<Job> Get()
{
return JobDataLog.GetAllJobQueue();
}

// GET api/<JobController>/5
[HttpGet("{ID}")]
[ActionName("GetByID")]
public Job Get(Guid ID)
{
return JobDataLog.GetJob(ID);
}

// GET api/<JobController>/5
[HttpGet]
[ActionName("GetCount")]
public int GetCount()
{
return JobDataLog.GetJobTotal();
}
}

还有Startup.cs的Configure和ConfigureService方法

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(60);
});

var tokenKey = Configuration.GetValue<string>("TokenKey");
var key = Encoding.ASCII.GetBytes(tokenKey);
services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; })
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddSingleton<IJWTAuthenticationManager>(new JWTAuthenticationManager(tokenKey));
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseCookiePolicy();
app.UseSession();
app.Use(async (context, next) =>
{
var JWToken = context.Session.GetString("JWToken");
if (!string.IsNullOrEmpty(JWToken))
{
context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
}
await next();
});

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

问题是,即使这个 Controller 有 Authorize 属性,所有的操作都被调用,即使 Authorize 过滤器使授权无效。

此外,当我在 OnAuthorization 方法中放置以下代码时:

context.Result = new StatusCodeResult(StatusCodes.Status401Unauthorized);

它阻止了所有操作的访问,包括那些具有 AllowAnnoynmous 属性的操作。

请帮助我,过去 3 个小时我一直被困在这个问题上。

最佳答案

如果您真的想使用自定义的 AuthorizeAttribute,那么您可以这样做。 :)

你会有一些波浪线,但 VS 将能够自动添加 using 语句。

原始代码有多个问题:

  1. 设置 Reponse.StatusCode 实际上不会导致返回响应。
  2. HttpContext.User 首先不会被填充,因为 ASP.NET Core 只会尝试对用户进行身份验证并填充用户的声明/身份(如果端点使用内置的 -在 AuthorizeAttribute 中。以下代码通过从 AuthorizeAttribute 派生来解决此问题。
  3. 在这种情况下,不需要额外的过滤器工厂类,因为您没有注入(inject)依赖项。但是,如果你必须注入(inject),我认为你会倒霉,因为你不能同时从 TypeFilterAttributeAuthorizeAttribute 派生,并且声明列表将是总是空的。

工作代码

public class MyAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
readonly string[] _requiredClaims;

public MyAuthorizeAttribute(params string[] claims)
{
_requiredClaims = claims;
}

public void OnAuthorization(AuthorizationFilterContext context)
{
var isAuthenticated = context.HttpContext.User.Identity.IsAuthenticated;
if (!isAuthenticated)
{
context.Result = new UnauthorizedResult();
return;
}

var hasAllRequredClaims = _requiredClaims.All(claim => context.HttpContext.User.HasClaim(x => x.Type == claim));
if (!hasAllRequredClaims)
{
context.Result = new ForbidResult();
return;
}
}
}

您可能应该改用策略

之所以以如此糟糕的方式工作,是因为 ASP.NET Core 团队不希望您编写自定义授权属性。参见 this answer on the subject . “正确”的方法是创建政策,并将您的 claim 要求分配给这些政策。但我也认为授权如此死板且缺乏对基本场景的支持是愚蠢的。

关于c# - ASP.NET Core Web API 自定义 AuthorizeAttribute 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66536416/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com