怎么样了?我正在做一个SignalR项目,我在处理WebAPI(REST)和SignalR之间保留的OWIN上下文概念时遇到了相当困难的时间 .

基本概念是我使用WebAPI创建登录页面,用户向我发送我处理的凭据,尝试在进行数据库搜索后保留一些信息,使用声明设置授权和IPrincipal然后传递用户返回生成的Auth Token .

使用SignalR,我让Javascript在查询字符串中传回授权令牌 . 我们的想法是匹配以查看Owin上下文是否与您在尝试进行SignalR连接时传递的令牌相匹配 . 它允许您使用SignalR文档建议的授权属性连接到集线器 .

StartUp.CS

//SignalR
        app.Map("/listener", map =>
        {
            map.UseCors(CorsOptions.AllowAll);


            map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions
            {
                Provider = new QsoAuthBearerProvider()
            });

            var hubConfiguration = new HubConfiguration ();
            hubConfiguration.EnableDetailedErrors = true;
            hubConfiguration.Resolver = GlobalHost.DependencyResolver;


            GlobalHost.Configuration.ConnectionTimeout =  TimeSpan.FromMinutes(20); 
            GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(30);

            map.RunSignalR(hubConfiguration);
        });

QsoAuthBearerProvider.CS

public class QsoAuthBearerProvider: OAuthBearerAuthenticationProvider
{
    public override Task RequestToken(OAuthRequestTokenContext context)
    {
        if (context.Request.Path.ToString().Contains("connect"))
        {
            var value = context.Request.Query.Get("authToken");

            if (!string.IsNullOrEmpty(value))
            {
                context.Token = value;
            }
        }

        return Task.FromResult<object>(null);
    }
}

LoginController.CS

在这里,我尝试设定人和一切的身份 .

namespace WebSocketServer.Controller
{
[RoutePrefix("login")]
public class LoginController : ApiController
{

    private static readonly log4net.ILog Log = ...

    private string CreateSessionKey()
    {
        //Creates a token key and passes it back as a string
    }


    private ClaimsPrincipal SetOwinContext(string sessionKey, UserCreds creds)
    {
        var userRepo = (User repository);
        var trackingRepo = (Tracking Repository);
        try
        {
            bool authenticated = false;

            authenticated = //Check with 3rd party if creds are good

            if (authenticated)
            {
                using (IDbConnection con = new SqlConnection(Constants.CONN_STR))
                {
                    var builder = new SqlBuilder();

                    var query = //My query for checking things using Dapper

                    var user = con.Query<SystemUser>(query.RawSql, query.Parameters).First();

                    if (user == null || (user.LockedOut != false && user.LockedOut != null)) return null;

                    userRepo.SuccessfulLogin(creds.Username);
                    var owinContext = HttpContext.Current.GetOwinContext();

                    var claims = new List<Claim>
                    {

                        //Name
                        new Claim(ClaimTypes.Name, sessionKey),

                        //Username
                        new Claim(ClaimTypes.NameIdentifier, creds.Username??""),

                        new Claim(ClaimTypes.Actor,user.LastName + ", " + user.FirstName),

                        //SystemId in Db
                        new Claim(ClaimTypes.PrimarySid, user.SystemUserId.ToString() ??""),

                        //ConnectionId
                        //new Claim(ClaimTypes.Sid, " "),

                        //Authenticated
                        new Claim(ClaimTypes.Authentication, "true"),

                        //Token
                        new Claim(ClaimTypes.Thumbprint, sessionKey),

                        //Machine Ip
                        new Claim(ClaimTypes.WindowsDeviceClaim, creds.MachineIp ?? ""),

                        //Default View
                        new Claim(ClaimTypes.GroupSid, user.DefaultViewId?.ToString() ?? ""),

                        //Role
                        new Claim(ClaimTypes.Role, (user.IsAdmin != null && user.IsAdmin == true) ? "Admin" : "")
                    };

                    var claimsIdentity = new ClaimsIdentity(claims);

                    var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
                    Thread.CurrentPrincipal = claimsPrincipal;
                    owinContext.Authentication.User = claimsPrincipal;

                    var tracking = new ConnectionTracking
                    {
                        Authenticated = true,
                        SystemUserId = user.SystemUserId,
                        Token = sessionKey,
                        MachineIp = creds.MachineIp
                    };

                    trackingRepo.Add(tracking);
                    trackingRepo.Save();

                    return claimsPrincipal;
                }
            }
            return null;
        }
        catch (Exception ex)
        {
            return null;
        }
        finally
        {
            trackingRepo.Dispose();
            userRepo.Dispose();
        }
    }

