2016-06-01 5 views
2

SignalR을 사용하여 WebAPI 서버 백엔드에서 JavaScript 웹 페이지로 메시지를 중계합니다. 이러한 메시지는 특정 사용자에게만 전달되므로 SignalR ConnectionId를 웹 페이지 사용자의 사용자 정의 ID와 매핑해야합니다.SignalR : OnConnected를 포함한 모든 통화에서 사용자 정의 ID 받기

현재 WebAPI는 FormsAuthentication을 사용하며 필요한 사용자 지정 ID는 쿠키에 있습니다.

처음에 나는 쿠키 떨어져 값을 가져 오도록 IUserIdProvider을 상속 : 올바르게 사용자 ID를 점점 늘어나는만큼 일

public class CustomIdProvider : IUserIdProvider 
{ 
    public string GetUserId(IRequest request) 
    { 
     Cookie formsAuthCookie = request.Cookies[FormsAuthentication.FormsCookieName]; 

     try 
     { 
      FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(formsAuthCookie.Value); 

      var obj = JsonConvert.DeserializeObject(ticket.Name) as JObject; 

      return (string)obj.GetValue("UserId"); 
     } 
     catch (Exception) 
     { 
      return null; 
     } 
    } 
} 

. 그러나 그 가치는 내가 말할 수있는 한 정체성에 결코 정해지지 않았습니다. Context.User.Identity.Name으로 인해 Identity 값을 편집 할 수 없었습니다. 모두 읽기 전용입니다.

편집 : CustomIdProvider를 다시 시도하면 GetUserId 메서드에서 반환 할 때 올바르게 값을 가져 오지만 OnConnected는 호출되지 않습니다.

내 다음 접근 방식은 Shaun Xu의 블로그 포스트 Set Context User Principal For Customized Authentication In SignalR을 기반으로했습니다. 여기 내 구현 :

public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    private const string CUSTOM_IDENTITY_KEY = "server.User"; 

    public override bool AuthorizeHubConnection(HubDescriptor hubDescriptor, IRequest request) 
    { 
     string customId; 

     // This gets the custom id from the cookie. 
     TryGetCustomId(request, out customId); 

     // The CustomIdentity class just sets the customId to the name.  
     request.Environment.Add(CUSTOM_IDENTITY_KEY, new ClaimsPrincipal(new CustomIdentity(customId, true))); 

     return true; 
    } 

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

     IDictionary<string, object> environment = hubIncomingInvokerContext.Hub.Context.Request.Environment; 

     object obj; 

     environment.TryGetValue(CUSTOM_IDENTITY_KEY, out obj); 

     var principal = obj as ClaimsPrincipal; 

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

     hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(environment), connectionId); 

     return true; 
    } 

이 실제로 두 가지 방법이 호출 될 때 올바르게 Context.User.Identity을 설정하기 위해 노력하고 있습니다.

그러나 내 문제는 사용자가 처음에 연결하고 OnConnected를 호출 할 때 AuthorizeHubMethodInvocation을 호출하지 않고 따라서 OnConnected에서 Context.User.Identity를 사용할 수 없다는 것입니다.

SignalR 허브의 모든 단계 (OnConnected, OnDisconnected 및 invoked 메소드)에서 내 사용자 정의 ID를 포함하는 올바른 ID에 액세스 할 수 있기를 원합니다.

아무에게도 좋은 해결책이 있습니까?

+0

세션에있는 항목을 다른 위치 (예 : 캐시 또는 데이터베이스)에 저장하는 대신 세션 ID로 연결 ID를 사용하는 것이 어떻습니까? 그런 다음 인증이 발생하기 전에 사용자를 추적 한 다음 해당 사용자를 인증하자마자 세션을 통해 메타 데이터를 추가 할 수 있습니다 – tommed

답변

1

나는 몇 가지 의견이 :

1) 당신은 권한 부여 단계에서 사용자 정의 정체성을 확립하려고해서는 안된다. 인증 단계의 관심사 여야합니다.

2) IUserIdProvider 사용자 지정을 구현하고 Context.User.Identity의 사용자 지정 ID를 설정하는 것은 별도의 우려입니다. 맞춤 IUserIdProvider지도Context.User.Identity의 속성 중 signalR의 사용자 식별자로 사용됩니다.

그래서 문제를 해결하십시오. 인증 단계에서 맞춤 ID를 설정해보십시오. 응용 프로그램 설정 방법에 따라 여러 가지 방법이 있습니다.사용자 정의 식별 ID를 구축

1) Application_PostAuthenticateRequest의 : 예를 들어

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e) 
{ 
    //Provide custom identity id to your HttpContext.Current.User 
    //In your case, you may extract that information from your authentication ticket. 
} 

하면 자세한 정보가 필요한 경우 당신은이 게시물에서 볼 수 있었다 : ASP.NET MVC - Set custom IIdentity or IPrincipal

2) 주장 ID를 사용하여 반환 할 수 있습니다 브라우저가 사용자의 서버에 요청을 보낼 때마다 사용자 정의 ID가 클레임으로, 클레임 ID가 다시 설정됩니다. 아래 예제에서 나는 owin 쿠키 인증을 사용합니다.

var claims = new List<Claim>(); 
    claims.Add(new Claim(ClaimTypes.Name, user.Id.ToString())); 

    var id = new ClaimsIdentity(claims, "Cookies"); 
    var ctx = Request.GetOwinContext(); 
    var authenticationManager = ctx.Authentication; 
    authenticationManager.SignIn(id); 

는 그런 다음 IUserIdProvider 구현에, 당신은 당신의 signalR 응용 프로그램에서 사용자 식별자로 사용하는 사용자의 ID에 해당하는 정보 ( Name 특성 제, ...)를 추출 할 수 있습니다.