OpenIdDict 3.0 跳过了 AllowAnonymous
AllowAnonymous skipped over with OpenIdDict 3.0
我正在使用 OpenIdDict 3.0,它运行良好,但是我有一个使用 AllowAnonymous 属性的控制器,但我仍然收到 "The request was rejected because the access token was missing"。我假设它可能与我的 Startup 中的顺序有关,这使得它不会在管道中受到影响,但我不确定。这是我的创业公司 class:
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseMvcWithDefaultRoute();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
}).AddNewtonsoftJson();
services.AddAutoMapper(typeof(Startup));
services.AddDbContext<MyDbContext>(options =>
{
options.UseSqlServer(WebConfig.ConnectionString, x => x.MigrationsAssembly("X.Api.DataAccess"));
options.UseLazyLoadingProxies();
options.UseOpenIddict();
});
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireLowercase = true;
})
.AddEntityFrameworkStores<MyDbContext>()
.AddUserStore<ApplicationUserStore>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
});
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<MyDbContext>();
})
.AddServer(options =>
{
options.SetAuthorizationEndpointUris("/connect/authorize")
.SetLogoutEndpointUris("/connect/logout")
.SetTokenEndpointUris("/connect/token");
options.AllowAuthorizationCodeFlow()
.AllowRefreshTokenFlow();
scopes.
options.RegisterScopes(Scopes.Email, Scopes.OpenId, Scopes.OfflineAccess);
// Register the signing and encryption credentials.
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.UseAspNetCore()
.EnableTokenEndpointPassthrough();
})
.AddValidation(options =>
{
// Import the configuration from the local OpenIddict server instance.
options.UseLocalServer();
// Register the ASP.NET Core host.
options.UseAspNetCore();
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});
}
如有任何帮助,我们将不胜感激!
您看到的行为实际上是 "normal":当您设置 DefaultAuthenticateScheme
时,身份验证中间件(又名 app.UseAuthentication()
)- 通常在 ASP.NET 核心管道 - 自动调用相应的身份验证处理程序来填充 HttpContext.User
.
无论您的 MVC 操作是用 [Authorize]
还是 [AllowAnonymous]
修饰,这种机制总是独立发生。如果 OpenIddict 在 Authorization
header 中找不到访问令牌,它会记录一个错误并告诉身份验证堆栈它无法提供它请求的 AuthenticateResult
。
如果您的 MVC 操作用 [Authorize]
装饰,身份验证堆栈将要求 OpenIddict return 401 挑战(除非使用 [AllowAnonymous]
)。
也就是说,虽然它不会阻止一切正常工作,但我同意它可能是一个重要的干扰源,因此我会考虑删除此日志消息。我打开 https://github.com/openiddict/openiddict-core/issues/941 进行跟踪。
干杯。
就我而言,我想摆脱使用 [AllowAnonymous]
属性创建的数据库上下文。但它不是那样工作的。因此,我必须创建自己的 AuthenticationMiddleware
替代品,并为异常添加必要的路径。
现在一步一步来。
第一。创建中间件:
public class CustomAuthenticationMiddleware
{
private readonly RequestDelegate _nextWithoutAuth;
private readonly AuthenticationMiddleware _nextWithAuth;
private List<PathString> _withoutAuth = new List<PathString>
{
"/url/1", "/url/2"
};
public CustomAuthenticationMiddleware(RequestDelegate next,
IServiceProvider sp)
{
_nextWithoutAuth = next;
_nextWithAuth = ActivatorUtilities
.CreateInstance<AuthenticationMiddleware>(sp, next);
}
public async Task Invoke(HttpContext context)
{
var path = context.Request.Path.HasValue ?
context.Request.Path.Value : null;
var withoutAuth = context.Request.Path.HasValue
&& _withoutAuth.Any(it => path.StartsWith(it, StringComparison.OrdinalIgnoreCase));
if (withoutAuth)
{
await _nextWithoutAuth.Invoke(context);
}
else
{
await _nextWithAuth.Invoke(context);
}
}
}
第二。用所需的值填充数组 _withoutAuth
。
第三。在 Startup.cs 中将 app.UseAuthentication();
替换为 app.UseMiddleware<CustomAuthenticationMiddleware>();
。
p.s。我使用.net core 2.1
p.s.s.我假设如果使用 [AllowAnonymous]
属性获取所有控制器及其方法并将它们添加到 _withoutAuth
数组中,您可以改进我的解决方案。
我正在使用 OpenIdDict 3.0,它运行良好,但是我有一个使用 AllowAnonymous 属性的控制器,但我仍然收到 "The request was rejected because the access token was missing"。我假设它可能与我的 Startup 中的顺序有关,这使得它不会在管道中受到影响,但我不确定。这是我的创业公司 class:
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseMvcWithDefaultRoute();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
}).AddNewtonsoftJson();
services.AddAutoMapper(typeof(Startup));
services.AddDbContext<MyDbContext>(options =>
{
options.UseSqlServer(WebConfig.ConnectionString, x => x.MigrationsAssembly("X.Api.DataAccess"));
options.UseLazyLoadingProxies();
options.UseOpenIddict();
});
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireLowercase = true;
})
.AddEntityFrameworkStores<MyDbContext>()
.AddUserStore<ApplicationUserStore>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
});
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<MyDbContext>();
})
.AddServer(options =>
{
options.SetAuthorizationEndpointUris("/connect/authorize")
.SetLogoutEndpointUris("/connect/logout")
.SetTokenEndpointUris("/connect/token");
options.AllowAuthorizationCodeFlow()
.AllowRefreshTokenFlow();
scopes.
options.RegisterScopes(Scopes.Email, Scopes.OpenId, Scopes.OfflineAccess);
// Register the signing and encryption credentials.
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.UseAspNetCore()
.EnableTokenEndpointPassthrough();
})
.AddValidation(options =>
{
// Import the configuration from the local OpenIddict server instance.
options.UseLocalServer();
// Register the ASP.NET Core host.
options.UseAspNetCore();
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme;
});
}
如有任何帮助,我们将不胜感激!
您看到的行为实际上是 "normal":当您设置 DefaultAuthenticateScheme
时,身份验证中间件(又名 app.UseAuthentication()
)- 通常在 ASP.NET 核心管道 - 自动调用相应的身份验证处理程序来填充 HttpContext.User
.
无论您的 MVC 操作是用 [Authorize]
还是 [AllowAnonymous]
修饰,这种机制总是独立发生。如果 OpenIddict 在 Authorization
header 中找不到访问令牌,它会记录一个错误并告诉身份验证堆栈它无法提供它请求的 AuthenticateResult
。
如果您的 MVC 操作用 [Authorize]
装饰,身份验证堆栈将要求 OpenIddict return 401 挑战(除非使用 [AllowAnonymous]
)。
也就是说,虽然它不会阻止一切正常工作,但我同意它可能是一个重要的干扰源,因此我会考虑删除此日志消息。我打开 https://github.com/openiddict/openiddict-core/issues/941 进行跟踪。
干杯。
就我而言,我想摆脱使用 [AllowAnonymous]
属性创建的数据库上下文。但它不是那样工作的。因此,我必须创建自己的 AuthenticationMiddleware
替代品,并为异常添加必要的路径。
现在一步一步来。
第一。创建中间件:
public class CustomAuthenticationMiddleware
{
private readonly RequestDelegate _nextWithoutAuth;
private readonly AuthenticationMiddleware _nextWithAuth;
private List<PathString> _withoutAuth = new List<PathString>
{
"/url/1", "/url/2"
};
public CustomAuthenticationMiddleware(RequestDelegate next,
IServiceProvider sp)
{
_nextWithoutAuth = next;
_nextWithAuth = ActivatorUtilities
.CreateInstance<AuthenticationMiddleware>(sp, next);
}
public async Task Invoke(HttpContext context)
{
var path = context.Request.Path.HasValue ?
context.Request.Path.Value : null;
var withoutAuth = context.Request.Path.HasValue
&& _withoutAuth.Any(it => path.StartsWith(it, StringComparison.OrdinalIgnoreCase));
if (withoutAuth)
{
await _nextWithoutAuth.Invoke(context);
}
else
{
await _nextWithAuth.Invoke(context);
}
}
}
第二。用所需的值填充数组 _withoutAuth
。
第三。在 Startup.cs 中将 app.UseAuthentication();
替换为 app.UseMiddleware<CustomAuthenticationMiddleware>();
。
p.s。我使用.net core 2.1
p.s.s.我假设如果使用 [AllowAnonymous]
属性获取所有控制器及其方法并将它们添加到 _withoutAuth
数组中,您可以改进我的解决方案。