【问题标题】:How to give Owin the user identity?如何赋予 Owin 用户身份?
【发布时间】:2016-09-15 05:20:22
【问题描述】:

tl;drHttpApplication.AuthenticateRequest 事件的 Owin 等效项是什么?

背景

在 IIS 上运行 ASP.net 站点时,全局 System.Web.HttpApplication 对象会在每个请求期间引发 AuthenticateRequest 事件。

各种 http 模块(例如内置的 FormsAuthentication)可以附加到事件。事件处理程序按照它们注册的顺序被调用。设置HttpContext.Current.User 的第一个处理程序是使用的身份验证。

订阅此事件的模块的工作是将HttpContext.Current.User 设置为某个Principal

IIdentity identity = new GenericIdentity("MBurns", "ContosoAuthentcation");
IPrincipal principal = new GenericPrincipal(identity, null);

HttpContext.Current.User = principal;

一旦分配了HttpContext.Current.User,ASP.net 就知道用户已通过身份验证。 (一旦用户通过身份验证,他们就不再是匿名的)。

任何模块都可以做到

任何人都可以使用web.config 在 ASP.net 中注册自己的IHttpModule

web.config

<system.webServer>
   <modules runAllManagedModulesForAllRequests="true">
      <add name="MySuperCoolAuthenticationModule" type="ContosoAuthModule" />
   </modules>
</system.webServer>

该模块很容易编写。您实现了IHttpModule 接口的唯一Init 方法。对我们来说,我们将自己添加为 AuthenticateRequest 事件处理程序:

public class ContosoAuthModule : IHttpModule
{
   public void Init(HttpApplication httpApplication)
   {
      // Register event handlers
      httpApplication.AuthenticateRequest += OnApplicationAuthenticateRequest;
   }
}

然后您可以执行身份验证用户所需的操作,如果他们是有效用户,请设置HttpContext.Current.User

private void OnApplicationAuthenticateRequest(object sender, EventArgs e)
{
   var request = HttpContext.Current.Request;
   String username = SomeStuffToFigureOutWhoIsMakingTheRequest(request);

   if (String.IsNullOrWhiteSpace(username))
   {
      //I don't know who they are :(
      return;
   }

   //I know who they are, they are [username]!
   IIdentity identity = new GenericIdentity(username, "ContosoSuperDuperAuthentication");
   HttpContext.Current.User = new GenericPrincipal(identity, null);
}

这就是 HttpApplication

MSDN 记录了 HttpApplication 引发的各种事件,以及按什么顺序:

ASP.NET Application Life Cycle Overview for IIS 7.0 (archive.is)

  1. 验证请求,它检查浏览器发送的信息并确定它是否包含潜在的恶意标记。有关详细信息,请参阅ValidateRequestaScript Exploits Overviewa
  2. 如果在 Web.config 文件的 UrlMappingsSectiona 部分中配置了任何 URL,则执行 URL 映射。
  3. 引发BeginRequest 事件。
  4. 引发AuthenticateRequesta 事件。
  5. 引发PostAuthenticateRequest 事件。
  6. 引发AuthorizeRequest 事件。
  7. 引发PostAuthorizeRequest 事件。
  8. 引发ResolveRequestCache 事件。

当它是 ASP.net 和 HttpApplication 时,这一切都很棒。一切都很好理解,很容易解释(在上面的半屏中),并且有效。

但是 HttpApplication 已经过时了。

欧文是新的热点

现在一切都应该是 Owin。 HttpApplication 位于System.Web。人们希望与System.Web 隔离。他们希望这个名为 Owin 事物 现在负责。

为了进一步实现这一目标,他们(即任何新的 ASP.net MCV、网络表单或 SignalR 网站)完全禁用了 ASP.net 的身份验证系统:

<system.web> 
   <authentication mode="None" />
</system.web> 

