mirror of
https://github.com/chatopera/cosin.git
synced 2025-08-01 16:38:02 +08:00
Closed https://github.com/chatopera/cosin/issues/223 fix session length issue
This commit is contained in:
parent
063e05ca1f
commit
2633da217c
@ -14,7 +14,7 @@ RUN chmod +x /opt/install-corretto-8.sh && /opt/install-corretto-8.sh
|
||||
|
||||
# install other lib and configure timezone
|
||||
RUN apt-get update && \
|
||||
apt-get install --no-install-recommends -y tzdata mysql-client-5.7 zip unzip vim-tiny && \
|
||||
apt-get install --no-install-recommends -y tzdata mysql-client-5.7 zip unzip vim-tiny libfontconfig1 libfreetype6 && \
|
||||
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
DEBIAN_FRONTEND=noninteractive dpkg-reconfigure --frontend noninteractive tzdata && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
@ -42,7 +42,7 @@ public class AgentSessionSubscription {
|
||||
// 把登出消息通知给浏览器
|
||||
NettyClients.getInstance().publishLeaveEventMessage(
|
||||
json.get("agentno").getAsString(),
|
||||
json.get("post").getAsString());
|
||||
json.get("expired").getAsString());
|
||||
} catch (Exception e) {
|
||||
logger.warn("[onMessage] error", e);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import com.chatopera.cc.config.MessagingServerConfigure;
|
||||
import com.chatopera.cc.model.Dict;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.proxy.AgentSessionProxy;
|
||||
import com.chatopera.cc.proxy.UserProxy;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
@ -40,7 +41,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class UserInterceptorHandler extends HandlerInterceptorAdapter {
|
||||
private final static Logger logger = LoggerFactory.getLogger(UserInterceptorHandler.class);
|
||||
private static UserProxy userProxy;
|
||||
|
||||
private static AgentSessionProxy agentSessionProxy;
|
||||
private static Integer webimport;
|
||||
|
||||
@Override
|
||||
@ -48,12 +49,14 @@ public class UserInterceptorHandler extends HandlerInterceptorAdapter {
|
||||
throws Exception {
|
||||
boolean filter = false;
|
||||
User user = (User) request.getSession(true).getAttribute(Constants.USER_SESSION_NAME);
|
||||
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
Menu menu = handlerMethod.getMethod().getAnnotation(Menu.class);
|
||||
if (user != null || (menu != null && menu.access()) || handlerMethod.getBean() instanceof BasicErrorController) {
|
||||
filter = true;
|
||||
if (user != null && StringUtils.isNotBlank(user.getId())) {
|
||||
|
||||
/**
|
||||
* 每次刷新用户的组织机构、角色和权限
|
||||
* TODO 此处代码执行频率高,但是并不是每次都要执行,存在很多冗余
|
||||
@ -164,7 +167,7 @@ public class UserInterceptorHandler extends HandlerInterceptorAdapter {
|
||||
}
|
||||
|
||||
|
||||
public static Integer getWebimport() {
|
||||
private static Integer getWebimport() {
|
||||
if (webimport == null) {
|
||||
webimport = MainContext.getContext().getBean(MessagingServerConfigure.class).getWebIMPort();
|
||||
}
|
||||
@ -172,10 +175,18 @@ public class UserInterceptorHandler extends HandlerInterceptorAdapter {
|
||||
}
|
||||
|
||||
|
||||
public static UserProxy getUserProxy() {
|
||||
private static UserProxy getUserProxy() {
|
||||
if (userProxy == null) {
|
||||
userProxy = MainContext.getContext().getBean(UserProxy.class);
|
||||
}
|
||||
return userProxy;
|
||||
}
|
||||
|
||||
private static AgentSessionProxy getAgentSessionProxy() {
|
||||
if (agentSessionProxy == null) {
|
||||
agentSessionProxy = MainContext.getContext().getBean(AgentSessionProxy.class);
|
||||
}
|
||||
return agentSessionProxy;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,31 +48,42 @@ public class AgentSessionProxy {
|
||||
* @param orgi
|
||||
*/
|
||||
public void updateUserSession(final String agentno, final String sessionId, final String orgi) {
|
||||
// logger.info("[updateUserSession] agentno {}, sessionId {}, orgi {}", agentno, sessionId, orgi);
|
||||
logger.info("[updateUserSession] agentno {}, sessionId {}, orgi {}", agentno, sessionId, orgi);
|
||||
if (cache.existUserSessionByAgentnoAndOrgi(agentno, orgi)) {
|
||||
final String preSessionId = cache.findOneSessionIdByAgentnoAndOrgi(agentno, orgi);
|
||||
if (StringUtils.equals(preSessionId, sessionId)) {
|
||||
// 现在的session和之前的是一样的,忽略更新
|
||||
// logger.info(
|
||||
// "[updateUserSession] agentno {}, sessionId {} is synchronized, skip update.", agentno,
|
||||
// sessionId);
|
||||
logger.info(
|
||||
"[updateUserSession] agentno {}, sessionId {} is synchronized, skip update.", agentno,
|
||||
sessionId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(preSessionId)) {
|
||||
// 通知浏览器登出
|
||||
// logger.info("[updateUserSession] notify logut browser");
|
||||
JsonObject payload = new JsonObject();
|
||||
payload.addProperty("agentno", agentno); // 坐席ID
|
||||
payload.addProperty("pre", preSessionId); // 之前的Session
|
||||
payload.addProperty("orgi", orgi); // 租户Id
|
||||
payload.addProperty("post", sessionId); // 之后的Id
|
||||
brokerPublisher.send(Constants.MQ_TOPIC_WEB_SESSION_SSO, payload.toString(), true);
|
||||
publishAgentLeaveEvent(agentno, sessionId, orgi);
|
||||
}
|
||||
}
|
||||
cache.putUserSessionByAgentnoAndSessionIdAndOrgi(agentno, sessionId, orgi);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通知浏览器登出
|
||||
*
|
||||
* @param agentno
|
||||
* @param expired 过期的SessionID
|
||||
* @param orgi
|
||||
*/
|
||||
public void publishAgentLeaveEvent(final String agentno, final String expired, final String orgi) {
|
||||
//
|
||||
logger.info("[publishAgentLeaveEvent] notify logut browser, expired session {}", expired);
|
||||
JsonObject payload = new JsonObject();
|
||||
payload.addProperty("agentno", agentno); // 坐席ID
|
||||
payload.addProperty("orgi", orgi); // 租户Id
|
||||
payload.addProperty("expired", expired); // 之后的Id
|
||||
brokerPublisher.send(Constants.MQ_TOPIC_WEB_SESSION_SSO, payload.toString(), true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否是"不合法"的Session信息
|
||||
*
|
||||
|
@ -186,8 +186,13 @@ public class AgentEventHandler {
|
||||
final SocketIOClient client,
|
||||
final AckRequest request,
|
||||
final InterventMessage received) throws JsonProcessingException {
|
||||
final String agentno = client.get("agentno");
|
||||
final String session = client.get("session");
|
||||
final String connectid = client.get("connectid");
|
||||
logger.info(
|
||||
"[onEvent] intervention: {}", received.toJsonObject());
|
||||
"[onIntervetionEvent] intervention: agentno {}, session {}, connectid {}, payload {}", agentno, session, connectid,
|
||||
received.toJsonObject());
|
||||
|
||||
if (received.valid()) {
|
||||
|
||||
// 获得AgentUser
|
||||
@ -195,9 +200,11 @@ public class AgentEventHandler {
|
||||
|
||||
// 验证当前的SSO中的session是否和传入的session匹配
|
||||
if (getAgentSessionProxy().isInvalidSessionId(
|
||||
received.getSupervisorid(), received.getSession(), agentUser.getOrgi())) {
|
||||
agentno, session, agentUser.getOrgi())) {
|
||||
// 该session信息不合法
|
||||
logger.info("[onConnect] invalid sessionId {}", received.getSession());
|
||||
logger.info("[onIntervetionEvent] invalid sessionId {}", session);
|
||||
// 强制退出
|
||||
client.sendEvent(MainContext.MessageType.LEAVE.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -265,19 +272,35 @@ public class AgentEventHandler {
|
||||
final SocketIOClient client,
|
||||
final AckRequest request,
|
||||
final ChatMessage received) throws IOException {
|
||||
final String agentno = client.get("agentno");
|
||||
final String session = client.get("session");
|
||||
final String connectid = client.get("connectid");
|
||||
received.setSessionid(session);
|
||||
|
||||
// 此处user代表坐席的ID
|
||||
String agentno = client.getHandshakeData().getSingleUrlParam("userid");
|
||||
// String agentno = client.getHandshakeData().getSingleUrlParam("userid");
|
||||
|
||||
logger.info(
|
||||
"[onEvent] message: agentUserId {}, agentno {}, toUser {}, channel {}, orgi {}, appId {}, userId {}, sessionId {}",
|
||||
"[onMessageEvent] message: agentUserId {}, agentno {}, toUser {}, channel {}, orgi {}, appId {}, userId {}, sessionId {}, connectid {}",
|
||||
received.getAgentuser(), agentno, received.getTouser(),
|
||||
received.getChannel(), received.getOrgi(), received.getAppid(), received.getUserid(),
|
||||
received.getSessionid());
|
||||
session, connectid);
|
||||
|
||||
|
||||
// 验证当前的SSO中的session是否和传入的session匹配
|
||||
if (getAgentSessionProxy().isInvalidSessionId(
|
||||
agentno, session, received.getOrgi())) {
|
||||
// 该session信息不合法
|
||||
logger.info("[onMessageEvent] invalid sessionId {}", session);
|
||||
// 强制退出
|
||||
client.sendEvent(MainContext.MessageType.LEAVE.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
AgentUser agentUser = MainContext.getCache().findOneAgentUserByUserIdAndOrgi(
|
||||
received.getTouser(), received.getOrgi()).orElseGet(null);
|
||||
|
||||
|
||||
/**
|
||||
* 判断用户在线状态,如果用户在线则通过webim发送
|
||||
* 检查收发双方的信息匹配
|
||||
|
@ -70,7 +70,7 @@ public class IMEventHandler {
|
||||
try {
|
||||
final String user = client.getHandshakeData().getSingleUrlParam("userid");
|
||||
final String orgi = client.getHandshakeData().getSingleUrlParam("orgi");
|
||||
final String session = client.getHandshakeData().getSingleUrlParam("session");
|
||||
final String session = MainUtils.getContextID(client.getHandshakeData().getSingleUrlParam("session"));
|
||||
final String appid = client.getHandshakeData().getSingleUrlParam("appid");
|
||||
final String agent = client.getHandshakeData().getSingleUrlParam("agent");
|
||||
final String skill = client.getHandshakeData().getSingleUrlParam("skill");
|
||||
@ -88,6 +88,11 @@ public class IMEventHandler {
|
||||
"[onConnect] user {}, orgi {}, session {}, appid {}, agent {}, skill {}, title {}, url {}, traceid {}, nickname {}",
|
||||
user, orgi, session, appid, agent, skill, title, url, traceid, nickname);
|
||||
|
||||
// save connection info
|
||||
client.set("session", session);
|
||||
client.set("userid", user);
|
||||
client.set("appid", appid);
|
||||
|
||||
if (StringUtils.isNotBlank(user)) {
|
||||
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress();
|
||||
String ip = MainUtils.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString());
|
||||
@ -189,7 +194,7 @@ public class IMEventHandler {
|
||||
, orgi);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
logger.warn("[onDisconnect] error", e);
|
||||
}
|
||||
NettyClients.getInstance().removeIMEventClient(
|
||||
user, MainUtils.getContextID(client.getSessionId().toString()));
|
||||
|
@ -101,8 +101,11 @@ $(document).ready(function(){
|
||||
$('#agentdesktop').attr('data-href', '/agent/index.html?userid='+data.userid).click();
|
||||
}
|
||||
}).on('leave', function(data){
|
||||
// 执行登出
|
||||
window.location.href = "/logout.html?code=2";
|
||||
top.layer.msg('当前会话已经过期,稍后将自动登出!',{icon: 1, time: 2000});
|
||||
setTimeout(function(){
|
||||
// 执行登出
|
||||
window.location.href = "/logout.html?code=2";
|
||||
}, 2000);
|
||||
});
|
||||
/****每分钟执行一次,与服务器交互,保持会话****/
|
||||
setInterval(function(){
|
||||
|
@ -57,13 +57,13 @@ function restApiRequest(opts) {
|
||||
|
||||
// 操作成功的
|
||||
function handleRestApiSucc(msg) {
|
||||
layer.msg( msg || '操作成功',{icon: 1, offset: 'b', time: 1000})
|
||||
layer.msg( msg || '操作成功',{icon: 1, time: 1000})
|
||||
}
|
||||
|
||||
// 操作失败的
|
||||
function handleRestApiFail(status, reason) {
|
||||
if(status && status === 'AUTH_ERROR'){
|
||||
layer.msg('会话过期,请重新登录!',{icon: 2, offset: 'b', time: 3000});
|
||||
layer.msg('会话过期,请重新登录!',{icon: 2, time: 3000});
|
||||
setTimeout(function(){
|
||||
// 执行登出
|
||||
window.location.href = "/logout.html";
|
||||
|
@ -36,13 +36,6 @@
|
||||
<a href="/apps/contacts/add.html<#if ckind??>?ckind=${ckind}</#if>" title="新建联系人" data-toggle="ajax" data-width="950" data-height="600" class="layui-btn layui-btn-small"><i class="layui-icon"></i>新建联系人</a>
|
||||
</div>
|
||||
</#if>
|
||||
<#if user?? && (user.roleAuthMap[ "A02_A01_A02_B08"]?? || user.admin)>
|
||||
<div class="layui-btn-group ukefu-btn-group">
|
||||
<button class="layui-btn layui-btn-small" id="mass" title="群发" data-toggle="ajax" data-width="700" data-height="495">
|
||||
<i class="kfont"></i> 群发
|
||||
</button>
|
||||
</div>
|
||||
</#if>
|
||||
<#if user?? && (user.roleAuthMap[ "A02_A01_A02_B08"]?? || user.admin)>
|
||||
<div class="layui-btn-group ukefu-btn-group">
|
||||
<button class="layui-btn layui-btn-small" href="/apps/contacts/imp.html<#if ckind??>?ckind=${ckind}</#if>" title="导入联系人" data-toggle="ajax" data-width="950" data-height="600">
|
||||
@ -207,51 +200,6 @@
|
||||
$('#batexp').attr("href", "javascript:void(0)");
|
||||
}
|
||||
});
|
||||
|
||||
// TODO 群发消息时重构
|
||||
// $("#mass").click(function () {
|
||||
// var ids = "";
|
||||
// var num = 0;
|
||||
// $('.ids').each(function() {
|
||||
// if ($(this).prop("checked")) {
|
||||
// if (ids != "") {
|
||||
// ids += "&";
|
||||
// }
|
||||
// ids += "ids=" + $(this).val();
|
||||
// num++;
|
||||
// }
|
||||
// });
|
||||
// if (num > 0) {
|
||||
// $('#mass').attr('href', '/apps/contacts/startmass.html?' + ids);
|
||||
// console.log(ids);
|
||||
// } else {
|
||||
// layer.msg('请先选择需要群发的联系人信息',{icon: 2, offset: 'rb', time: 3000})
|
||||
// $('#mass').attr("href", "javascript:void(0)");
|
||||
// }
|
||||
// })
|
||||
|
||||
// TODO 群发消息时重构
|
||||
// function getQueryVariable(variable) {
|
||||
// var query = window.location.search.substring(1);
|
||||
// var vars = query.split("&");
|
||||
// for (var i=0;i<vars.length;i++) {
|
||||
// var pair = vars[i].split("=");
|
||||
// if(pair[0] == variable){return pair[1];}
|
||||
// }
|
||||
// return(false);
|
||||
// }
|
||||
|
||||
// TODO 群发消息时重构
|
||||
// if ( getQueryVariable('massStatus') ){
|
||||
// var multiMediaDialogWin = parent.$('#multiMediaDialogWin');
|
||||
//
|
||||
// if(multiMediaDialogWin.length>0){
|
||||
// parent.$('#multiMediaDialogWin').load(function{parent.layui.element().tabChange('ukefutab','multiMediaDialogWin');}).attr('src' , '/agent/index.html');
|
||||
// } else {
|
||||
// parent.$('#agentdesktop').attr('data-href' , '/agent/index.html').click();
|
||||
// }
|
||||
// }
|
||||
|
||||
});
|
||||
layui.use(['laypage', 'layer'], function() {
|
||||
var laypage = layui.laypage,
|
||||
|
@ -313,9 +313,9 @@
|
||||
drawCanvasImage(data.attachmentid) ;
|
||||
}
|
||||
if(data.calltype == "呼入"){
|
||||
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">'+data.createtime+'</label><label class="user">'+data.nickName+'</label> </div><div class="chatting-right"><i class="arrow arrow${inviteData.consult_dialog_color!''}"></i><div class="chat-content theme${inviteData.consult_dialog_color!''}">'+chat+'</div></div>' , "chat-block");
|
||||
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">'+data.createtime+'</label><label class="user">'+data.username+'</label> </div><div class="chatting-right"><i class="arrow arrow${inviteData.consult_dialog_color!''}"></i><div class="chat-content theme${inviteData.consult_dialog_color!''}">'+chat+'</div></div>' , "chat-block");
|
||||
}else if(data.calltype == "呼出"){
|
||||
output('<div class="chat-left"> <img class="user-img" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" alt=""><div class="chat-message"><label class="user">'+data.nickName+'</label><label class="time">'+data.createtime+'</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">'+chat+'</div></div>' , "chat-block");
|
||||
output('<div class="chat-left"> <img class="user-img" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" alt=""><div class="chat-message"><label class="user">'+data.username+'</label><label class="time">'+data.createtime+'</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">'+chat+'</div></div>' , "chat-block");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
<#elseif msg?? && msg == '1'>
|
||||
layer.msg('用户注册成功,请通过用户名和密码登陆',{icon: 2, time: 3000})
|
||||
<#elseif msg?? && msg == '2'>
|
||||
layer.msg('您的账号已经在其它浏览器登录,请确认是您本人的操作,保证安全。',{icon: 2, offset: 't', time: 0})
|
||||
layer.msg('您的账号已经在其它浏览器登录,请确认是您本人的操作,保证安全。',{icon: 4, offset: 't', time: 0})
|
||||
</#if>
|
||||
});
|
||||
layui.use('form', function(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user