1
0
mirror of https://github.com/chatopera/cosin.git synced 2025-08-01 16:38:02 +08:00
This commit is contained in:
Hai Liang Wang 2019-11-12 20:05:23 +08:00
parent 063e05ca1f
commit 2633da217c
11 changed files with 85 additions and 84 deletions

View File

@ -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/*

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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信息
*

View File

@ -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发送
* 检查收发双方的信息匹配

View File

@ -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()));

View File

@ -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(){

View File

@ -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";

View File

@ -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">&#xe608;</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">&#xe654;</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,

View File

@ -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");
}
});

View File

@ -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(){