Asp.Net Web API - Asp.Net Identity和Owin vs HttpModule AuthenticateRequest

时间:2015-03-04 17:14:42

标签: asp.net asp.net-web-api asp.net-identity owin

我有一个托管在Web角色(IIS 8.5)中的Asp.Net Web API项目,我按照this post的步骤使用Azure Scheduler向我的应用程序发送请求是时候做点工作了。

问题是正在加载负责验证调度程序请求的HttpModule,但是当请求到达ApiController时,其结果将被忽略。

我使用POSTMAN测试REST端点,这是我在调试时在http模块中看到的内容:

Http Module

响应信息是:

  

此请求已拒绝授权

如果我从控制器中删除了Authorize属性,这就是我在请求命中时看到的内容:

SchedulerController

Startup.Auth.cs的相关部分:

        app.UseCookieAuthentication(cookieOptions);
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);  
        app.UseOAuthBearerTokens(OAuthBearerOptions);
        app.UseLinkedInAuthentication("777777", "8888888");

使用Asp.Net Identity和Owin时是否可以使用HttpModule对请求进行身份验证,或者我必须实现Owin AuthenticationMiddleware模块才能实现此目的?

1 个答案:

答案 0 :(得分:0)

好的,我已经实现了一个自定义owin身份验证中间件,只是为了发现它也不会工作。原因是我几个月前将这行添加到我的WebApi.config文件中,以避免对我的web api控制器进行无意的cookie身份验证:

        config.SuppressDefaultHostAuthentication();

这也抑制了我的新owin auth中间件。要启用它,我必须添加以下行:

        config.Filters.Add(new HostAuthenticationFilter(SchedulerAuthenticationMiddlewareConstants.DefaultAuthenticationType));

完全删除SuppressDefaultHostAuthentication()使HttpModule正常工作但在这种情况下,我的缺点是隐式启用除端点的承载令牌之外的其他身份验证机制。

HttpModule功能相应的Owin Auth中间件如下所示:

using System.Collections.Generic;
using System.IO;
using System.Security.Claims;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Owin;

namespace SchedulerAuthenticationMiddleware
{
    public static class SchedulerAuthenticationExtensions
    {
        public static IAppBuilder UseSchedulerAuthentication(this IAppBuilder app, SchedulerAuthenticationOptions options)
        {
            return app.Use(typeof(SchedulerAuthenticationMiddleware), app, options);
        }
    }

    public static class SchedulerAuthenticationMiddlewareConstants
    {
        public const string DefaultAuthenticationType = "Scheduler";
    }

    public class SchedulerAuthenticationOptions : AuthenticationOptions
    {
        public SchedulerAuthenticationOptions(string schedulerSharedSecret)
            : base(SchedulerAuthenticationMiddlewareConstants.DefaultAuthenticationType)
        {
            Description.Caption = SchedulerAuthenticationMiddlewareConstants.DefaultAuthenticationType;

            // http://brockallen.com/2013/10/27/host-authentication-and-web-api-with-owin-and-active-vs-passive-authentication-middleware/
            // Active middleware always look at every incoming request and attempt to authenticate the call and if successful 
            // they create a principal that represents the current user and assign that principal to the hosting environment. 
            // Passive middleware, on the other hand, only inspects the request when asked to. 
            AuthenticationMode = AuthenticationMode.Passive;

            SchedulerSharedSecret = schedulerSharedSecret;
        }

        public string SchedulerSharedSecret { get; set; }
    }

    // One instance is created when the application starts.
    public class SchedulerAuthenticationMiddleware : AuthenticationMiddleware<SchedulerAuthenticationOptions>
    {
        public SchedulerAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app, SchedulerAuthenticationOptions options)
            : base(next, options)
        {
        }

        // Called for each request, to create a handler for each request.
        protected override AuthenticationHandler<SchedulerAuthenticationOptions> CreateHandler()
        {
            return new SchedulerAuthenticationHandler();
        }
    }

    class SchedulerAuthenticationHandler : AuthenticationHandler<SchedulerAuthenticationOptions>
    {
        protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
        {
            AuthenticationTicket ticket = null;
            if (Context.Request.Headers.ContainsKey("x-ms-scheduler-jobid"))
            {
                using (StreamReader sr = new StreamReader(Context.Request.Body))
                {
                    string bodyContent = sr.ReadToEnd();
                    var match = new Regex(@"secret:(\d*)").Match(bodyContent);
                    if (match.Success && match.Groups[1].Value == Options.SchedulerSharedSecret)
                    {
                        ticket = CreateTicket();
                    }
                }
            }

            return Task.FromResult(ticket);
        }

        private AuthenticationTicket CreateTicket()
        {
            AuthenticationProperties properties = new AuthenticationProperties();
            ClaimsIdentity claimIdentity = CreateSchedulerIdentity();
            return new AuthenticationTicket(claimIdentity, properties);
        }

        private ClaimsIdentity CreateSchedulerIdentity()
        {
            // ASP.Net Identity requires the NameIdentifier field to be set or it won't  
            // accept the external login (AuthenticationManagerExtensions.GetExternalLoginInfo)
            Claim nameIdentifier = new Claim(ClaimTypes.NameIdentifier, "scheduler", null, Options.AuthenticationType);
            Claim nameIdClaim = new Claim(ClaimTypes.Name, "scheduler", null, Options.AuthenticationType);
            Claim schedulerRoleClaim = new Claim(ClaimTypes.Role, "scheduler");
            Claim identificatorClaim = new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "application");

            ClaimsIdentity claimIdentity = new ClaimsIdentity(new List<Claim>
                            {
                                nameIdentifier,
                                nameIdClaim,
                                schedulerRoleClaim,
                                identificatorClaim
                            }, "custom", ClaimTypes.Name, ClaimTypes.Role);
            return claimIdentity;
        }
    }
}

最后,我可以使用Authorize(Roles = "scheduler")

授权我的任何网络API操作