我正在尝试为 Serilog 提供一个 ActiveUser
属性。
不幸的是,我似乎无法找到正确的位置来检查当前用户。
在下面的代码中,httpContext.User.Identity.IsAuthenticated
总是false?
但仅当使用不记名 token 登录时
- 只要用户是,不记名 token 登录就可以正常工作 通过 Controller 方法的身份验证,用户需要属于 到正确的角色,以便进行身份验证。尽管用户名设置不正确 - 存在声明,并且 IsAuthenticated 设置为 true。
- 如果我使用 cookie 登录,用户设置正确,声明设置正确,Serilog 工作正常。无论是使用不记名 token 还是 cookie 来调用都是如此。一旦用户使用 cookie 登录,它就始终有效。
当不记名 token 被验证时,用户是不是立即设置?
项目是aspnetcore 2.0
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
... (other configuration items)
app.UseIdentityServer();
app.UseAuthentication();
app.Use(async (httpContext, next) =>
{
// HERE IsAuthenticated IS ALWAYS FALSE
// HERE THE CLAIMS ARE ALWAYS EMPTY, UNLESS
// I LOGIN USING THE COOKIE AS WELL - THEN IT WORKS
var userName = httpContext.User.Identity.IsAuthenticated
? httpContext.User.GetClaim("name")
: "(unknown)";
LogContext.PushProperty(
"ActiveUser",
!string.IsNullOrWhiteSpace(userName)
? userName
: "(unknown)");
await next.Invoke();
});
app.UseMvc(
routes =>
{
routes.MapRoute(
"default",
"{controller=Home}/{action=Index}/{id?}");
});
在我的 Controller 方法中,用户设置正确,并且经过身份验证。
[Authorize]
[HttpGet("user")]
public object UserDetail()
{
// HERE THE CLAIMS ARE SET, IsAuthenticated IS ALWAYS TRUE
// AS THE USER MUST BE AUTHENTICATED TO GET HERE
Debug.Assert(this.User.Identity.IsAuthenticated == true)
编辑
进一步深入研究这个问题,似乎在我的中间件已经执行之后验证了 JWTBearer token 。中间件需要在验证 token 后执行。
长话短说
(完整配置)
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentityServer();
app.UseAuthentication();
app.Use(async (httpContext, next) =>
{
var userName = httpContext.User.Identity.IsAuthenticated
? httpContext.User.GetClaim("email")
: "(unknown)";
LogContext.PushProperty("ActiveUser", !string.IsNullOrWhiteSpace(userName) ? userName : "(unknown)");
await next.Invoke();
});
app.UseMvc(
routes =>
{
routes.MapRoute(
"default",
"{controller=Home}/{action=Index}/{id?}");
});
}
(更多配置)
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication()
.AddOpenIdConnect(
o =>
{
o.Authority = "https://localhost:44319";
o.ClientId = "api";
o.ClientSecret = "secret";
o.RequireHttpsMetadata = false;
o.ResponseType = "code id_token token";
o.GetClaimsFromUserInfoEndpoint = true;
})
.AddJwtBearer(
o =>
{
o.Authority = "https://localhost:44319";
o.Audience = "api";
o.RequireHttpsMetadata = false;
//o.SaveToken = true;
});
services.AddMemoryCache();
services.AddIdentity<ApplicationUser, ApplicationRole>(
x =>
{
x.Password.RequireNonAlphanumeric = false;
x.Password.RequireUppercase = false;
})
.AddEntityFrameworkStores<FormWorkxContext>()
.AddDefaultTokenProviders()
.AddIdentityServer();
// NB
services.Configure<IdentityOptions>(
options =>
{
options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role;
options.ClaimsIdentity.UserNameClaimType = ClaimTypes.Name;
});
services.ConfigureApplicationCookie(
options =>
{
options.LoginPath = "/login";
options.LogoutPath = "/logout";
options.Events.OnRedirectToLogin = this.ProcessStatusCodeResponse;
});
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity<ApplicationUser>();
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc(
_ =>
{
_.Filters.Add(
new AuthorizeFilter(
new AuthorizationPolicyBuilder(
JwtBearerDefaults.AuthenticationScheme,
IdentityConstants.ApplicationScheme)
.RequireAuthenticatedUser()
.Build()));
_.Filters.Add(new ExceptionFilter());
_.ModelBinderProviders.Insert(0, new PartyModelBinderProvider());
_.ModelBinderProviders.Insert(0, new DbGeographyModelBinder());
_.ModelMetadataDetailsProviders.Add(new KeyTypeModelMetadataProvider());
})
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<Startup>())
.AddJsonOptions(json => json.SerializerSettings.Converters.Add(new DbGeographyJsonConverter()));
}
最佳答案
正在复制 my answer from your other related question万一有人遇到这个问题并想知道发生了什么:
Since you have multiple authentication schemes registered and none is the default, authentication does not happen automatically as the request goes through the pipeline. That's why the
HttpContext.User
was empty/unauthenticated when it went through your custom middleware. In this "passive" mode, the authentication scheme won't be invoked until it is requested. In your example, this happens when the request passes through yourAuthorizeFilter
. This triggers the JWT authentication handler, which validates the token, authenticates and sets the Identity, etc. That's why theUser
is populated correctly by the time it gets to your controller action.
关于c# - 用户似乎没有在 dotnet core 2.0 中的“Use”管道中进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46274422/