修复了发送文本消息会产生xss攻击的问题

master
cleverqin 4 years ago
parent 03c083fdc3
commit 53ec51d8f7

@ -93,7 +93,7 @@ io.sockets.on('connection',(socket)=>{
//删除登录用户信息,并通知所有在线用户 //删除登录用户信息,并通知所有在线用户
util.removeUser(socket.user.id); util.removeUser(socket.user.id);
socket.broadcast.emit('system', socket.user, 'logout'); socket.broadcast.emit('system', socket.user, 'logout');
store.saveUser(user,"logout"); store.saveUser(socket.user,"logout");
} }
}); });
let userJson=socket.handshake.query.User; let userJson=socket.handshake.query.User;

@ -252,10 +252,36 @@ html,body{
.message-item-send .message-content-container{ .message-item-send .message-content-container{
background-color: #0087f7; background-color: #0087f7;
color: #f2f2f2; color: #f2f2f2;
position: relative;
}
.message-item-send .message-content-container:after{
display: block;
content: '';
position: absolute;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 5px solid #0087f7;
top: 15px;
left: 100%;
}
.message-item-receive .message-content-container{
position: relative;
background-color: #ffffff;
color: #606266;
} }
.message-item-receive .message-avatar{ .message-item-receive .message-avatar{
float: left; float: left;
} }
.message-item-receive .message-content-container:before{
display: block;
content: '';
position: absolute;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-right: 5px solid #ffffff;
top: 15px;
right: 100%;
}
/****用户组件样式****/ /****用户组件样式****/
.user-item-avatar{ .user-item-avatar{
display: block; display: block;

@ -44,7 +44,9 @@
:num="getUnReadNum(item.id)" :num="getUnReadNum(item.id)"
:key="item.id"> :key="item.id">
<div slot="time" v-if="getLatestMessage(item.id).time">{{getLatestMessage(item.id).time | friendlyTime}}</div> <div slot="time" v-if="getLatestMessage(item.id).time">{{getLatestMessage(item.id).time | friendlyTime}}</div>
<span slot="message" v-if="getLatestMessage(item.id).type==='text'" v-html="renderExpression(getLatestMessage(item.id).content,baseUrl)"></span> <span slot="message" v-if="getLatestMessage(item.id).type==='text'">
<message-text :text="getLatestMessage(item.id).content"></message-text>
</span>
<div slot="message" v-if="getLatestMessage(item.id).type==='image'">【图片】</div> <div slot="message" v-if="getLatestMessage(item.id).type==='image'">【图片】</div>
</user-item> </user-item>
</div> </div>
@ -61,7 +63,9 @@
<div class="webChat-session-messages"> <div class="webChat-session-messages">
<div class="webChat-message-list scroll" ref="message-list"> <div class="webChat-message-list scroll" ref="message-list">
<message-item v-for="(item,i) in messages" :is-send="loginUser.id===item.from.id" :setting="setting" :key="i" :message="item"> <message-item v-for="(item,i) in messages" :is-send="loginUser.id===item.from.id" :setting="setting" :key="i" :message="item">
<div class="message-content-container" v-html="renderExpression(item.content,baseUrl)" slot="message" v-if="item.type==='text'"></div> <div class="message-content-container" slot="message" v-if="item.type==='text'">
<message-text :text="item.content"></message-text>
</div>
<div class="message-image-warp" slot="message" v-if="item.type==='image'" v-html="item.content"></div> <div class="message-image-warp" slot="message" v-if="item.type==='image'" v-html="item.content"></div>
</message-item> </message-item>
</div> </div>
@ -272,7 +276,9 @@
:num="getUnReadNum(item.id)" :num="getUnReadNum(item.id)"
:key="item.id"> :key="item.id">
<div slot="time" v-if="getLatestMessage(item.id).time">{{getLatestMessage(item.id).time | friendlyTime}}</div> <div slot="time" v-if="getLatestMessage(item.id).time">{{getLatestMessage(item.id).time | friendlyTime}}</div>
<span slot="message" v-if="getLatestMessage(item.id).type==='text'" v-html="renderExpression(getLatestMessage(item.id).content,baseUrl)"></span> <span slot="message" v-if="getLatestMessage(item.id).type==='text'">
<message-text :text="getLatestMessage(item.id).content"></message-text>
</span>
<div slot="message" v-if="getLatestMessage(item.id).type==='image'">【图片】</div> <div slot="message" v-if="getLatestMessage(item.id).type==='image'">【图片】</div>
</user-item> </user-item>
</div> </div>
@ -385,7 +391,9 @@
<div class="iChat-session-container" :class="{'with-panel':isShowTool||isShowExpression}"> <div class="iChat-session-container" :class="{'with-panel':isShowTool||isShowExpression}">
<div class="iChat-message-list scroll" ref="message-list"> <div class="iChat-message-list scroll" ref="message-list">
<message-item v-for="(item,i) in messages" :is-send="loginUser.id===item.from.id" :setting="setting" :key="i" :message="item"> <message-item v-for="(item,i) in messages" :is-send="loginUser.id===item.from.id" :setting="setting" :key="i" :message="item">
<div class="message-content-container" v-html="renderExpression(item.content,baseUrl)" slot="message" v-if="item.type==='text'"></div> <div class="message-content-container" slot="message" v-if="item.type==='text'">
<message-text :text="item.content"></message-text>
</div>
<div class="message-image-warp" slot="message" v-if="item.type==='image'" v-html="item.content"></div> <div class="message-image-warp" slot="message" v-if="item.type==='image'" v-html="item.content"></div>
</message-item> </message-item>
</div> </div>

@ -346,27 +346,40 @@
{title:"[飞机]",url: "/飞机.gif"}, {title:"[飞机]",url: "/飞机.gif"},
{title:"[气球]",url: "/气球.gif"} {title:"[气球]",url: "/气球.gif"}
]; ];
//渲染解析表情 let mapData=[];
const renderExpression=function(text,baseUrl){ expressions.forEach((item)=>{
let expressionMap={}; mapData[item.title]=item.url;
expressions.forEach((item,i)=>{
expressionMap[item.title]=i;
}); });
if(typeof (text) != "undefined") { //渲染解析表情
let arr = text.match(/\[.*?\]/g); const MessageText=Vue.extend({
if(arr&&arr.length>0){ props:{
for(let i = 0; i < arr.length; i++){ text:{
let index=expressionMap[arr[i]]; type:String,
if(index!==undefined) { default:""
let url=baseUrl+expressions[index].url;
const img = "<img src="+url +" class='expression-img'/>";
text = text.replace(arr[i],img);
} }
},
render(h){
const reg=/\[.*?\]/g;
let result=this.text.replace(reg,(word)=>{
return "|"+word+"|";
});
let arr=result.split('|');
return h('span',
arr.map((item)=>{
if(reg.test(item)&&mapData[item]){
return h('img',{
class:"expression-img",
attrs:{
src:mixin.data().baseUrl+mapData[item]
} }
})
}else {
return item;
} }
})
)
} }
return text; });
};
//消息组件 //消息组件
const MessageItem=Vue.extend({ const MessageItem=Vue.extend({
template:"#message-item", template:"#message-item",
@ -531,7 +544,7 @@
new Vue({ new Vue({
template: mainTpl, template: mainTpl,
el:"#app", el:"#app",
components:{MessageItem,UserItem,Login}, components:{MessageItem,UserItem,Login,MessageText},
mixins:[mixin], mixins:[mixin],
data(){ data(){
return { return {
@ -560,7 +573,6 @@
pickerExpression(item){ pickerExpression(item){
this.text+=item.title; this.text+=item.title;
}, },
renderExpression,
fileChange(e){ fileChange(e){
let file=e.target.files[0]; let file=e.target.files[0];
let maxSize=1*1024*1024; let maxSize=1*1024*1024;
@ -639,7 +651,7 @@
_this.socket.on("loginSuccess",(user,users)=>{ _this.socket.on("loginSuccess",(user,users)=>{
_this.loginUser=user; _this.loginUser=user;
_this.onlineUsers=users; _this.onlineUsers=users;
document.title="聊天室 | "+user.name; document.title=user.name+" 聊天室";
}); });
_this.socket.on("loginFail",(message)=>{ _this.socket.on("loginFail",(message)=>{
AlterMessage(message,'error') AlterMessage(message,'error')

Loading…
Cancel
Save