Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Asp.net核心中将数据从AuthorizationHandler传递到控制器_C#_Asp.net Core_Asp.net Core Mvc_Asp.net Core 2.0 - Fatal编程技术网

C# 如何在Asp.net核心中将数据从AuthorizationHandler传递到控制器

C# 如何在Asp.net核心中将数据从AuthorizationHandler传递到控制器,c#,asp.net-core,asp.net-core-mvc,asp.net-core-2.0,C#,Asp.net Core,Asp.net Core Mvc,Asp.net Core 2.0,我为用户登录使用了特定的授权策略,因此创建了自定义授权处理程序。我想显示一条特定的警报消息,如果他们没有通过策略。我阅读了,发现我可以通过casting AuthorizationHandlerContext访问AuthorizationFilterContext。我试图将消息添加到HttpContext.Items属性并在控制器中访问它,但当我使用TryGetValue方法检查它时,它返回false if (context.HasFailed && context.Resour

我为用户登录使用了特定的授权策略,因此创建了自定义授权处理程序。我想显示一条特定的警报消息,如果他们没有通过策略。我阅读了,发现我可以通过casting AuthorizationHandlerContext访问AuthorizationFilterContext。我试图将消息添加到HttpContext.Items属性并在控制器中访问它,但当我使用TryGetValue方法检查它时,它返回false

if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
{
 mvcContext.HttpContext.Items["message"] = "alert message";
}
这是我在控制器操作中使用的代码,授权失败时将执行该代码

public IActionResult Login()
        {
            bool t = HttpContext.Items.TryGetValue("message", out Object e);
            //t is false
            TempData["message"] = e as string;
            return View();
        }
这是我注册所有认证服务的启动类

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                    .AddCookie(options =>
                    {
                        options.AccessDeniedPath = "/Account/Login";
                        options.LoginPath = "/Account/Login";
                    });
            services.AddAuthorization(options =>
            {
                options.AddPolicy("CustomRequirement", policy => policy.Requirements.Add(new CustomRequirement()));
            });
我有什么办法可以解决这个问题吗


添加了完整的处理程序

public class CustomRequirementHandler : AuthorizationHandler<CustomRequirement>
    {

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
        {
            Dictionary<string, string> claims = context.User.Claims.ToDictionary(p => p.Type, p => p.Value);
            if (claims.TryGetValue("SessionId", out string sessionId) && claims.TryGetValue("UserId", out string userName) )
            {
                bool qq = ;//we check session id and user id that is stored in our database, true if valid.
                if (qq)
                {
                    context.Succeed(requirement);
                }
                else
                {
                    context.Fail();
                }
            }
            else
            {
                context.Fail();
            }

            if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)


   {
            var tempData = _tempDictionaryFactory.GetTempData(mvcContext.HttpContext);
            tempData["message"] = "alert message";
        }

        return Task.CompletedTask;
    }
}

更新-以下是带有自定义授权处理程序的新空项目的日志记录器日志

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:50236/
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[12]
      AuthenticationScheme: Cookies was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action WebApplication1.HomeController.Index (WebApplication1) in 6217.0905ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 6389.8033ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:50236/Account/Login?ReturnUrl=%2F
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method WebApplication1.Controllers.AccountController.Login (WebApplication1) with arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.Formatters.Json.Internal.JsonResultExecutor[1]
      Executing JsonResult, writing value .
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action WebApplication1.Controllers.AccountController.Login (WebApplication1) in 3723.1458ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 3741.0345ms 200 application/json; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:50236/favicon.ico
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 4.1151ms 404 text/plain

使用TempData显示您的消息

您需要
ITempDataDictionaryFactory
IHttpContextAccessor
或可从
mvcContext.HttpContext

if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
{
    var tempData = _tempDataDictionaryFactory.GetTempData(mvcContext.HttpContext);
    tempData["message"] = "alert message";
}
然后您可以通过TempData在登录方法中获得它

public IActionResult Login()
{
    string message = null;
    var item = TempData.FirstOrDefault(x =>x.Key == key);

    if (item.Value != null)
    {
        message = (string)item.Value;
    }

     return View();
}
为什么您的代码不起作用:

