Your requirement may be necessary in some cases where the user is required to be authenticated BUT not actually referenced in the code (e.g: the code does not access any info on the current identity, especially related to the business model of the user).
So I assume that you are aware of that because the following will just simply remove the requirement to check for authenticated user when the code runs in the development environment. There is another way to auto sign-in a dummy user which can be better in some scenarios.
Here is the first solution, it configures a default policy only which does not include the DenyAnonymousAuthorizationRequirement
(which is the only requirement contained in the default policy). That means if you have multiple policies used somewhere (with AuthorizeAttribute
), only the default will be ignored (while debugging). The second solution (shown later) may suit that scenario better.
//inject IHostingEnvironment in the Startup constructor
public Startup(IConfiguration configuration, IHostingEnvironment env){
HostingEnvironment = env;
}
public IHostingEnvironment HostingEnvironment { get; }
//in the ConfigureServices method in Startup.cs
services.AddAuthorization(o => {
if (HostingEnvironment.IsDevelopment()){
o.DefaultPolicy = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme)
//there should be at least 1 requirement
//here we add a simple always-passed assertion
.RequireAssertion(e => true).Build();
}
//...
});
We need to use IHostingEnvironment
(in .net core 2.2, since 3.0 we have 2 alternatives IWebHostEnvironment
and IHostEnvironment
) so we inject it in the Startup
constructor and store it in a readonly property (as you see above). There is another way is try to get the ASPNETCORE_ENVIRONMENT
variable directly like this:
var isDevelopment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development";
Here is the second solution in which you use a custom global IAsyncAuthorizationFilter
to auto sign-in a dummy user (so it's always authenticated for all requests).
public class AllowAnonymousFilterAttribute : Attribute, IAsyncAuthorizationFilter
{
readonly IHostingEnvironment _hostingEnvironment;
public AllowAnonymousFilterAttribute(IHostingEnvironment env){
_hostingEnvironment = env;
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (_hostingEnvironment.IsDevelopment() && !context.HttpContext.User.Identity.IsAuthenticated)
{
//prepare a dummy user to auto sign-in
HttpContext.User = new ClaimsPrincipal(new[] {
new ClaimsIdentity(new []{ new Claim(ClaimTypes.NameIdentifier,"admin")},
CookieAuthenticationDefaults.AuthenticationScheme)
});
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,
HttpContext.User);
}
}
}
Register the filter globally, here I write code for .net core 2.2
:
services.AddMvc(o => {
//register the filter only for development (should be debugging)
if (HostingEnvironment.IsDevelopment()){
o.Filters.Add<AllowAnonymousFilterAttribute>();
}
//...
});
I'm sure there are still some other solutions but what I've introduced here are fairly simple and good enough for your purpose.
P/S: the first solution I've introduced above suits for .net core 2.2 (actually currently I do not have access to newer versions of .net core, it's a pity). For the newer versions, the Authorization
middleware is separate so you may just simply not call .UseAuthorization()
middleware in the Configure
method (of course for development environment only) as one other answer suggests.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…