如何给Owin提供用户身份?

时间:2016-05-18 15:45:07

标签: asp.net iis owin

tl; dr :Owin等同于 HttpApplication.AuthenticateRequest 事件?

背景

在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>

该模块很容易编写。您实现Init接口的单独IHttpModule方法。对于我们,我们将自己添加为 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. 验证请求,该请求检查浏览器发送的信息并确定其是否包含潜在的恶意标记。有关详情,请参阅ValidateRequest a Script Exploits Overview a
  2.   
  3. 如果在Web.config文件的UrlMappingsSection a 部分中配置了任何URL,则执行URL映射。
  4.   
  5. 举起BeginRequest活动。
  6.   
  7. 提升AuthenticateRequest a 事件。
  8.   
  9. 举起PostAuthenticateRequest活动。
  10.   
  11. 举起AuthorizeRequest活动。
  12.   
  13. 举起PostAuthorizeRequest活动。
  14.   
  15. 举起ResolveRequestCache活动。
  16.   

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

但是 HttpApplication 已经过时了。

Owin是新的热点

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

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

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

所以不再有 HttpApplication.AuthenticateRequest 事件。 :(

Owin的等价物是什么?

Owin等同于 HttpApplication.AuthenticateRequest

可以肯定地说,无论我的代码在何处被调用,我的工作仍然是将HttpContext.Current.User设置为身份。

可以肯定地说,无论我的代码在哪里被称为表单,我的工作仍然是将HttpContext.Current.User设置为标识吗?

Owin等同于 HttpApplication.AuthenticateRequest

尝试不起作用

没有任何东西被称为:

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";
    }
}

1 个答案:

答案 0 :(得分:0)

查看此网站Jwt Authentication in ASP.NET WEB API AND MVC的博客文章。它解释了如何解决问题&#34;授权已被拒绝此请求&#34;使用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);
        }



    }