簡體   English   中英

使用 SignalR + Azure 移動應用程序身份驗證調用特定用戶 sid

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM