2014-10-30 2 views
11

+ я использовал this solution для реализации аутентификации на основе токена с использованием ASP.NET Web API 2, Owin и Identity ..., который отлично работал хорошо. Я использовал это other solution, и это для реализации авторизации и аутентификации хакеров сигнального уровня, передав токен-носитель через строку соединения, но похоже, что либо токен-носитель не собирается, либо что-то еще что-то не так где-то, и именно поэтому я ищу HELP .. .these мои коды ... QueryStringBearerAuthorizeAttribute: это класс, отвечающий за проверкуАутентификация SignalR с маркером-носителем webAPI

using ImpAuth.Entities; 
using Microsoft.AspNet.Identity.EntityFramework; 
using Microsoft.Owin.Security; 
using Microsoft.Owin.Security.OAuth; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Security.Claims; 
using System.Threading.Tasks; 
using System.Web; 

namespace ImpAuth.Providers 
{ 
    using System.Security.Claims; 
    using Microsoft.AspNet.SignalR; 
    using Microsoft.AspNet.SignalR.Hubs; 
    using Microsoft.AspNet.SignalR.Owin; 

    public class QueryStringBearerAuthorizeAttribute : AuthorizeAttribute 
    { 
     public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) 
     { 
      var token = request.QueryString.Get("Bearer"); 
      var authenticationTicket = Startup.AuthServerOptions.AccessTokenFormat.Unprotect(token); 

      if (authenticationTicket == null || authenticationTicket.Identity == null || !authenticationTicket.Identity.IsAuthenticated) 
      { 
       return false; 
      } 

      request.Environment["server.User"] = new ClaimsPrincipal(authenticationTicket.Identity); 
      request.Environment["server.Username"] = authenticationTicket.Identity.Name; 
      request.GetHttpContext().User = new ClaimsPrincipal(authenticationTicket.Identity); 
      return true; 
     } 

     public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod) 
     { 
      var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId; 

      // check the authenticated user principal from environment 
      var environment = hubIncomingInvokerContext.Hub.Context.Request.Environment; 
      var principal = environment["server.User"] as ClaimsPrincipal; 

      if (principal != null && principal.Identity != null && principal.Identity.IsAuthenticated) 
      { 
       // create a new HubCallerContext instance with the principal generated from token 
       // and replace the current context so that in hubs we can retrieve current user identity 
       hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(environment), connectionId); 

       return true; 
      } 

      return false; 
     } 
    } 
} 

и это мой пуск класс ....

using ImpAuth.Providers; 
using Microsoft.AspNet.SignalR; 
using Microsoft.Owin; 
using Microsoft.Owin.Cors; 
using Microsoft.Owin.Security.Facebook; 
using Microsoft.Owin.Security.Google; 
//using Microsoft.Owin.Security.Facebook; 
//using Microsoft.Owin.Security.Google; 
using Microsoft.Owin.Security.OAuth; 
using Owin; 
using System; 
using System.Collections.Generic; 
using System.Data.Entity; 
using System.Linq; 
using System.Web; 
using System.Web.Http; 

[assembly: OwinStartup(typeof(ImpAuth.Startup))] 

namespace ImpAuth 
{ 
    public class Startup 
    { 
     public static OAuthAuthorizationServerOptions AuthServerOptions; 

     static Startup() 
     { 
      AuthServerOptions = new OAuthAuthorizationServerOptions 
      { 
       AllowInsecureHttp = true, 
       TokenEndpointPath = new PathString("/token"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30), 
       Provider = new SimpleAuthorizationServerProvider() 
       // RefreshTokenProvider = new SimpleRefreshTokenProvider() 
      }; 
     } 

     public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } 
     public static GoogleOAuth2AuthenticationOptions googleAuthOptions { get; private set; } 
     public static FacebookAuthenticationOptions facebookAuthOptions { get; private set; } 

