我在Windows服务中有一个自托管的信号器服务器(hub)。具有身份验证的用户或具有JWT令牌的客户端只能访问此中心。 这是我的启动和程序类的设置
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.SetIsOriginAllowed((host) => true));
});
services.AddOptions();
services.AddDbContextPool<MusterEFContext>
(options =>
options.UseLazyLoadingProxies().UseSqlServer(Configuration["Database:Connection"])
);
//Code for transient services, etc.
var jwtConfig = new JwtAuthentication();
Configuration.GetSection("JwtAuthentication").Bind(jwtConfig);
services.AddIdentity<MusterUser, IdentityRole>(options =>
{
options.Password.RequiredLength = 8;
options.User.RequireUniqueEmail = true;
options.Password.RequireDigit = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
})
.AddEntityFrameworkStores<MusterEFContext>()
.AddSignInManager<SignInManager<MusterUser>>()
.AddUserManager<UserManager<MusterUser>>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddDefaultTokenProviders();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.IncludeErrorDetails = true;
options.ClaimsIssuer = jwtConfig.ValidIssuer;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtConfig.ValidIssuer,
ValidAudience = jwtConfig.ValidAudience,
RoleClaimType = ClaimTypes.Role,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.SecurityKey))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/realtime")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("TenantPolicy", policy => policy.RequireRole("Tenant"));
options.AddPolicy("HostPolicy", policy => policy.RequireRole("Host"));
options.AddPolicy("AdminPolicy", policy => policy.RequireRole("Admin"));
options.AddPolicy("DashboardPolicy", policy => policy.RequireAssertion(x => (
x.User.IsInRole("Host") || x.User.IsInRole("Tenant")
)));
});
services.AddHangfire(x => x.UseSqlServerStorage(Configuration["Database:Hangfire"]));
services.AddHangfireServer();
services.AddSignalR();
}
这是启动类的其余部分
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseHangfireDashboard();
app.UseSignalR(config =>
{
config.MapHub<Muster.Core.Hubs.ChatHub>("/realtime");
});
}
我面临的挑战是在我的登台服务器上部署并安装此服务时
我试图从上下文中获取当前用户声明的这一行始终返回null
public override async Task OnConnectedAsync()
{
try
{
string userId = (Context.User.Identity as ClaimsIdentity).FindFirst(ClaimTypes.Name).Value; //This line always breaks because Context.User is null or empty i.e no claims.
Logger.LogInformation($"User Id : {userId}");
if (userId != null)
{
string connectionId = Context.ConnectionId;
var user = _userManager.FindByIdAsync(userId);
if (user.Result != null)
{
await _messageService.AddConnection(connectionId, userId, Context.GetHttpContext().Request.Headers["User-Agent"]);
}
await base.OnConnectedAsync();
}
else
{
Logger.LogWarning("Could not get user id for specified claim");
throw new Exception("User Id is Null");
}
// await base.OnConnectedAsync();
}
catch (Exception ex)
{
Logger.LogError("An error occured while connecting to this hub");
Logger.LogError(ex.Message);
Logger.LogError(ex.StackTrace);
Logger.LogError(ex.TargetSite.ToString());
throw;
}
}```
由于某种原因,当我在登台服务器上尝试连接到集线器的用户或客户端无法获得任何主张时,但这在我的计算机上非常有效。 这是我的Signalr Javascript客户端的摘录
this.connection = new signalR.HubConnectionBuilder()
.withUrl(config.SignalRUrl, { accessTokenFactory: () => { return auth.token(); } })
.configureLogging(signalR.LogLevel.Trace)
.build();