[英]Calling specific user sid using SignalR + Azure Mobile App authentication
我正在使用以下命令檢索 WebApi 控制器中的 sid
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;
}
我得到一個非空值。 但是,當我嘗試使用
hubContext.Clients.User(sid).refresh()
預期的客戶端沒有響應。 實際上沒有客戶回應。 那說
hubContext.Clients.All.refresh()
確實打電話給每個人。 我沒有做過類似的事情
var idProvider = new PrincipalUserIdProvider();
GlobalHost.DependencyResolver.Register (typeof(IUserIdProvider), () => idProvider);
但我認為這應該是默認的吧? 我錯過了什么? 也許有某種方法可以檢查客戶端中的 userIds 是什么?
更新。 我發現這個Context.User.Identity.Name is null with SignalR 2.XX 如何解決? 其中談到在 webapi 之前使用信號器,我試圖無濟於事。 不過,我正在使用 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-zumo-auth]
更新 3.我在 Hub 中添加了更多功能
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
不確定這是否有幫助,但來自 WebApi 的 sid 看起來像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 提出了非常煩人但又精明的“為什么它不是空的:微笑:”。 一旦我最終接受了 Context.User.Identity.Name 將始終為空,我就能夠使用集線器來檢索 sid
var identity = (ClaimsIdentity)Context.User.Identity;
var tmp = identity.FindFirst(ClaimTypes.NameIdentifier);
return tmp.Value;
這讓我查看了 User.Identity.Name 的信號器代碼,最終登陸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()。 希望這可以幫助那里的人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.