2016-01-21 11 views
12

प्रश्न: मैं अज्ञात उपयोगकर्ताओं का प्रबंधन कैसे करूं ताकि जब एक हब प्रतिक्रिया भेजता है तो एक ही ब्राउज़र में एकाधिक टैब अपडेट किए जाते हैं?सिग्नलआर सी # एमवीसी मैपिंग क्लाइंट आईडी

मैं एक परियोजना में SignalR एकीकृत करने के लिए अज्ञात उपयोगकर्ताओं रह सकते हैं ताकि ऑपरेटरों के साथ चैट करना चाहते हैं:

परिदृश्य इस प्रकार है। जाहिर है उपयोगकर्ता iIdentity के साथ प्रमाणित है क्लाइंट.उसर (उपयोगकर्ता नाम) कमांड के माध्यम से मैप किया गया है। लेकिन वर्तमान में एक अनाम उपयोगकर्ता कह रहा है साइट.com/tools और site.com/notTools मैं केवल एक कनेक्शन आईडी के साथ सभी टैब पर संदेश नहीं भेज सकता। केवल एक टैब प्रतिक्रिया इकट्ठा करता है।

मैंने आईडब्ल्यूसी पैच का उपयोग करने का प्रयास किया है, लेकिन यह उपकरण चैट जानकारी को डेटाबेस में सहेजने के लिए खाता नहीं है और मुझे लगता है कि AJAX के माध्यम से गुजरने वाले चर डेटाबेस को पढ़ने/लिखने का एक सुरक्षित तरीका नहीं है।

मैं भी निम्नलिखित में ध्यान दिया है: Managing SignalR connections for Anonymous user

हालांकि ऐसी है कि के रूप में एक आधार बनाने और सत्र का उपयोग कर Owin से कम सुरक्षित लगता है।

मुझे क्लाइंट.यूसर() का उपयोग करने का विचार था जब भी उपयोगकर्ता डिस्कनेक्ट करते समय इसे कनेक्ट और हटाते समय झूठा खाता बनाते थे। लेकिन मैं कचरा खातों के साथ अपने एस्पनेटस डीबी संदर्भ को भरना नहीं चाहता, यह अनावश्यक लगता है।

क्या नकली उपयोगकर्ता नाम मानचित्र बनाने के लिए UserHandler.ConnectedIds.Add(Context.ConnectionId); का उपयोग करना संभव है? मुझे हानि हो रही है।

क्या iUserId प्रदाता का उपयोग करने के लिए यह समझदारी होगी?

public interface IUserIdProvider 
{ 
    string GetUserId(IRequest request); 
} 

फिर डेटाबेस बनाएं जो आईपी पते को कनेक्शन आईडी और एकल उपयोगकर्ता नामों में संग्रहीत करता है?

डेटाबेस:

उपयोगकर्ता: FK के साथ कनेक्शन आईडी को

|userid|username|IP  |connectionIDs| 
| 1 | user1 |127.0.0.1| 1   | 
| 2 | user2 |127.0.0.2| 2   | 

connectionIDs:

|connectionID|SignalRID|connectionIDs| 
|  1  | xx.x.x.x|  1  | 
|  2  | xx.xxx.x|  2  | 
|  3  | xx.xxxxx|  2  | 
|  4  | xxxxx.xx|  2  | 

तो संभवत: कनेक्शन के आसपास तर्क बारे में?

public override Task OnConnected() 
    { 
    if(Context.Identity.UserName != null){ 
     //add a connection based on the currently logged in user. 
    } 
    else{ 
    ///save new user to database? 
    } 
    } 

लेकिन सवाल अभी भी बनी हुई है कि मैं वेबसाईट पर कमांड भेजते समय उसके साथ कई टैब कैसे संभालूं?

अद्यतन स्पष्ट होने के लिए, मेरा इरादा लाइव चैट/समर्थन उपकरण बनाना है जो हर समय ब्राउज़र में अज्ञात पहुंच की अनुमति देता है।

ग्राहक http://www.livechatinc.com

को कुछ इसी तरह चाहता है मैं पहले से ही है कि भेजता है और केंद्र से प्राप्त करता है, क्या डोमेन उस पर है की परवाह किए बिना एक जावास्क्रिप्ट प्लगइन बनाया है। (मेरे क्लाइंट में मल्टीसाइट्स हैं) पहेली में लापता टुकड़ा सबसे आसान है, अज्ञात उपयोगकर्ताओं को बहु-टैबड वार्तालापों की अनुमति देने के लिए प्रबंधित करना।

+0

की तरह होगा एक Android एप्लिकेशन

mChatHub.invoke("Register", PrefUtils.MY_USER_ID).get(); 
जे एस के लिए