    // POST api/<controller>
    /// <summary>
    /// Login registration
    /// </summary>
    /// <param name="userCreds">String containing user name and password</param>
    /// <returns></returns>
    //[ActionName("register")]
    public JObject Post([FromBody]UserCreds creds)
    {

        try
        {

            var privatePrincial = SetOwinContext(CreateSessionKey(), creds);
            var principal = HttpContext.Current.GetOwinContext();

            if (principal.Authentication.User != null)
            {

                var claim = principal.Authentication.User.FindAll(o => o.Type == ClaimTypes.Thumbprint)
                    .First<Claim>();
                Thread.CurrentPrincipal = HttpContext.Current.GetOwinContext().Authentication.User;
                return JObject.FromObject(new
                {
                    token = claim.Value                        
                });
            }
            else
            {
                return JObject.FromObject(new { token = "-1" });
            }


        }
        catch (Exception ex)
        {
            Log.Fatal(ex.ToString());
            return JObject.FromObject(new { error = ex.ToString() });

        }

    }

}
}

HubAuthorizeAttribute.CS

namespace WebSocketServer.Authentication
{
/// <summary>
/// Custom hub authorization
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class HubAuthorizeAttribute : AuthorizeAttribute
{
    private static readonly log4net.ILog Log = ...

    private string _ConnId { get; set; }


    /// <summary>
    /// Invocation for hub; Gets the connection string id
    /// </summary>
    /// <param name="hubIncomingInvokerContext"><see cref="IHubIncomingInvokerContext"/></param>
    /// <param name="appliesToMethod"></param>
    /// <returns>Boolean</returns>
    public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
    {
        try
        {


            var principal = HttpContext.Current.GetOwinContext();
            //hubIncomingInvokerContext.Hub.Context.QueryString.Get("authToken");
            if (principal != null && principal.Authentication.User.Identity.IsAuthenticated == true)
            {
                this._ConnId = hubIncomingInvokerContext.Hub.Context.ConnectionId;


                return true;
            }

            return false;

        }
        catch (Exception ex)
        {
            Log.Fatal(ex.ToString());
            return false;
        }
    }

    protected override bool UserAuthorized(IPrincipal user)
    {
        if (user == null) return false;

        var userPrincipal = user as IUserPrincipal;

        return userPrincipal != null && userPrincipal.Authenticated;
    }


    /// <summary>
    /// Authorization function for hub, works only if principal authenticated is true
    /// </summary>
    /// <param name="hubDescriptor"><see cref="HubDescriptor"/></param>
    /// <param name="request"></param>
    /// <returns>Boolean if person can access hub or not</returns>
    public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request)
    {
        try
        {
            var principal = HttpContext.Current.User as IUserPrincipal;

            return principal != null && principal.Authenticated == true;


            //return true;
        }
        catch (Exception ex)
        {
            Log.Fatal(ex.ToString());
            return false;
        }
    }
}
}

那么在我的集线器中使用[HubAuthorize]属性并尝试访问当前上下文会发生什么 . 现在,Request上下文始终将User作为null,与Thread.CurrentPrincipal,HttpContext.Current.GetOwinContext()相同 . 因此,似乎在使用WebAPI发回之后,上下文似乎丢失了 .

我不知道如何在Owin,我可以搜索身份或校长的不同实例,所以我可以查看那里的声明 .

我知道我的SignalR按原样工作,没有任何属性 . 我的代码在协商和连接时似乎没有干涉 . 我确实看到我的authToken的查询字符串涉及被传递,我能够在我的QsoAuthBearerProvider.RequestToken()函数中看到它 . 在上下文中,我可以看到它在那里,但不保留任何用户信息 .

我们将Angular作为纯前端,而SignalR在其自己的运行站点上充当中间件 .

所以,感谢您在此时提供的任何帮助 . 几天来,我一直在为此而奋斗,并没有取得什么进展 .

谢谢!