我无法弄清楚为什么当我尝试从Xamarin上连接Context.User.Indetity.Name为空时。我需要做些什么特别的事吗?我登录到服务器并且用户已建立连接。之后我使用以下代码:
var Connection = new HubConnection(Url);
_hub = Connection.CreateHubProxy(hubName);
_hub.On(srvEvent, onData);
await Connection.Start();
但我从来没有得到用户名。我做错了什么?
以下是服务器的代码:
var name = Context.User.Identity.Name;
Connections.Add(name, Context.ConnectionId);
return base.OnConnected();
它来自网络应用程序,而不是来自xamarin应用程序。
谢谢!
答案 0 :(得分:5)
以下是我告诉你的代码。
我正在使用外部OAuth2服务器进行身份验证,因此我必须以某种方式将访问令牌传递给SignalR,因为SignalR使用Web套接字来回传递消息我无法在头中传递访问令牌,因为这是Web套接字不支持。
我以这种方式将访问令牌作为查询字符串参数传递(Javascript客户端)
app.UseCors(CorsOptions.AllowAll);
app.UseAuthQSTokenExtractor();
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();
app.UseIdentityServerBearerTokenAuthentication(
new IdentityServerBearerTokenAuthenticationOptions
{
Authority = ConfigurationManager.AppSettings["api:idserver"],
RequiredScopes = new[]
{
"chat-hub"
}
});
var hubConfiguration = new HubConfiguration ();
hubConfiguration.EnableDetailedErrors = true;
app.RunSignalR(hubConfiguration);
然后在我的SignalR上,我添加了一个中间件,它接受该查询字符串并使用Bearer Token将其作为Authorization标头添加到标头中。这是在我的启动类
中完成的app.UseIdentityServerBearerTokenAuthentication(
new IdentityServerBearerTokenAuthenticationOptions
{
Authority = ConfigurationManager.AppSettings["api:idserver"],
RequiredScopes = new[]
{
"chat-hub"
}
});
中间件的代码就是这个
var identity = Context.User.Identity as ClaimsIdentity;
我的启动课然后看起来像这样
public static string[] GetIdentityClaimsIssSub(HubCallerContext Context)
{
var identity = Context.User.Identity as ClaimsIdentity;
if (identity == null)
return null;
var issuerFromIdentity = identity.FindFirst("iss");
var subFromIdentity = identity.FindFirst("sub");
if (issuerFromIdentity == null || subFromIdentity == null)
return null;
return new string[] { issuerFromIdentity.Value, subFromIdentity.Value };
}
你可以在上面的代码中看到我告诉SignalR使用Oauth2服务器,那个代码就是这个
case
设置完毕后,我可以访问我的Context.User.Identity.Name,如果你想获得其他的IdentityClaim,你可以这样做
case someVar if someVar.length < 2 => someVar.toLowerCase
我正在使用上面的代码来获取这样的subjectId(userid)
case d if d.startsWith("www.") => d.substring(4)
我希望它有所帮助