XMPP SSO(Single Sign-On)

JID의 리소스가 부족하면 로그인 후 XMPP 서버에 tigase-10과 같은 리소스가 자동으로 할당됩니다.XMPP는 다중 로그인을 지원하기 때문에 서로 다른 클라이언트가 같은 JID로 로그인하면 서버는 모든 클라이언트에게 서로 다른 리소스를 분배하여 그들을 구분합니다.예를 들어 A 클라이언트의 리소스는tigase-10이고 B 클라이언트는tigase-11이다. 이때 A 클라이언트의 완전한jid는[email protected]/tigase-10, B 클라이언트의 jid는[email protected]/tigase-11.이렇게 하면 C 클라이언트가[email protected]/tigase-10 메시지를 보내면 A가 받습니다[email protected]/tigase-11은 B가 받지만[email protected]메시지를 보내면 서버가 도대체 누구에게 보냈는지 모르기 때문에 반드시 클라이언트가 메시지를 잃어버릴 것이다.
XMPP를 단일 로그인으로 만들려면 jid의 리소스가 일치해야 합니다. 예를 들어[email protected]/boris .XMPP 서버는 리소스가 일치하는 경우 두 가지 처리 가능성이 있습니다.
인용하다
If there is already an active resource of the same name, the server MUST either (1) terminate the active resource and allow the newly-requested session, or (2) disallow the newly-requested session and maintain the active resource. Which of these the server does is up to the implementation, although it is RECOMMENDED to implement case #1. In case #1, the server SHOULD send a stream error to the active resource, terminate the XML stream and underlying TCP connection for the active resource, and return a IQ stanza of type "result"(indicating success) to the newly-requested session. In case #2, the server SHOULD send a stanza error to the newly-requested session but maintain the XML stream for that connection so that the newly-requested session has an opportunity to negotiate a non-conflicting resource identifier before sending another request for session establishment.
간단하게 말하면 만약에 리소스가 일치한다면 첫 번째 방법은 활동하고 있는 리소스를 끝내고 최신 요청한 세션을 남기는 것이다. 즉, A가 먼저 로그인하고 B가 다시 로그인하면 A가 오프라인 된다.두 번째 방법은 최신 요청 세션을 거절하고 첫 번째를 유지하는 것이다. 즉, A가 먼저 로그인하고 B가 다시 로그인하면 B가 올라가지 않는다.
내 실례 중의 서버는 첫 번째 방법을 사용한다. 어떤 방법이든 오프라인 클라이언트는 서버가 보내는 error를 받는다.
<stream:error xmlns:stream="http://etherx.jabber.org/streams">
<conflict xmlns="urn:ietf:params:xml:ns:xmpp-streams"></conflict>
</stream:error>

conflict는 로그인 충돌을 대표하기 때문에 이 메시지를 받으면 다른 클라이언트가 같은jid에 로그인했는지 확인할 수 있습니다. 따라서 이 error만 처리하면 됩니다.
OC 의 XMPPFramework 에서 다음을 수행할 수 있습니다.
- (void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
{
	HWLOGI(@"didReceiveError:%@",error);
    DDXMLNode *errorNode = (DDXMLNode *)error;
    // 
    for(DDXMLNode *node in [errorNode children])
    {
        // 【 】
        if([[node name] isEqualToString:@"conflict"])
        {
            // 
            [_timer invalidate];
            NSString *message = [NSString stringWithFormat:@"%@さんが の でログインしたため、 にログアウトしました。",[[[SharedAppDelegate myInfo] myCardDetial]fullNameWithSpace]];

            // , OK logout
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:nil message:message delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
            alert.tag = 9999;
            alert.delegate = SharedAppDelegate;
            [alert show];
            [alert release];
        }
    }
}

좋은 웹페이지 즐겨찾기