फार्म रजिस्टर करने के लिए क्या आप चाहते हैं करने के लिए सक्षम होने के लिए एक अनाम उपयोगकर्ता है किसी भी खुले ब्राउज़र टैब से उसी साइट (यानी साइट.com) से चैट करें, है ना? – tede24

+0

@ tede24 हां यही मैं चाहता हूं। – Chris

+3

क्या आप किसी प्रकार के सत्र आईडी (गइड) के साथ एक कुकी सेट नहीं कर सकते हैं, उस आईडी के लिए एक समूह बनाएं और वहां सभी कनेक्शन की सदस्यता लें? इस तरह आप संदेशों को सभी टैब – tede24

उत्तर

2

एक समाधान व्यापक रूप से अपनाया उपयोगकर्ता के साथ आईडी के बारे में उनकी किसी तरह के साथ रजिस्टर करने के लिए है कनेक्शन से वापस, कनेक्ट पर।

public override Task OnConnected() 
     { 
      Clients.Caller.Register(); 


      return base.OnConnected(); 
     } 

और ग्राहकों से अपना खुद का आईडी तर्क

किसी तरह के साथ एक कॉल के साथ उपयोगकर्ता रिटर्न की तुलना में रजिस्टर विधि

public void Register(Guid userId) 
    { 
     s_ConnectionCache.Add(userId, Guid.Parse(Context.ConnectionId)); 
    } 

और आप एक स्थिर शब्दकोश में उपयोगकर्ता आईडी रखने (ताले की देखभाल करें क्योंकि आपको इसे थ्रेड सुरक्षित होने की आवश्यकता है;

static readonly IConnectionCache s_ConnectionCache = new ConnectionsCache(); 

यहां

public class ConnectionsCache :IConnectionCache 
{ 
    private readonly Dictionary<Guid, UserConnections> m_UserConnections = new Dictionary<Guid, UserConnections>(); 
    private readonly Dictionary<Guid,Guid> m_ConnectionsToUsersMapping = new Dictionary<Guid, Guid>(); 
    readonly object m_UserLock = new object(); 
    readonly object m_ConnectionLock = new object(); 
    #region Public 


    public UserConnections this[Guid index] 
     => 
     m_UserConnections.ContainsKey(index) 
     ?m_UserConnections[index]:new UserConnections(); 

    public void Add(Guid userId, Guid connectionId) 
    { 
     lock (m_UserLock) 
     { 
      if (m_UserConnections.ContainsKey(userId)) 
      { 
       if (!m_UserConnections[userId].Contains(connectionId)) 
       { 

        m_UserConnections[userId].Add(connectionId); 

       } 

      } 
      else 
      { 
       m_UserConnections.Add(userId, new UserConnections() {connectionId}); 
      } 
     } 


      lock (m_ConnectionLock) 
      { 
       if (m_ConnectionsToUsersMapping.ContainsKey(connectionId)) 
       { 
        m_ConnectionsToUsersMapping[connectionId] = userId; 
       } 
       else 
       { 
         m_ConnectionsToUsersMapping.Add(connectionId, userId); 
       } 
      } 

    } 

    public void Remove(Guid connectionId) 
    { 
     lock (m_ConnectionLock) 
     { 
      if (!m_ConnectionsToUsersMapping.ContainsKey(connectionId)) 
      { 
       return; 
      } 
      var userId = m_ConnectionsToUsersMapping[connectionId]; 
      m_ConnectionsToUsersMapping.Remove(connectionId); 
      m_UserConnections[userId].Remove(connectionId); 
     } 



    } 

एक नमूना कॉल यह एक ही

chat.client.register = function() { 
    chat.server.register(SOME_USER_ID); 
} 
+0

जबकि आपका उदाहरण अंतरिम में काम करेगा, यह मेरे तत्काल मुद्दे को हल नहीं करता है। एप्लिकेशन पहले से मौजूद है, हालांकि हम समवर्ती-टैब को संभाल नहीं सकते हैं। यही एकमात्र मुद्दा है। हम उपयोगकर्ताओं को हमारी साइटों तक पहुंच के लिए पंजीकरण करने के लिए मजबूर नहीं करना चाहते हैं। जब कोई उपयोगकर्ता कनेक्ट होता है और वार्तालाप डेटा प्रारंभ करता है, तो नाम, ईमेल, क्वेरी का विवरण। "पंजीकृत" वार्तालाप से जुड़े हुए, अन्य टैब जो "पंजीकृत" नहीं हैं, तत्काल चैट वार्तालाप न करें। – Chris

+0

उपयोगकर्ता का उपनाम है - यहां आपका "ग्रुपिंग" टोकन है - लक्ष्य उपयोगकर्ता को पंजीकृत नहीं करना है, लक्ष्य अपने कनेक्शन को एक साथ समूह करना है, जैसा कि आप ग्राहकों के साथ जवाब देंगे। सभी()। आप आसानी से डायनामिक क्लाइंट = क्लाइंट्स का उपयोग कर प्रासंगिक कनेक्शन प्राप्त कर सकते हैं। क्लाइंट्स (उपयोगकर्ता कनेक्शन। चयन करें (x => x.ToString())। ToList()); और केवल उन कनेक्शनों के लिए डेटा को धक्का देने से। मैं एंड्रॉइड क्लाइंट के साथ इसका उपयोग कर रहा हूं, और मेरे पास कोई पंजीकरण नहीं है –

+0

मैं उत्तर के रूप में आपकी प्रतिक्रिया को चिह्नित कर रहा हूं। यह अंतरिम में काम करता है और मैं इसे बाद की तारीख में विकसित करूंगा। – Chris

5

मैं झूठी उपयोगकर्ता खाता विचार (यह नहीं जानता कि यह काम करता है) का पालन नहीं कर रहा है, लेकिन एक विकल्प विकसित करेगा।

लक्ष्य सभी ब्राउज़र टैब द्वारा साझा किए गए ChatSessionId कुकी के माध्यम से और इस ChatSessionId नामक समूह बनाने के माध्यम से हासिल किया जा सकता है।

मैंने asp.net/signalr से मूल चैट ट्यूटोरियल लिया और एक ही उपयोगकर्ता के रूप में कई टैब से चैट की अनुमति देने के लिए कार्यक्षमता जोड़ा।

1) उपयोगकर्ता की पहचान करने "चैट" कार्रवाई में एक चैट सत्र पहचान प्रदान करेगा, जैसा कि हम उपयोगकर्ता क्रेडेंशियल नहीं है:

public ActionResult Chat() 
    { 
     ChatSessionHelper.SetChatSessionCookie(); 
     return View(); 
    } 

2) सत्र चैट करने के लिए जब चैट पेज