所以没有更多的 HttpApplication.AuthenticateRequest 事件。 :(

什么是 Owin 等价物?

HttpApplication.AuthenticateRequest 的 Owin 等价物是什么?

可以肯定地说,无论从哪里调用我的代码,我的工作仍然是将HttpContext.Current.User 设置为一个身份。

可以肯定地说,无论我的代码在哪里调用表单,我的工作仍然是将HttpContext.Current.User 设置为一个身份吗?

HttpApplication.AuthenticateRequest 的 Owin 等价物是什么?

尝试无效

它没有被调用过:

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
using System.Web;
using System.IO;
using Microsoft.Owin.Extensions;
using System.Security.Claims;
using System.Security.Principal;

[assembly: OwinStartup("AnyStringAsLongAsItsNotBlank", typeof(BasicAuthOwin))]
public class BasicAuthOwin
{
    public void Configuration(IAppBuilder app)
    {
        app.Use((context, next) =>
        {
            System.Diagnostics.Trace.WriteLine("They did their best, shoddily-iddly-iddly-diddly");
            OnAuthenticateRequest(context);
            return next.Invoke();
        });
        app.UseStageMarker(PipelineStage.Authenticate);

        app.Run(context =>
            {
                return context.Response.WriteAsync("Hello world");
            });
    }

    private void OnAuthenticateRequest(IOwinContext context)
    {
        var request = context.Request;
        String username = SomeStuffToFigureOutWhoIsMakingTheRequest(request);

        if (String.IsNullOrWhiteSpace(username))
        {
            //I don't know who they are :(
            return;
        }

        //I know who they are, they are [username]!
        IIdentity identity = new GenericIdentity(username, "ContosoSuperDuperOwinAuthentication");
        context.Authentication.User = new ClaimsPrincipal(identity);
    }

    private string SomeStuffToFigureOutWhoIsMakingTheRequest(IOwinRequest request)
    {
        //if ((System.Diagnostics.Stopwatch.GetTimestamp % 3) == 0)
        //  return "";

        return "MBurns";
    }
}

【问题讨论】:

  • 你解决过这个问题吗?我对同样的事情很感兴趣。
  • @deezg 我从来没有这样做过。这没什么大不了的,因为我们都知道 IIS 和 System.Web 不会去任何地方。我刚刚注释掉了 web.config 中的 authentication mode="None" 设置(并温柔地拍了拍 Owin “这很好,亲爱的” 拍了拍头)
  • :) 感谢您的回复。我现在做的差不多。
  • 你最近试过吗?这个应用程序似乎对我有用:pastebin.com/mP4ZSxGQ 在浏览器上显示“Hello world MBurns”(我将 WriteAsync 输出更改为使用 HttpContext.Current.User.Identity.Name)。

标签: asp.net iis owin


【解决方案1】:

查看此网站Jwt Authentication in ASP.NET WEB API AND MVC 的博客文章。它解释了如何使用 OWIN 解决“此请求的授权已被拒绝”的问题。

JWTHandler 类

public static void OnAuthenticateRequest(IOwinContext context)
        {
            var requestHeader = context.Request.Headers.Get("Authorization");
            int userId = Convert.ToInt32(JwtDecoder.GetUserIdFromToken(requestHeader).ToString());
            var identity = new GenericIdentity(userId.ToString(), "StakersClubOwinAuthentication");
            //context.Authentication.User = new ClaimsPrincipal(identity);

            var token = requestHeader.StartsWith("Bearer ") ? requestHeader.Substring(7) : requestHeader;
            var secret = WebConfigurationManager.AppSettings.Get("jwtKey");
            Thread.CurrentPrincipal = ValidateToken(
                token,
                secret,
                true
                );
            context.Authentication.User = (ClaimsPrincipal) Thread.CurrentPrincipal;
            //if (HttpContext.Current != null)
            //{
            //    HttpContext.Current.User = Thread.CurrentPrincipal;
            //}
        }

启动类

public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var config = new HttpConfiguration();

            app.Use((context, next) =>
            {
                JwtAuthHandler.OnAuthenticateRequest(context); //the new method
                return next.Invoke();
            });
            app.UseStageMarker(PipelineStage.Authenticate);            
            WebApiConfig.Register(config);//Remove or comment the config.MessageHandlers.Add(new JwtAuthHandler()) section it would not be triggered on execution.


            app.UseWebApi(config);
        }



    }

【讨论】:

    猜你喜欢
    • 2016-11-17
    • 2017-06-11
    • 2017-03-06
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多