     public void Configuration(IAppBuilder app) 
     { 
      //app.MapSignalR(); 
      ConfigureOAuth(app); 
      app.Map("/signalr", map => 
      { 
       // Setup the CORS middleware to run before SignalR. 
       // By default this will allow all origins. You can 
       // configure the set of origins and/or http verbs by 
       // providing a cors options with a different policy. 
       map.UseCors(CorsOptions.AllowAll); 
       var hubConfiguration = new HubConfiguration 
       { 
        // You can enable JSONP by uncommenting line below. 
        // JSONP requests are insecure but some older browsers (and some 
        // versions of IE) require JSONP to work cross domain 
        //EnableJSONP = true 
        EnableDetailedErrors = true 
       }; 
       // Run the SignalR pipeline. We're not using MapSignalR 
       // since this branch already runs under the "/signalr" 
       // path. 
       map.RunSignalR(hubConfiguration); 
      }); 
      HttpConfiguration config = new HttpConfiguration(); 
      app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); 
      WebApiConfig.Register(config); 
      app.UseWebApi(config); 
     } 

     public void ConfigureOAuth(IAppBuilder app) 
     { 
      //use a cookie to temporarily store information about a user logging in with a third party login provider 
      app.UseExternalSignInCookie(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ExternalCookie); 
      OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); 

      OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() 
      { 
       AllowInsecureHttp = true, 
       TokenEndpointPath = new PathString("/token"), 
       AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
       Provider = new SimpleAuthorizationServerProvider() 
      }; 

      // Token Generation 
      app.UseOAuthAuthorizationServer(OAuthServerOptions); 
      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 

      //Configure Google External Login 
      googleAuthOptions = new GoogleOAuth2AuthenticationOptions() 
      { 
       ClientId = "1062903283154-94kdm6orqj8epcq3ilp4ep2liv96c5mn.apps.googleusercontent.com", 
       ClientSecret = "rv5mJUz0epWXmvWUAQJSpP85", 
       Provider = new GoogleAuthProvider() 
      }; 
      app.UseGoogleAuthentication(googleAuthOptions); 

      //Configure Facebook External Login 
      facebookAuthOptions = new FacebookAuthenticationOptions() 
      { 
       AppId = "CHARLIE", 
       AppSecret = "xxxxxx", 
       Provider = new FacebookAuthProvider() 
      }; 
      app.UseFacebookAuthentication(facebookAuthOptions); 
     } 
    } 

} 

и это нокаут плюс код jquery на клиенте ....

function chat(name, message) { 
    self.Name = ko.observable(name); 
    self.Message = ko.observable(message); 
} 

function viewModel() { 
    var self = this; 
    self.chatMessages = ko.observableArray(); 

    self.sendMessage = function() { 
     if (!$('#message').val() == '' && !$('#name').val() == '') { 
      $.connection.hub.qs = { Bearer: "yyCH391w-CkSVMv7ieH2quEihDUOpWymxI12Vh7gtnZJpWRRkajQGZhrU5DnEVkOy-hpLJ4MyhZnrB_EMhM0FjrLx5bjmikhl6EeyjpMlwkRDM2lfgKMF4e82UaUg1ZFc7JFAt4dFvHRshX9ay0ziCnuwGLvvYhiriew2v-F7d0bC18q5oqwZCmSogg2Osr63gAAX1oo9zOjx5pe2ClFHTlr7GlceM6CTR0jz2mYjSI" }; 
      $.connection.hub.start().done(function() { 
       $.connection.hub.qs = { Bearer: "yyCH391w-CkSVMv7ieH2quEihDUOpWymxI12Vh7gtnZJpWRRkajQGZhrU5DnEVkOy-hpLJ4MyhZnrB_EMhM0FjrLx5bjmikhl6EeyjpMlwkRDM2lfgKMF4e82UaUg1ZFc7JFAt4dFvHRshX9ay0ziCnuwGLvvYhiriew2v-F7d0bC18q5oqwZCmSogg2Osr63gAAX1oo9zOjx5pe2ClFHTlr7GlceM6CTR0jz2mYjSI" }; 
       $.connection.impAuthHub.server.sendMessage($('#name').val(), $('#message').val()) 
          .done(function() { $('#message').val(''); $('#name').val(''); }) 
          .fail(function (e) { alert(e) }); 
      }); 
     } 
    } 

    $.connection.impAuthHub.client.newMessage = function (NAME, MESSAGE) { 
     //alert(ko.toJSON(NAME, MESSAGE)); 
     var chat1 = new chat(NAME, MESSAGE); 
     self.chatMessages.push(chat1); 
    } 

} 

ko.applyBindings(new viewModel()); 

и вот мой класс ступицы ...

using ImpAuth.Providers; 
using Microsoft.AspNet.SignalR; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace ImpAuth 
{ 
    public class impAuthHub : Hub 
    { 
     [QueryStringBearerAuthorize] 
     public void SendMessage(string name, string message) 
     { 

      Clients.All.newMessage(name, message); 
     } 
    } 
} 

... теперь проблема возникает, когда я пытаюсь вызвать аутентификацию класса ступицы и я получаю эту ошибку

caller is not authenticated to invove method sendMessage in impAuthHub 

но затем я изменяю этот метод в классе QueryStringBearerAuthorizeAttribute так, чтобы он возвращался как true

