调用使用SignalR + Azure的移动应用认证
private string GetAzureSID()
{
var principal = this.User as ClaimsPrincipal;
var nameIdentifier = principal.FindFirst(ClaimTypes.NameIdentifier);
if (nameIdentifier != null)
{
var sid = nameIdentifier.Value;
return sid;
}
return null;
}
检索SID在我的WebAPI控制器和我得到一个非空值特定用户的SID。但是,当我尝试呼叫使用的特定集线器客户端
hubContext.Clients.User(sid).refresh()
预期的客户端不响应。其实没有客户回应。这就是说
hubContext.Clients.All.refresh()
确实叫大家。我没有做过任何类似的事情
var idProvider = new PrincipalUserIdProvider();
GlobalHost.DependencyResolver.Register (typeof(IUserIdProvider),() => idProvider);
但我认为应该是默认的权利?我错过了什么?也许有一些方法可以检查客户端中的用户ID?
更新。我发现这个Context.User.Identity.Name is null with SignalR 2.X.X. How to fix it?它讨论了之前webapi有signalr,我试图无济于事。尽管我使用Azure身份验证,但这可能是问题所在。这里是我的ConfigureMobileApp看起来像
public static void ConfigureMobileApp(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);
// Use Entity Framework Code First to create database tables based on your DbContext
// Database.SetInitializer(new MobileServiceInitializer());
var migrator = new DbMigrator(new Migrations.Configuration());
migrator.Update();
MobileAppSettingsDictionary settings = config.GetMobileAppSettingsProvider().GetMobileAppSettings();
if (string.IsNullOrEmpty(settings.HostName))
{
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
{
// This middleware is intended to be used locally for debugging. By default, HostName will
// only have a value when running in an App Service application.
SigningKey = ConfigurationManager.AppSettings["SigningKey"],
ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
TokenHandler = config.GetAppServiceTokenHandler()
});
}
app.MapSignalR();
app.UseWebApi(config);
}
这可能是因为该问题是认证后不知何故从Azure中来吗?我试图从我的客户
[Authorize]
public class AppHub : Hub
{
public string Identify()
{
return Context.User.Identity.Name;
}
}
调用集线器但结果却是“空”,所以我觉得Signalr无法获得正确的用户。
更新2可能是我需要创建一个UseOAuthBearerAuthentication读取[X-谟-AUTH]
更新3我增加了一些更多的功能到我中心
public string Identify()
{
return HttpContext.Current.User.Identity.Name;
}
public bool Authenticated()
{
return Context.User.Identity.IsAuthenticated;
}
public string Bearer()
{
return Context.Headers["x-zumo-auth"];
}
结果是
null
true
the correct bearer token
不知道这是否有帮助,但从我们的sid bApi看起来像sid:8ba1a8532eaa6eda6758c3e522f77c24
更新4.我找到了sid!我将我的中心代码更改为
public string Identify()
{
// return HttpContext.Current.User.Identity.Name;
var identity = (ClaimsIdentity)Context.User.Identity;
var tmp = identity.FindFirst(ClaimTypes.NameIdentifier);
return tmp.Value;
}
我得到了sid。不确定Context.User.Identity.Name如何与此不同,但这确实起作用。现在的问题是,我该如何使用给定的SID调用
hubContext.Clients.User(...???...).refresh()
,如果我知道用户的的NameIdentifier?
特别感谢@davidfowler,因为它非常令人讨厌而又敏感的“为什么它不会为null:smile:”。一旦我最终接受了Context.User.Identity。名称将永远是空的,我能得到集线器使用检索SID
var identity = (ClaimsIdentity)Context.User.Identity;
var tmp = identity.FindFirst(ClaimTypes.NameIdentifier);
return tmp.Value;
害得我通过了User.Identity.Name的signalr代码,最终降落在PrincipalUserIdProvider看。惊喜,惊喜,它基于User.Identity.Name分配GetUserId。我创建了一个新的IUserIdProvider:
public class ZumoUserIdProvider : IUserIdProvider
{
public string GetUserId(IRequest request)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
if (request.User != null && request.User.Identity != null)
{
var identity = (ClaimsIdentity)request.User.Identity;
var identifier = identity.FindFirst(ClaimTypes.NameIdentifier);
if (identifier != null)
{
return identifier.Value;
}
}
return null;
}
}
和Startup.cs
public void Configuration(IAppBuilder app)
{
var userIdProvider = new ZumoUserIdProvider();
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider),() => userIdProvider);
ConfigureMobileApp(app);
}
和像变魔术一样,我现在可以hubContext.Clients.User(SID).REFRESH()任何事情之前注册它。希望这可以帮助那里的人。