AuthorizationHandler<T> 未在 AllowAnonymous 控制器方法中触发
AuthorizationHandler<T> is not fired in AllowAnonymous controller method
我正在使用 .Net Core 2.1 和 AngularJS 制作应用程序。
在我的 .Net Core 应用程序中,有一些方法允许经过身份验证和未经身份验证的用户访问。
这是我获取个人资料的方法
/// <summary>
/// Find personal profile.
/// </summary>
/// <param name="id">Id of user. 0 for the request sender profile</param>
/// <returns></returns>
[HttpGet("personal-profile/{id}")]
[AllowAnonymous]
public async Task<IActionResult> FindProfile([FromRoute] int? id)
{
// Get requester identity.
var profile = IdentityService.GetProfile(HttpContext);
// Search for accounts.
var accounts = UnitOfWork.Accounts.Search();
if (id == null || id < 1)
{
if (profile != null)
accounts = accounts.Where(x => x.Id == profile.Id);
else
return Ok();
}
else
accounts = accounts.Where(x => x.Id == id);
// Only search for active account.
accounts = accounts.Where(x => x.Status == AccountStatus.Available);
// Find the first account in system.
var account = await accounts.FirstOrDefaultAsync();
return Ok(account);
}
这是我的 AuthorizationHandler class。
/// <summary>
/// Handle requirement asychronously.
/// </summary>
/// <param name="context"></param>
/// <param name="requirement"></param>
/// <returns></returns>
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
SolidAccountRequirement requirement)
{
// Convert authorization filter context into authorization filter context.
var authorizationFilterContext = (AuthorizationFilterContext) context.Resource;
//var httpContext = authorizationFilterContext.HttpContext;
var httpContext = _httpContextAccessor.HttpContext;
// Find claim identity attached to principal.
var claimIdentity = (ClaimsIdentity) httpContext.User.Identity;
// Find email from claims list.
var email =
claimIdentity.Claims.Where(x => x.Type.Equals(ClaimTypes.Email))
.Select(x => x.Value)
.FirstOrDefault();
// Email is invalid.
if (string.IsNullOrEmpty(email))
{
context.Fail();
return;
}
// Find accounts based on conditions.
var accounts = _unitOfWork.Accounts.Search();
accounts = accounts.Where(x =>
x.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase) && x.Status == AccountStatus.Available);
// Find the first matched account in the system.
var account = await accounts.FirstOrDefaultAsync();
// Account is not found.
if (account == null)
return;
// Initiate claim identity with newer information from database.
var claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaim(new Claim(ClaimTypes.Email, email));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, account.Nickname));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, Enum.GetName(typeof(AccountRole), account.Role)));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Authentication,
Enum.GetName(typeof(AccountStatus), account.Status)));
// Update claim identity.
_identityService.SetProfile(httpContext, account);
context.Succeed(requirement);
}
这就是我正在做的。
- 在
AuthorizationHandler
中,检查请求身份(由 JWT Bearer 中间件解析)
- 查询数据库以查找用户信息。
- 找到用户后,用户信息将附加到
httpContext.Items[ClaimTypes.Actor]
这是我的代码中发生的事情:
- 使用邮递员向 api/user/personal-profile/0
发送请求以获取请求发件人资料。
- 在FindProfile
中,profile
变量为null而不是用户信息,这意味着AuthorizationHandler
没有被触发。
如果我从 FindProfile
方法中删除 [AllowAnonymous]
属性,一切正常。
请查看我在下面附上的那两张图片以获取更多信息:
我的问题是:
我们可以使用 AllowAnonymous 方法触发 AuthorizationHandler
吗?在我的系统中,有一些 API 可供这两种用户使用。
- 如果用户是管理员,将返回一些额外的信息。
- 如果用户是普通用户,返回的信息很少。
谢谢
> Can we make AuthorizationHandler be triggered with AllowAnonymous method?
不,你不能。 [AllowAnonymous]
绕过所有授权语句。如果您有兴趣,this is the corresponding code 中的 AuthorizeFilter.OnAuthorizationAsync
实现。
if (context.Filters.Any(item => item is IAllowAnonymousFilter))
{
return;
}
考虑删除 AllowAnonymous
并添加一些自定义逻辑。例如,您可以创建自己的 MVC 过滤器。比方说:
public class MyAllowAnonymous : ActionFilterAttribute {}
然后在AuthorizationHandler
检查authorizationFilterContext.Filters
集合是否有这个过滤器。如果是,returns context.Succeed(requirement);
。
考虑用另一个 IAuthorizationRequirement
.
创建一个单独的 AuthorizationHandler
实现
您可以直接通过authorizationFilterContext.ActionDescriptor
获取路由名称而不是过滤器检查,并决定是否允许匿名访问。但是你的 AuthorizationHandler 应该知道路由列表。
我正在使用 .Net Core 2.1 和 AngularJS 制作应用程序。 在我的 .Net Core 应用程序中,有一些方法允许经过身份验证和未经身份验证的用户访问。
这是我获取个人资料的方法
/// <summary>
/// Find personal profile.
/// </summary>
/// <param name="id">Id of user. 0 for the request sender profile</param>
/// <returns></returns>
[HttpGet("personal-profile/{id}")]
[AllowAnonymous]
public async Task<IActionResult> FindProfile([FromRoute] int? id)
{
// Get requester identity.
var profile = IdentityService.GetProfile(HttpContext);
// Search for accounts.
var accounts = UnitOfWork.Accounts.Search();
if (id == null || id < 1)
{
if (profile != null)
accounts = accounts.Where(x => x.Id == profile.Id);
else
return Ok();
}
else
accounts = accounts.Where(x => x.Id == id);
// Only search for active account.
accounts = accounts.Where(x => x.Status == AccountStatus.Available);
// Find the first account in system.
var account = await accounts.FirstOrDefaultAsync();
return Ok(account);
}
这是我的 AuthorizationHandler class。
/// <summary>
/// Handle requirement asychronously.
/// </summary>
/// <param name="context"></param>
/// <param name="requirement"></param>
/// <returns></returns>
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
SolidAccountRequirement requirement)
{
// Convert authorization filter context into authorization filter context.
var authorizationFilterContext = (AuthorizationFilterContext) context.Resource;
//var httpContext = authorizationFilterContext.HttpContext;
var httpContext = _httpContextAccessor.HttpContext;
// Find claim identity attached to principal.
var claimIdentity = (ClaimsIdentity) httpContext.User.Identity;
// Find email from claims list.
var email =
claimIdentity.Claims.Where(x => x.Type.Equals(ClaimTypes.Email))
.Select(x => x.Value)
.FirstOrDefault();
// Email is invalid.
if (string.IsNullOrEmpty(email))
{
context.Fail();
return;
}
// Find accounts based on conditions.
var accounts = _unitOfWork.Accounts.Search();
accounts = accounts.Where(x =>
x.Email.Equals(email, StringComparison.InvariantCultureIgnoreCase) && x.Status == AccountStatus.Available);
// Find the first matched account in the system.
var account = await accounts.FirstOrDefaultAsync();
// Account is not found.
if (account == null)
return;
// Initiate claim identity with newer information from database.
var claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaim(new Claim(ClaimTypes.Email, email));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, account.Nickname));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, Enum.GetName(typeof(AccountRole), account.Role)));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Authentication,
Enum.GetName(typeof(AccountStatus), account.Status)));
// Update claim identity.
_identityService.SetProfile(httpContext, account);
context.Succeed(requirement);
}
这就是我正在做的。
- 在
AuthorizationHandler
中,检查请求身份(由 JWT Bearer 中间件解析) - 查询数据库以查找用户信息。
- 找到用户后,用户信息将附加到
httpContext.Items[ClaimTypes.Actor]
这是我的代码中发生的事情:
- 使用邮递员向 api/user/personal-profile/0
发送请求以获取请求发件人资料。
- 在FindProfile
中,profile
变量为null而不是用户信息,这意味着AuthorizationHandler
没有被触发。
如果我从 FindProfile
方法中删除 [AllowAnonymous]
属性,一切正常。
请查看我在下面附上的那两张图片以获取更多信息:
我的问题是:
我们可以使用 AllowAnonymous 方法触发 AuthorizationHandler
吗?在我的系统中,有一些 API 可供这两种用户使用。
- 如果用户是管理员,将返回一些额外的信息。
- 如果用户是普通用户,返回的信息很少。
谢谢
> Can we make AuthorizationHandler be triggered with AllowAnonymous method?
不,你不能。 [AllowAnonymous]
绕过所有授权语句。如果您有兴趣,this is the corresponding code 中的 AuthorizeFilter.OnAuthorizationAsync
实现。
if (context.Filters.Any(item => item is IAllowAnonymousFilter))
{
return;
}
考虑删除 AllowAnonymous
并添加一些自定义逻辑。例如,您可以创建自己的 MVC 过滤器。比方说:
public class MyAllowAnonymous : ActionFilterAttribute {}
然后在AuthorizationHandler
检查authorizationFilterContext.Filters
集合是否有这个过滤器。如果是,returns context.Succeed(requirement);
。
考虑用另一个
IAuthorizationRequirement
. 创建一个单独的 您可以直接通过
authorizationFilterContext.ActionDescriptor
获取路由名称而不是过滤器检查,并决定是否允许匿名访问。但是你的 AuthorizationHandler 应该知道路由列表。
AuthorizationHandler
实现