📄 authenticate.java
字号:
ConnectReturnQosServer returnQos = new ConnectReturnQosServer(glob, info.getConnectQos().getData()); returnQos.getSessionQos().setSessionName(info.getSessionName()); returnQos.setReconnected(true); returnQos.getData().addClientProperty(Constants.CLIENTPROPERTY_RCVTIMESTAMPSTR, IsoDateParser.getCurrentUTCTimestampNanos()); log.info("Reconnected with given publicSessionId to '" + info.getSessionName() + "'."); return returnQos; } catch (XmlBlasterException e) { log.warning("Access is denied when trying to reconnect to session " + info.getSessionName() + ": " + e.getMessage()); throw e; // Thrown if authentication failed } catch (Throwable e) { log.severe("Internal error when trying to reconnect to session " + info.getSessionName() + " with public session ID: " + e.toString()); e.printStackTrace(); throw XmlBlasterException.convert(glob, ME, ErrorCode.INTERNAL_CONNECTIONFAILURE.toString(), e); } } } // [3] Generate a secret session ID if (secretSessionId == null || secretSessionId.length() < 2) { secretSessionId = createSessionId("null" /*subjectCtx.getName()*/); connectQos.getSessionQos().setSecretSessionId(secretSessionId); // assure consistency if (log.isLoggable(Level.FINE)) log.fine("Empty secretSessionId - generated secretSessionId=" + secretSessionId); } I_Session sessionCtx = null; I_Manager securityMgr = null; SessionInfo sessionInfo = null; try { // Get suitable SecurityManager and context ... securityMgr = plgnLdr.getManager(connectQos.getClientPluginType(), connectQos.getClientPluginVersion()); if (securityMgr == null) { log.warning("Access is denied, there is no security manager configured for this connect QoS: " + connectQos.toXml()); throw new XmlBlasterException(glob, ErrorCode.USER_SECURITY_AUTHENTICATION_ACCESSDENIED, ME, "There is no security manager configured with the given connect QoS"); } sessionCtx = securityMgr.reserveSession(secretSessionId); // always creates a new I_Session instance if (connectQos.bypassCredentialCheck()) { // This happens when a session is auto created by a PtP message // Only ConnectQosServer (which is under control of the core) can set this flag if (log.isLoggable(Level.FINE)) log.fine("SECURITY SWITCH OFF: Granted access to xmlBlaster without password, bypassCredentialCheck=true"); } else { String securityInfo = sessionCtx.init(connectQos.getSecurityQos()); // throws XmlBlasterExceptions if authentication fails if (securityInfo != null && securityInfo.length() > 1) log.warning("Ignoring security info: " + securityInfo); } // Now the client is authenticated } catch (XmlBlasterException e) { // If access is denied: cleanup resources log.warning("Access is denied: " + e.getMessage()); if (securityMgr != null) securityMgr.releaseSession(secretSessionId, null); // allways creates a new I_Session instance throw e; } catch (Throwable e) { log.severe("PANIC: Access is denied: " + e.getMessage() + "\n" + ServerScope.getStackTraceAsString(e)); // On error: cleanup resources securityMgr.releaseSession(secretSessionId, null); // allways creates a new I_Session instance throw XmlBlasterException.convert(glob, ME, ErrorCode.INTERNAL_CONNECTIONFAILURE.toString(), e); } if (log.isLoggable(Level.FINE)) log.fine("Checking if user is known ..."); SubjectInfo subjectInfo = null; try { /* // Check if user is known, otherwise create an entry ... I_Subject subjectCtx = sessionCtx.getSubject(); SessionName subjectName = new SessionName(glob, connectQos.getSessionName(), 0L); // Force to be of type subject (no public session ID) boolean subjectIsAlive = false; synchronized(this.loginNameSubjectInfoMap) { // Protect against two simultaneous logins subjectInfo = (SubjectInfo)this.loginNameSubjectInfoMap.get(subjectName.getLoginName()); //log.error(ME, "DEBUG ONLY, subjectName=" + subjectName.toString() + " loginName=" + subjectName.getLoginName() + " state=" + toXml()); if (subjectInfo == null) { subjectInfo = new SubjectInfo(getGlobal(), this, subjectName); this.loginNameSubjectInfoMap.put(subjectInfo.getLoginName(), subjectInfo); // Protect against two simultaneous logins } subjectIsAlive = subjectInfo.isAlive(); } // synchronized(this.loginNameSubjectInfoMap) if (!subjectInfo.isAlive()) { try { subjectInfo.toAlive(subjectCtx, connectQos.getSubjectQueueProperty()); } catch(Throwable e) { synchronized(this.loginNameSubjectInfoMap) { this.loginNameSubjectInfoMap.remove(subjectInfo.getLoginName()); } throw e; } } */ boolean returnLocked = true; subjectInfo = getOrCreateSubjectInfoByName(connectQos.getSessionName(), returnLocked, sessionCtx.getSubject(), connectQos.getSubjectQueueProperty()); try { // subjectInfo.getLock().release()) if (subjectInfo.isAlive()) { if (connectQos.getData().hasSubjectQueueProperty()) subjectInfo.setSubjectQueueProperty(connectQos.getSubjectQueueProperty()); // overwrites only if not null } // Check if client does a relogin and wants to destroy old sessions if (connectQos.getSessionQos().clearSessions() == true && subjectInfo.getNumSessions() > 0) { SessionInfo[] sessions = subjectInfo.getSessions(); for (int i=0; i<sessions.length; i++ ) { SessionInfo si = sessions[i]; log.warning("Destroying session '" + si.getSecretSessionId() + "' of user '" + subjectInfo.getSubjectName() + "' as requested by client"); disconnect(si.getSecretSessionId(), (String)null); } // will create a new SubjectInfo instance (which should be OK) return connect(connectQos, secretSessionId); } if (log.isLoggable(Level.FINE)) log.fine("Creating sessionInfo for " + subjectInfo.getId()); sessionInfo = getSessionInfo(connectQos.getSessionName()); if (sessionInfo != null && !sessionInfo.isShutdown() && sessionInfo.getConnectQos().bypassCredentialCheck()) { if (log.isLoggable(Level.FINE)) log.fine("connect: Reused session with had bypassCredentialCheck=true"); String oldSecretSessionId = sessionInfo.getSecretSessionId(); sessionInfo.setSecuritySession(sessionCtx); if (secretSessionId == null || secretSessionId.length() < 2) { // Keep the old secretSessionId connectQos.getSessionQos().setSecretSessionId(oldSecretSessionId); } else { // The CORBA driver insists in a new secretSessionId changeSecretSessionId(oldSecretSessionId, secretSessionId); connectQos.getSessionQos().setSecretSessionId(secretSessionId); } sessionInfo.updateConnectQos(connectQos); } else { // Create the new sessionInfo instance if (log.isLoggable(Level.FINE)) log.fine("connect: sessionId='" + secretSessionId + "' connectQos='" + connectQos.toXml() + "'"); sessionInfo = new SessionInfo(subjectInfo, sessionCtx, connectQos, getGlobal()); synchronized(this.sessionInfoMap) { this.sessionInfoMap.put(secretSessionId, sessionInfo); } } connectQos.getSessionQos().setSecretSessionId(secretSessionId); connectQos.getSessionQos().setSessionName(sessionInfo.getSessionName()); subjectInfo.notifyAboutLogin(sessionInfo); fireClientEvent(sessionInfo, true); } finally { if (subjectInfo != null) subjectInfo.getLock().release(); } // --- compose an answer ----------------------------------------------- ConnectReturnQosServer returnQos = new ConnectReturnQosServer(glob, connectQos.getData()); returnQos.getSessionQos().setSecretSessionId(secretSessionId); // securityInfo is not coded yet ! returnQos.getSessionQos().setSessionName(sessionInfo.getSessionName()); returnQos.getData().addClientProperty(Constants.CLIENTPROPERTY_RCVTIMESTAMPSTR, IsoDateParser.getCurrentUTCTimestampNanos()); // Now some nice logging ... StringBuffer sb = new StringBuffer(256); if (connectQos.bypassCredentialCheck()) sb.append("Created tempory session for client "); else sb.append("Successful login for client "); sb.append(sessionInfo.getSessionName().getAbsoluteName()); sb.append(", session"); sb.append(((connectQos.getSessionTimeout() > 0L) ? " expires after"+Timestamp.millisToNice(connectQos.getSessionTimeout()) : " lasts forever")); sb.append(", ").append(subjectInfo.getNumSessions()).append(" of "); sb.append(connectQos.getMaxSessions()).append(" sessions are in use."); log.info(sb.toString()); if (log.isLoggable(Level.FINEST)) log.finest(toXml()); if (log.isLoggable(Level.FINEST)) log.finest("Returned QoS:\n" + returnQos.toXml()); if (log.isLoggable(Level.FINER)) log.finer("Leaving connect()"); return returnQos; } catch (XmlBlasterException e) { String id = (sessionInfo != null) ? sessionInfo.getId() : ((subjectInfo != null) ? subjectInfo.getId() : ""); log.warning("Connection for " + id + " failed: " + e.getMessage()); //e.printStackTrace(); Sometimes nice, often not - what to do? try { if (sessionInfo != null) sessionInfo.setTransportConnectFail(e); disconnect(secretSessionId, (String)null); // cleanup } catch (Throwable th) { log.warning("Ignoring problems during cleanup of exception '" + e.getMessage() + "':" + th.getMessage()); } throw e; } catch (Throwable e) { e.printStackTrace(); log.severe("Internal error: Connect failed: " + e.getMessage()); try { disconnect(secretSessionId, (String)null); // cleanup } catch (Throwable th) { log.warning("Ignoring problems during cleanup of exception '" + e.getMessage() + "':" + th.getMessage()); } throw XmlBlasterException.convert(glob, ME, ErrorCode.INTERNAL_CONNECTIONFAILURE.toString(), e); } } public final /*synchronized*/ void disconnect(String secretSessionId, String qos_literal) throws XmlBlasterException { try { if (log.isLoggable(Level.FINER)) log.finer("Entering disconnect()"); //Thread.currentThread().dumpStack(); if (log.isLoggable(Level.FINEST)) log.finest(toXml().toString()); if (secretSessionId == null) { throw new IllegalArgumentException("disconnect() failed, the given secretSessionId is null"); } I_Manager securityMgr = plgnLdr.getManager(secretSessionId); I_Session sessionSecCtx = securityMgr.getSessionById(secretSessionId); if (sessionSecCtx == null) { throw new XmlBlasterException(this.glob, ErrorCode.USER_NOT_CONNECTED, ME + " Authenticate.disconnect", "You are not connected, your secretSessionId is invalid."); } try { CryptDataHolder dataHolder = new CryptDataHolder(MethodName.DISCONNECT, new MsgUnitRaw(null, (byte[])null, qos_literal), null); securityMgr.releaseSession(secretSessionId, sessionSecCtx.importMessage(dataHolder).getQos()); } catch(Throwable e) { log.warning("Ignoring importMessage() problems, we continue to cleanup resources: " + e.getMessage()); } SessionInfo sessionInfo = getSessionInfo(secretSessionId); if (sessionInfo.getCbQueueNumMsgs() > 0) { long sleep = glob.getProperty().get("cb.disconnect.pending.sleep", 1000L); // TODO: allow configuration over DisconnectQos log.info("Sleeping cb.disconnect.pending.sleep=" + sleep + " millis in disconnect(" + sessionInfo.getId() + ") to deliver " + sessionInfo.getCbQueueNumMsgs() + " pending messages ..."); try { Thread.sleep(sleep); } catch( InterruptedException i) {} } SubjectInfo subjectInfo = sessionInfo.getSubjectInfo(); DisconnectQosServer disconnectQos = new DisconnectQosServer(glob, qos_literal); boolean forceShutdownEvenIfEntriesExist = false; resetSessionInfo(sessionInfo, disconnectQos.deleteSubjectQueue(), forceShutdownEvenIfEntriesExist, true); if (disconnectQos.clearSessions() == true && subjectInfo.getNumSessions() > 0) { SessionInfo[] sessions = subjectInfo.getSessions(); for (int i=0; i<sessions.length; i++ ) { SessionInfo si = sessions[i]; log.warning("Destroying session '" + si.getSecretSessionId() + "' of user '" + subjectInfo.getSubjectName() + "' as requested by client"); disconnect(si.getSecretSessionId(), null); } } if (log.isLoggable(Level.FINEST)) log.finest(toXml().toString()); if (log.isLoggable(Level.FINER)) log.finer("Leaving disconnect()"); } catch (XmlBlasterException e) { if (log.isLoggable(Level.FINE)) log.fine("disconnect failed: " + e.getMessage()); throw e; } catch (Throwable e) { e.printStackTrace(); log.severe("Internal error: Disconnect failed: " + e.getMessage()); throw XmlBlasterException.convert(glob, ME, ErrorCode.INTERNAL_DISCONNECT.toString(), e); } } /** * Access a subjectInfo with the unique login name. * <p /> * If the client is yet unknown, there will be instantiated a dummy SubjectInfo object * @param returnLocked true: The SubjectInfo is locked * @param prop Can be null * @return the SubjectInfo object, is never null * @exception the SubjectInfo object is never locked in such a case */ public final SubjectInfo getOrCreateSubjectInfoByName(SessionName subjectName, boolean returnLocked, I_Subject subjectCtx, CbQueueProperty prop) throws XmlBlasterException
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -