我有一个托管在Web角色(IIS 8.5)中的Asp.Net Web API项目,我按照this post的步骤使用Azure Scheduler向我的应用程序发送请求是时候做点工作了。
问题是正在加载负责验证调度程序请求的HttpModule,但是当请求到达ApiController时,其结果将被忽略。
我使用POSTMAN测试REST端点,这是我在调试时在http模块中看到的内容:
响应信息是:
此请求已拒绝授权
如果我从控制器中删除了Authorize属性,这就是我在请求命中时看到的内容:
Startup.Auth.cs的相关部分:
app.UseCookieAuthentication(cookieOptions);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOAuthBearerTokens(OAuthBearerOptions);
app.UseLinkedInAuthentication("777777", "8888888");
使用Asp.Net Identity和Owin时是否可以使用HttpModule对请求进行身份验证,或者我必须实现Owin AuthenticationMiddleware模块才能实现此目的?
答案 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")