HttpContext
创建每个请求意味着插入
mvcContext.HttpContext.Items[“message”]=“alert message”
只能用于当前请求,当您在controller或his方法中使用授权时,它将向当前请求插入您的消息,并重定向到您的AccessDeniedPath或LoginPath,并且将为此请求创建新的
HttpContext
,而无需您的消息。要在请求之间共享一些信息,可以使用TempData或其他方法

更新在此处尝试从访问器获取httpContext完整代码

添加到启动
services.AddSingleton()

公共类CustomRequirementHandler:AuthorizationHandler
{
专用只读IHttpContextAccessor\u httpContext;
私有只读项PDataDictionaryFactory\u tempDataDictionaryFactory;
公共CustomRequirementHandler(IHttpContextAccessor httpContext、ITempDataDictionaryFactory tempDataDictionary)
{
_httpContext=httpContext;
_tempDataDictionaryFactory=tempDataDictionary;
}
受保护的覆盖任务HandleRequirementAsync(授权HandlerContext上下文,CustomRequirement)
{
///////
//你的逻辑
///////
if(context.hasfiled)
{
var tempData=_tempDataDictionaryFactory.GetTempData(_httpContext.httpContext);
tempData[“消息”]=“警报消息”;
}
返回Task.CompletedTask;
}
}
当context.Fail()时更新;已通过tempData provider执行tempData,但您可以调用tempData provider执行手动保存

例如:

public class CustomRequirementHandler : AuthorizationHandler<CustomRequirement>
{
    private readonly ITempDataProvider _tempDataProvider;

    public CustomRequirementHandler(ITempDataProvider tempDataProvider)
    {
        _tempDataProvider = tempDataProvider;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
    {
        ///////
        //Your logic
        ///////
        context.Fail();


        if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
        {
            _tempDataProvider.SaveTempData(mvcContext.HttpContext, new Dictionary<string, object>() {  { "message","alertmessage "+DateTime.Now } });
        }

        return Task.CompletedTask;
    }
}
公共类CustomRequirementHandler:AuthorizationHandler
{
私有只读ITempDataProvider _tempDataProvider;
公共CustomRequirementHandler(ITempDataProvider tempDataProvider)
{
_tempDataProvider=tempDataProvider;
}
受保护的覆盖任务HandleRequirementAsync(授权HandlerContext上下文,CustomRequirement)
{
///////
//你的逻辑
///////
context.Fail();
if(context.hasfiled&&context.Resource为AuthorizationFilterContext mvcContext)
{
_SaveTempData(mvcContext.HttpContext,new Dictionary(){{{“message”,“alertmessage”+DateTime.Now}});
}
返回Task.CompletedTask;
}
}

在asp.net core中,对于API控制器,请注意我使用的是
\u httpContext。项目
,例如:

\u httpContext.Items[“Token”]=Token
,您可以在其中存储所需的任何对象

在控制器中,只需执行以下操作:

返回HttpContext.Items[“Token”]
作为CustomToken

public class HasConstituentIdHandler : AuthorizationHandler<HasConstituentIdRequirement>
{
    private readonly OpenIddictTokenManager<CustomToken> _tokenManager;
    private readonly HttpContext _httpContext;

    public HasConstituentIdHandler(OpenIddictTokenManager<CustomToken> tokenManager, IHttpContextAccessor httpContextAccessor)
    {
        _tokenManager = tokenManager;
        _httpContext = httpContextAccessor.HttpContext;
     
    }
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, HasConstituentIdRequirement requirement)
    {
        var tokenId = context.User.GetTokenId();

        if (tokenId != null)
        {
            

            var token = await _tokenManager.FindByIdAsync(tokenId);
            token.Context = new EventContext {ConstituentId = "junk"};//todo: s.f for now
            if (!string.IsNullOrWhiteSpace(token?.Context?.ConstituentId))
            {
                if (_httpContext != null) _httpContext.Items["Token"] = token;
                context.Succeed(requirement);
            }
        }
        if (_httpContext != null)
        {
            
               var response = _httpContext.Response;
            var bytes = Encoding.UTF8.GetBytes("Missing constituent information! Please log in again.");
            response.StatusCode = (int) HttpStatusCode.Unauthorized;
            response.ContentType = "application/json";
            await response.Body.WriteAsync(bytes, 0, bytes.Length);
        }
    }
}
公共类hasConstructentidHandler:AuthorizationHandler
{
私有只读OpenIddictTokenManager\u tokenManager;
私有只读HttpContext\u HttpContext;
public HasConstructentidHandler(OpenIddictTokenManager tokenManager、IHttpContextAccessor httpContextAccessor)
{
_tokenManager=tokenManager;
_httpContext=httpContextAccessor.httpContext;
}
受保护的重写异步任务HandleRequirementAsync(AuthorizationHandlerContext上下文,HasConstructentidRequest要求)
{
var tokenId=context.User.GetTokenId();
if(令牌ID!=null)
{
var token=await\u tokenManager.FindByIdAsync(tokenId);
token.Context=neweventcontext{componentid=“junk”};//todo:s.f现在
如果(!string.IsNullOrWhiteSpace(标记?.Context?.constructionId))
{
如果(_httpContext!=null)_httpContext.Items[“Token”]=Token;
成功(要求);
}
}
if(_httpContext!=null)
{
var response=\u httpContext.response;
var bytes=Encoding.UTF8.GetBytes(“缺少组成信息!请重新登录”);
response.StatusCode=(int)HttpStatusCode.Unauthorized;
response.ContentType=“application/json”;
wait response.Body.WriteAsync(字节,0,字节.长度);
}
}
}

谢谢,我应该使用哪个TempDataProvider来生成TempDataDictionaryFactory?您不需要创建它,应该使用DI来获取它。你能分享你的授权处理程序吗?@itkhomi刚刚做了,我想添加这样的构造函数会解决这个问题。@ringord,当然,现在试着让它工作起来。只需将TempDataDictionaryFactory更改为注入的TempDataDictionaryFactory即可。我刚刚尝试过,当我访问控制器(帐户/登录)时,TempData没有任何元素。我的
public class CustomRequirementHandler : AuthorizationHandler<CustomRequirement>
{
    private readonly ITempDataProvider _tempDataProvider;