दर्ज सदस्यता लें

ग्राहक के पक्ष

$.connection.hub.start() 
     .then(function(){chat.server.joinChatSession();}) 
     .done(function() { 
      ... 

सर्वर साइड (हब)

public Task JoinChatSession() 
{ 
    //get user SessionId to allow use multiple tabs 
    var sessionId = ChatSessionHelper.GetChatSessionId(); 
    if (string.IsNullOrEmpty(sessionId)) throw new InvalidOperationException("No chat session id"); 

    return Groups.Add(Context.ConnectionId, sessionId); 
} 

3), उपयोगकर्ता की बातचीत सत्र के लिए संदेश प्रसारित

public void Send(string message) 
{ 
    //get user chat session id 
    var sessionId = ChatSessionHelper.GetChatSessionId(); 
    if (string.IsNullOrEmpty(sessionId)) throw new InvalidOperationException("No chat session id"); 

    //now message will appear in all tabs 
    Clients.Group(sessionId).addNewMessageToPage(message); 
} 

अंत में (सरल) ChatSessionHelper वर्ग

public static class ChatSessionHelper 
{ 
    public static void SetChatSessionCookie() 
    { 
     var context = HttpContext.Current; 
     HttpCookie cookie = context.Request.Cookies.Get("Session") ?? new HttpCookie("Session", GenerateChatSessionId()); 

     context.Response.Cookies.Add(cookie); 
    } 

    public static string GetChatSessionId() 
    { 
     return HttpContext.Current.Request.Cookies.Get("Session")?.Value; 
    } 

    public static string GenerateChatSessionId() 
    { 
     return Guid.NewGuid().ToString(); 
    } 
} 
+0

जबकि आपका उत्तर काम करेगा, यह मेरी जरूरतों का पालन नहीं करता है, जो एक सुरक्षित स्टाइल चैट सिस्टम है। कोई भी व्यक्ति अपनी कुकीज़ को गलत साबित कर सकता है और चैट का उपयोग कर सकता है जिसका उपयोग करने का इरादा नहीं था। मुझे ऐसे समाधान की आवश्यकता है जो डेटा के आधार पर आईडी प्रबंधित करेगी जिसे आसानी से गलत नहीं किया जा सकता ... आसानी से।@ tede24 – Chris

+0

यह समाधान एक डोमेन के लिए काम करेगा, लेकिन यह ध्यान में नहीं रखता कि दो डोमेन को कुकी साझा करने की आवश्यकता है। – Chris

+0

@chris प्रश्न में दो डोमेन नहीं कहा गया है, उदाहरण हमेशा site.com/xx है। वैसे भी, जब भी आपको उचित कुकी सेटिंग्स – tede24

संबंधित मुद्दे