public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod) 
     { 
      var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId; 

      // check the authenticated user principal from environment 
      var environment = hubIncomingInvokerContext.Hub.Context.Request.Environment; 
      var principal = environment["server.User"] as ClaimsPrincipal; 

      if (principal != null && principal.Identity != null && principal.Identity.IsAuthenticated) 
      { 
       // create a new HubCallerContext instance with the principal generated from token 
       // and replace the current context so that in hubs we can retrieve current user identity 
       hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(environment), connectionId); 

       return true; 
      } 

      return true; 
     } 

... он работает .... ЧТО ТАКОЕ ПРОБЛЕМА С МОЕМ КОДОМ ИЛИ РЕАЛИЗАЦИЕЙ?

+0

Я послал письмо Луи, который раздвоенный мой репозиторий и реализована интеграция с SignalR , надеюсь, он проверит и сможет помочь. Рад, что мои сообщения были полезны в вашем случае :) –

+0

Привет, Taiseer благодарит за письмо. МакКабуэ, есть несколько вещей, о которых я могу думать. сначала вы могли бы отладить ваше приложение и разбить его на линии, где мы устанавливаем var main. Я хотел бы видеть, какие значения размещены в принципе. Это будет лучшее место для начала. –

+0

+ привет Льюис ... я получаю нулевое значение принципа ... либо токен-носитель не отправляется, покупая способ, как я могу проверить, отправляется ли токен-носитель с клиента? – McKabue

ответ

24

Вам необходимо настроить свой сигнал так:

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

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

    var hubConfiguration = new HubConfiguration 
    { 
     Resolver = GlobalHost.DependencyResolver, 
    }; 
    map.RunSignalR(hubConfiguration); 
}); 

Затем вам нужно написать базовый пользовательский OAuthBearerAuthenticationProvider для signalR, который принимает access_token в виде строки запроса.

public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider 
{ 
    public override Task RequestToken(OAuthRequestTokenContext context) 
    { 
     var value = context.Request.Query.Get("access_token"); 

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

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

После этого все, что вам нужно, это отправить access_token с сигнальным соединением в качестве строки запроса.

$.connection.hub.qs = { 'access_token': token }; 

А для хаба просто обычный [Authorize] атрибут

public class impAuthHub : Hub 
{ 
    [Authorize] 
    public void SendMessage(string name, string message) 
    { 
     Clients.All.newMessage(name, message); 
    } 
} 

Надеется, что это помогает. Ярд

+0

И как бы вы получили доступ к пользователю из концентратора 'Context'? Вы можете назвать 'Context.User.Identity.Name'? Что делает эта линия точно? 'context.Token = value;' Как он заполняет контекст концентратора? Спасибо! –

+4

Я просто пробовал этот метод, но, к сожалению, мой «Context.User.Identity.Name» является «null» –

+0

Где «контекст» из «Провайдера» подходит в конвейере OWIN? Как будет влиять на мой «Контекст» тот факт, что я установил «context.Token» в токен, полученный от клиента? Любой репо/более сложный пример был бы золотом для меня прямо сейчас. Благодаря! –

1

Не могу прокомментировать, поэтому добавив свой ответ после комментариев о превосходном ответе Питера.

Было немного больше копания, и идентификатор пользователя, который я установил в моем настраиваемом провайдере авторизации owin, скрывался здесь (показан полный метод хаба).

[Authorize] 
    public async Task<int> Test() 
    { 
     var claims = (Context.User.Identity as System.Security.Claims.ClaimsIdentity).Claims.FirstOrDefault(); 
     if (claims != null) 
     { 
      var userId = claims.Value; 

      //security party! 
      return 1; 
     } 

     return 0; 
    } 

Больше добавлены texas697:

Startup.Auth.CS добавить это ConfigureAuth(), если не уже есть:

app.Map("/signalr", map => 
    { 
     map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions() 
     { 
      Provider = new QueryStringOAuthBearerProvider() //important bit! 
     }); 

     var hubConfiguration = new HubConfiguration 
     { 
      EnableDetailedErrors = true, 
      Resolver = GlobalHost.DependencyResolver, 
     }; 
     map.RunSignalR(hubConfiguration); 
    }); 

Поставщик пользовательских аутентификации выглядит следующим образом:

public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider 
{ 
    public override Task RequestToken(OAuthRequestTokenContext context) 
    { 
     var value = context.Request.Query.Get("access_token"); 

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

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

Я получаю сообщение об ошибке: Caller не имеет права вызывать метод на . Я вижу, что токен запроса выполнен правильно, а токен назначается с правом стоимость. –

Смежные вопросы