    public CustomRequirementHandler(ITempDataProvider tempDataProvider)
    {
        _tempDataProvider = tempDataProvider;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)
    {
        ///////
        //Your logic
        ///////
        context.Fail();


        if (context.HasFailed && context.Resource is AuthorizationFilterContext mvcContext)
        {
            _tempDataProvider.SaveTempData(mvcContext.HttpContext, new Dictionary<string, object>() {  { "message","alertmessage "+DateTime.Now } });
        }

        return Task.CompletedTask;
    }
}
public class HasConstituentIdHandler : AuthorizationHandler<HasConstituentIdRequirement>
{
    private readonly OpenIddictTokenManager<CustomToken> _tokenManager;
    private readonly HttpContext _httpContext;

    public HasConstituentIdHandler(OpenIddictTokenManager<CustomToken> tokenManager, IHttpContextAccessor httpContextAccessor)
    {
        _tokenManager = tokenManager;
        _httpContext = httpContextAccessor.HttpContext;
     
    }
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, HasConstituentIdRequirement requirement)
    {
        var tokenId = context.User.GetTokenId();

        if (tokenId != null)
        {
            

            var token = await _tokenManager.FindByIdAsync(tokenId);
            token.Context = new EventContext {ConstituentId = "junk"};//todo: s.f for now
            if (!string.IsNullOrWhiteSpace(token?.Context?.ConstituentId))
            {
                if (_httpContext != null) _httpContext.Items["Token"] = token;
                context.Succeed(requirement);
            }
        }
        if (_httpContext != null)
        {
            
               var response = _httpContext.Response;
            var bytes = Encoding.UTF8.GetBytes("Missing constituent information! Please log in again.");
            response.StatusCode = (int) HttpStatusCode.Unauthorized;
            response.ContentType = "application/json";
            await response.Body.WriteAsync(bytes, 0, bytes.Length);
        }
    }
}