From ac247f8e6829768cf2e172cb43be46dda750dfc0 Mon Sep 17 00:00:00 2001 From: ronger Date: Wed, 11 May 2022 09:17:02 +0800 Subject: [PATCH 1/5] =?UTF-8?q?:lock:=20xss=20=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/ArticleServiceImpl.java | 11 +- .../service/impl/CommentServiceImpl.java | 8 +- .../service/impl/PortfolioServiceImpl.java | 2 + .../forest/service/impl/TagServiceImpl.java | 2 + .../forest/service/impl/TopicServiceImpl.java | 3 + .../java/com/rymcu/forest/util/XssUtils.java | 110 ++++++++++++++++++ 6 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/rymcu/forest/util/XssUtils.java diff --git a/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java index 7113a57..5890793 100644 --- a/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java @@ -12,10 +12,7 @@ import com.rymcu.forest.mapper.ArticleMapper; import com.rymcu.forest.service.ArticleService; import com.rymcu.forest.service.TagService; import com.rymcu.forest.service.UserService; -import com.rymcu.forest.util.Html2TextUtil; -import com.rymcu.forest.util.NotificationUtils; -import com.rymcu.forest.util.UserUtils; -import com.rymcu.forest.util.Utils; +import com.rymcu.forest.util.*; import com.rymcu.forest.web.api.exception.BaseApiException; import com.rymcu.forest.web.api.exception.ErrorCode; import lombok.extern.slf4j.Slf4j; @@ -112,7 +109,7 @@ public class ArticleServiceImpl extends AbstractService
implements Arti String articleTitle = article.getArticleTitle(); String articleTags = article.getArticleTags(); String articleContent = article.getArticleContent(); - String articleContentHtml = article.getArticleContentHtml(); + String articleContentHtml = XssUtils.replaceHtmlCode(article.getArticleContentHtml()); User user = UserUtils.getCurrentUserByToken(); if (Objects.isNull(user)) { throw new BaseApiException(ErrorCode.INVALID_TOKEN); @@ -358,7 +355,7 @@ public class ArticleServiceImpl extends AbstractService
implements Arti if (!type.equals(articleList)) { ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle()); if (type.equals(articleView)) { - article.setArticleContent(articleContent.getArticleContentHtml()); + article.setArticleContent(XssUtils.replaceHtmlCode(articleContent.getArticleContentHtml())); // 获取所属作品集列表数据 List portfolioArticleDTOList = articleMapper.selectPortfolioArticles(article.getIdArticle()); portfolioArticleDTOList.forEach(this::genPortfolioArticles); @@ -366,7 +363,7 @@ public class ArticleServiceImpl extends AbstractService
implements Arti } else if (type.equals(articleEdit)) { article.setArticleContent(articleContent.getArticleContent()); } else { - article.setArticleContent(articleContent.getArticleContentHtml()); + article.setArticleContent(XssUtils.replaceHtmlCode(articleContent.getArticleContentHtml())); } } return article; diff --git a/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java index 0602e87..f3838be 100644 --- a/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java @@ -12,6 +12,7 @@ import com.rymcu.forest.service.CommentService; import com.rymcu.forest.util.Html2TextUtil; import com.rymcu.forest.util.NotificationUtils; import com.rymcu.forest.util.Utils; +import com.rymcu.forest.util.XssUtils; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,6 +43,7 @@ public class CommentServiceImpl extends AbstractService implements Comm private List genComments(List commentDTOList) { commentDTOList.forEach(commentDTO -> { commentDTO.setTimeAgo(Utils.getTimeAgo(commentDTO.getCreatedTime())); + commentDTO.setCommentContent(XssUtils.replaceHtmlCode(commentDTO.getCommentContent())); if (commentDTO.getCommentAuthorId() != null) { Author author = commentMapper.selectAuthor(commentDTO.getCommentAuthorId()); if (author != null) { @@ -87,10 +89,10 @@ public class CommentServiceImpl extends AbstractService implements Comm comment.setCommentIP(ip); comment.setCommentUA(ua); comment.setCreatedTime(new Date()); + comment.setCommentContent(XssUtils.replaceHtmlCode(comment.getCommentContent())); commentMapper.insertSelective(comment); - StringBuilder commentSharpUrl = new StringBuilder(article.getArticlePermalink()); - commentSharpUrl.append("#comment-").append(comment.getIdComment()); - commentMapper.updateCommentSharpUrl(comment.getIdComment(), commentSharpUrl.toString()); + String commentSharpUrl = article.getArticlePermalink() + "#comment-" + comment.getIdComment(); + commentMapper.updateCommentSharpUrl(comment.getIdComment(), commentSharpUrl); String commentContent = comment.getCommentContent(); if(StringUtils.isNotBlank(commentContent)){ diff --git a/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java index ea40a5f..08492dc 100644 --- a/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java @@ -15,6 +15,7 @@ import com.rymcu.forest.service.PortfolioService; import com.rymcu.forest.service.UserService; import com.rymcu.forest.util.UserUtils; import com.rymcu.forest.util.Utils; +import com.rymcu.forest.util.XssUtils; import com.rymcu.forest.web.api.common.UploadController; import com.rymcu.forest.web.api.exception.BaseApiException; import org.apache.commons.lang.StringUtils; @@ -75,6 +76,7 @@ public class PortfolioServiceImpl extends AbstractService implements portfolio.setPortfolioAuthorId(user.getIdUser()); portfolio.setCreatedTime(new Date()); portfolio.setUpdatedTime(portfolio.getCreatedTime()); + portfolio.setPortfolioDescriptionHtml(XssUtils.replaceHtmlCode(portfolio.getPortfolioDescription())); portfolioMapper.insertSelective(portfolio); PortfolioIndexUtil.addIndex( PortfolioLucene.builder() diff --git a/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java index 09b4680..8524506 100644 --- a/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java @@ -13,6 +13,7 @@ import com.rymcu.forest.service.TagService; import com.rymcu.forest.util.BaiDuAipUtils; import com.rymcu.forest.util.CacheUtils; import com.rymcu.forest.util.UserUtils; +import com.rymcu.forest.util.XssUtils; import com.rymcu.forest.web.api.common.UploadController; import com.rymcu.forest.web.api.exception.BaseApiException; import org.apache.commons.lang.StringUtils; @@ -127,6 +128,7 @@ public class TagServiceImpl extends AbstractService implements TagService { Integer result; Map map = new HashMap(1); + tag.setTagDescription(XssUtils.replaceHtmlCode(tag.getTagDescription())); if (tag.getIdTag() == null) { if (StringUtils.isBlank(tag.getTagTitle())) { map.put("message", "标签名不能为空!"); diff --git a/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java index 8ee2856..8d261b3 100644 --- a/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java @@ -1,5 +1,6 @@ package com.rymcu.forest.service.impl; +import cn.hutool.http.HtmlUtil; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.rymcu.forest.core.service.AbstractService; @@ -10,6 +11,7 @@ import com.rymcu.forest.entity.Tag; import com.rymcu.forest.entity.Topic; import com.rymcu.forest.mapper.TopicMapper; import com.rymcu.forest.service.TopicService; +import com.rymcu.forest.util.XssUtils; import com.rymcu.forest.web.api.common.UploadController; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; @@ -48,6 +50,7 @@ public class TopicServiceImpl extends AbstractService implements TopicSer @Transactional(rollbackFor = Exception.class) public Map saveTopic(Topic topic) { Integer result = 0; + topic.setTopicDescriptionHtml(XssUtils.replaceHtmlCode(topic.getTopicDescriptionHtml())); Map map = new HashMap(1); if (topic.getIdTopic() == null) { if (StringUtils.isBlank(topic.getTopicTitle())) { diff --git a/src/main/java/com/rymcu/forest/util/XssUtils.java b/src/main/java/com/rymcu/forest/util/XssUtils.java new file mode 100644 index 0000000..d35f4c8 --- /dev/null +++ b/src/main/java/com/rymcu/forest/util/XssUtils.java @@ -0,0 +1,110 @@ +package com.rymcu.forest.util; + +import cn.hutool.http.HtmlUtil; +import org.apache.commons.lang.StringUtils; + +/** + * Created on 2022/5/10 17:06. + * + * @author ronger + * @email ronger-x@outlook.com + * @packageName com.rymcu.forest.util + */ +public class XssUtils { + + /** + * 滤除content中的危险 HTML 代码, 主要是脚本代码, 滚动字幕代码以及脚本事件处理代码 + * @param content 需要滤除的字符串 + * @return 过滤的结果 + */ + public static String replaceHtmlCode(String content) { + if (StringUtils.isBlank(content)) { + return null; + } + if (0 == content.length()) { + return ""; + } + // 需要滤除的脚本事件关键字 + String[] eventKeywords = { + "onmouseover", "onmouseout", "onmousedown", "onmouseup", "onmousemove", "onclick", "ondblclick", + "onkeypress", "onkeydown", "onkeyup", "ondragstart", "onerrorupdate", "onhelp", "onreadystatechange", + "onrowenter", "onrowexit", "onselectstart", "onload", "onunload", "onbeforeunload", "onblur", + "onerror", "onfocus", "onresize", "onscroll", "oncontextmenu", "alert" + }; +// content = replace(content, " -1) { + int b = 0; + String str1, str2, str3, str4, strA, strB; + str1 = source; + str2 = str1.toLowerCase(); + str3 = oldStr; + str4 = str3.toLowerCase(); + if (matchCase) { + strA = str1; + strB = str3; + } else { + strA = str2; + strB = str4; + } + a = strA.indexOf(strB, findStartPos); + if (a > -1) { + b = oldStr.length(); + findStartPos = a + b; + StringBuilder stringBuilder = new StringBuilder(source); + source = stringBuilder.replace(a, a + b, newStr) + ""; + // 新的查找开始点位于替换后的字符串的结尾 + findStartPos = findStartPos + newStr.length() - b; + } + } + return source; + } + +} + + From da934ff548c801138e7f347ae8c77a310e91682d Mon Sep 17 00:00:00 2001 From: ronger Date: Wed, 11 May 2022 19:50:28 +0800 Subject: [PATCH 2/5] =?UTF-8?q?:lock:=20=E8=AF=84=E8=AE=BA=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E7=94=A8=E6=88=B7=E9=89=B4=E6=9D=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rymcu/forest/service/CommentService.java | 3 +- .../service/impl/CommentServiceImpl.java | 33 +++++++++---------- .../web/api/comment/CommentController.java | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/rymcu/forest/service/CommentService.java b/src/main/java/com/rymcu/forest/service/CommentService.java index 92b2b9d..a6bc0ed 100644 --- a/src/main/java/com/rymcu/forest/service/CommentService.java +++ b/src/main/java/com/rymcu/forest/service/CommentService.java @@ -3,6 +3,7 @@ package com.rymcu.forest.service; import com.rymcu.forest.core.service.Service; import com.rymcu.forest.dto.CommentDTO; import com.rymcu.forest.entity.Comment; +import com.rymcu.forest.web.api.exception.BaseApiException; import javax.servlet.http.HttpServletRequest; import java.util.List; @@ -26,7 +27,7 @@ public interface CommentService extends Service { * @param request * @return */ - Map postComment(Comment comment, HttpServletRequest request); + Map postComment(Comment comment, HttpServletRequest request) throws BaseApiException; /** * 获取评论列表数据 diff --git a/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java index f3838be..111d52b 100644 --- a/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java @@ -9,10 +9,8 @@ import com.rymcu.forest.entity.Comment; import com.rymcu.forest.mapper.CommentMapper; import com.rymcu.forest.service.ArticleService; import com.rymcu.forest.service.CommentService; -import com.rymcu.forest.util.Html2TextUtil; -import com.rymcu.forest.util.NotificationUtils; -import com.rymcu.forest.util.Utils; -import com.rymcu.forest.util.XssUtils; +import com.rymcu.forest.util.*; +import com.rymcu.forest.web.api.exception.BaseApiException; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -65,23 +63,24 @@ public class CommentServiceImpl extends AbstractService implements Comm @Override @Transactional(rollbackFor = Exception.class) - public Map postComment(Comment comment, HttpServletRequest request) { + public Map postComment(Comment comment, HttpServletRequest request) throws BaseApiException { + comment.setCommentAuthorId(Objects.requireNonNull(UserUtils.getCurrentUserByToken()).getIdUser()); Map map = new HashMap(1); - if(comment.getCommentArticleId() == null){ - map.put("message","非法访问,文章主键异常!"); + if (comment.getCommentArticleId() == null) { + map.put("message", "非法访问,文章主键异常!"); return map; } - if(comment.getCommentAuthorId() == null){ - map.put("message","非法访问,用户未登录!"); + if (comment.getCommentAuthorId() == null) { + map.put("message", "非法访问,用户未登录!"); return map; } - if(StringUtils.isBlank(comment.getCommentContent())){ - map.put("message","回帖内容不能为空!"); + if (StringUtils.isBlank(comment.getCommentContent())) { + map.put("message", "回帖内容不能为空!"); return map; } Article article = articleService.findById(comment.getCommentArticleId().toString()); if (article == null) { - map.put("message","文章不存在!"); + map.put("message", "文章不存在!"); return map; } String ip = Utils.getIpAddress(request); @@ -95,23 +94,23 @@ public class CommentServiceImpl extends AbstractService implements Comm commentMapper.updateCommentSharpUrl(comment.getIdComment(), commentSharpUrl); String commentContent = comment.getCommentContent(); - if(StringUtils.isNotBlank(commentContent)){ + if (StringUtils.isNotBlank(commentContent)) { Integer length = commentContent.length(); - if(length > MAX_PREVIEW){ + if (length > MAX_PREVIEW) { length = 200; } - String commentPreviewContent = commentContent.substring(0,length); + String commentPreviewContent = commentContent.substring(0, length); commentContent = Html2TextUtil.getContent(commentPreviewContent); // 评论者不是作者本人则进行消息通知 if (!article.getArticleAuthorId().equals(comment.getCommentAuthorId())) { - NotificationUtils.saveNotification(article.getArticleAuthorId(),comment.getIdComment(), NotificationConstant.Comment, commentContent); + NotificationUtils.saveNotification(article.getArticleAuthorId(), comment.getIdComment(), NotificationConstant.Comment, commentContent); } // 判断是否是回复消息 if (comment.getCommentOriginalCommentId() != null && comment.getCommentOriginalCommentId() != 0) { Comment originalComment = commentMapper.selectByPrimaryKey(comment.getCommentOriginalCommentId()); // 回复消息时,评论者不是上级评论作者则进行消息通知 if (!comment.getCommentAuthorId().equals(originalComment.getCommentAuthorId())) { - NotificationUtils.saveNotification(originalComment.getCommentAuthorId(),comment.getIdComment(), NotificationConstant.Comment, commentContent); + NotificationUtils.saveNotification(originalComment.getCommentAuthorId(), comment.getIdComment(), NotificationConstant.Comment, commentContent); } } } diff --git a/src/main/java/com/rymcu/forest/web/api/comment/CommentController.java b/src/main/java/com/rymcu/forest/web/api/comment/CommentController.java index 7ca1ed4..56d8cb6 100644 --- a/src/main/java/com/rymcu/forest/web/api/comment/CommentController.java +++ b/src/main/java/com/rymcu/forest/web/api/comment/CommentController.java @@ -26,7 +26,7 @@ public class CommentController { private CommentService commentService; @PostMapping("/post") - public GlobalResult postComment(@RequestBody Comment comment, HttpServletRequest request) throws BaseApiException, UnsupportedEncodingException { + public GlobalResult postComment(@RequestBody Comment comment, HttpServletRequest request) throws BaseApiException { Map map = commentService.postComment(comment,request); return GlobalResultGenerator.genSuccessResult(map); } From 38e0178af9a75c743e5ee3e1012e2b084b064169 Mon Sep 17 00:00:00 2001 From: ronger Date: Mon, 23 May 2022 09:46:44 +0800 Subject: [PATCH 3/5] =?UTF-8?q?:lock:=20xss=20=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/ArticleServiceImpl.java | 6 +- .../service/impl/CommentServiceImpl.java | 4 +- .../service/impl/PortfolioServiceImpl.java | 2 +- .../forest/service/impl/TagServiceImpl.java | 2 +- .../forest/service/impl/TopicServiceImpl.java | 4 +- .../java/com/rymcu/forest/util/XssUtils.java | 91 +++++++------------ 6 files changed, 40 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java index 5890793..68f919d 100644 --- a/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/ArticleServiceImpl.java @@ -109,7 +109,7 @@ public class ArticleServiceImpl extends AbstractService
implements Arti String articleTitle = article.getArticleTitle(); String articleTags = article.getArticleTags(); String articleContent = article.getArticleContent(); - String articleContentHtml = XssUtils.replaceHtmlCode(article.getArticleContentHtml()); + String articleContentHtml = XssUtils.filterHtmlCode(article.getArticleContentHtml()); User user = UserUtils.getCurrentUserByToken(); if (Objects.isNull(user)) { throw new BaseApiException(ErrorCode.INVALID_TOKEN); @@ -355,7 +355,7 @@ public class ArticleServiceImpl extends AbstractService
implements Arti if (!type.equals(articleList)) { ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle()); if (type.equals(articleView)) { - article.setArticleContent(XssUtils.replaceHtmlCode(articleContent.getArticleContentHtml())); + article.setArticleContent(XssUtils.filterHtmlCode(articleContent.getArticleContentHtml())); // 获取所属作品集列表数据 List portfolioArticleDTOList = articleMapper.selectPortfolioArticles(article.getIdArticle()); portfolioArticleDTOList.forEach(this::genPortfolioArticles); @@ -363,7 +363,7 @@ public class ArticleServiceImpl extends AbstractService
implements Arti } else if (type.equals(articleEdit)) { article.setArticleContent(articleContent.getArticleContent()); } else { - article.setArticleContent(XssUtils.replaceHtmlCode(articleContent.getArticleContentHtml())); + article.setArticleContent(XssUtils.filterHtmlCode(articleContent.getArticleContentHtml())); } } return article; diff --git a/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java index 111d52b..6773cc1 100644 --- a/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/CommentServiceImpl.java @@ -41,7 +41,7 @@ public class CommentServiceImpl extends AbstractService implements Comm private List genComments(List commentDTOList) { commentDTOList.forEach(commentDTO -> { commentDTO.setTimeAgo(Utils.getTimeAgo(commentDTO.getCreatedTime())); - commentDTO.setCommentContent(XssUtils.replaceHtmlCode(commentDTO.getCommentContent())); + commentDTO.setCommentContent(XssUtils.filterHtmlCode(commentDTO.getCommentContent())); if (commentDTO.getCommentAuthorId() != null) { Author author = commentMapper.selectAuthor(commentDTO.getCommentAuthorId()); if (author != null) { @@ -88,7 +88,7 @@ public class CommentServiceImpl extends AbstractService implements Comm comment.setCommentIP(ip); comment.setCommentUA(ua); comment.setCreatedTime(new Date()); - comment.setCommentContent(XssUtils.replaceHtmlCode(comment.getCommentContent())); + comment.setCommentContent(XssUtils.filterHtmlCode(comment.getCommentContent())); commentMapper.insertSelective(comment); String commentSharpUrl = article.getArticlePermalink() + "#comment-" + comment.getIdComment(); commentMapper.updateCommentSharpUrl(comment.getIdComment(), commentSharpUrl); diff --git a/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java index 08492dc..c0de668 100644 --- a/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/PortfolioServiceImpl.java @@ -76,7 +76,7 @@ public class PortfolioServiceImpl extends AbstractService implements portfolio.setPortfolioAuthorId(user.getIdUser()); portfolio.setCreatedTime(new Date()); portfolio.setUpdatedTime(portfolio.getCreatedTime()); - portfolio.setPortfolioDescriptionHtml(XssUtils.replaceHtmlCode(portfolio.getPortfolioDescription())); + portfolio.setPortfolioDescriptionHtml(XssUtils.filterHtmlCode(portfolio.getPortfolioDescription())); portfolioMapper.insertSelective(portfolio); PortfolioIndexUtil.addIndex( PortfolioLucene.builder() diff --git a/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java index 8524506..7b6bfdf 100644 --- a/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/TagServiceImpl.java @@ -128,7 +128,7 @@ public class TagServiceImpl extends AbstractService implements TagService { Integer result; Map map = new HashMap(1); - tag.setTagDescription(XssUtils.replaceHtmlCode(tag.getTagDescription())); + tag.setTagDescription(XssUtils.filterHtmlCode(tag.getTagDescription())); if (tag.getIdTag() == null) { if (StringUtils.isBlank(tag.getTagTitle())) { map.put("message", "标签名不能为空!"); diff --git a/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java b/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java index 8d261b3..bb81f9b 100644 --- a/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java +++ b/src/main/java/com/rymcu/forest/service/impl/TopicServiceImpl.java @@ -49,8 +49,8 @@ public class TopicServiceImpl extends AbstractService implements TopicSer @Override @Transactional(rollbackFor = Exception.class) public Map saveTopic(Topic topic) { - Integer result = 0; - topic.setTopicDescriptionHtml(XssUtils.replaceHtmlCode(topic.getTopicDescriptionHtml())); + Integer result; + topic.setTopicDescriptionHtml(XssUtils.filterHtmlCode(topic.getTopicDescriptionHtml())); Map map = new HashMap(1); if (topic.getIdTopic() == null) { if (StringUtils.isBlank(topic.getTopicTitle())) { diff --git a/src/main/java/com/rymcu/forest/util/XssUtils.java b/src/main/java/com/rymcu/forest/util/XssUtils.java index d35f4c8..abc1343 100644 --- a/src/main/java/com/rymcu/forest/util/XssUtils.java +++ b/src/main/java/com/rymcu/forest/util/XssUtils.java @@ -1,8 +1,14 @@ package com.rymcu.forest.util; +import cn.hutool.core.util.ReUtil; import cn.hutool.http.HtmlUtil; import org.apache.commons.lang.StringUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.regex.Pattern; + /** * Created on 2022/5/10 17:06. * @@ -31,16 +37,8 @@ public class XssUtils { "onrowenter", "onrowexit", "onselectstart", "onload", "onunload", "onbeforeunload", "onblur", "onerror", "onfocus", "onresize", "onscroll", "oncontextmenu", "alert" }; -// content = replace(content, " -1) { - int b = 0; - String str1, str2, str3, str4, strA, strB; - str1 = source; - str2 = str1.toLowerCase(); - str3 = oldStr; - str4 = str3.toLowerCase(); - if (matchCase) { - strA = str1; - strB = str3; - } else { - strA = str2; - strB = str4; - } - a = strA.indexOf(strB, findStartPos); - if (a > -1) { - b = oldStr.length(); - findStartPos = a + b; - StringBuilder stringBuilder = new StringBuilder(source); - source = stringBuilder.replace(a, a + b, newStr) + ""; - // 新的查找开始点位于替换后的字符串的结尾 - findStartPos = findStartPos + newStr.length() - b; + public static String filterHtmlCode(String content) { + String regex = "
[\\s|\\S]+?
"; + // 拿到匹配的pre标签List + List resultFindAll = ReUtil.findAll(regex, content, 0, new ArrayList<>()); + String result = ""; + // size大于0,就做替换 + if (resultFindAll.size() > 0) { + // 生成一个待替换唯一字符串 + String preTagReplace = UUID.randomUUID().toString() + System.currentTimeMillis(); + // 判断替换字符串是否唯一 + while (ReUtil.findAll(preTagReplace, content, 0, new ArrayList<>()).size() > 0) { + preTagReplace = UUID.randomUUID().toString() + System.currentTimeMillis(); } + Pattern pattern = Pattern.compile(preTagReplace); + // 替换pre标签内容 + String preFilter = ReUtil.replaceAll(content, regex, preTagReplace); + System.err.println("pre标签替换"); + System.err.println(preFilter); + final String[] filterResult = {HtmlUtil.filter(preFilter)}; + resultFindAll.forEach(obj -> { + filterResult[0] = ReUtil.replaceFirst(pattern, filterResult[0], obj); + }); + result = filterResult[0]; + } else { + result = HtmlUtil.filter(content); } - return source; + return result; } } From 007ab5d3aa3ad111f57b28ee23261ff472f73fae Mon Sep 17 00:00:00 2001 From: ronger Date: Mon, 23 May 2022 09:50:27 +0800 Subject: [PATCH 4/5] :arrow_up: fastjson v2 --- pom.xml | 6 +++++- src/main/java/com/rymcu/forest/config/ShiroLoginFilter.java | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8d90720..ea0eb05 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ com.alibaba fastjson - 1.2.79 + 2.0.3 @@ -241,6 +241,10 @@ com.google.guava guava + + org.json + json + diff --git a/src/main/java/com/rymcu/forest/config/ShiroLoginFilter.java b/src/main/java/com/rymcu/forest/config/ShiroLoginFilter.java index 6f6d87d..babf323 100644 --- a/src/main/java/com/rymcu/forest/config/ShiroLoginFilter.java +++ b/src/main/java/com/rymcu/forest/config/ShiroLoginFilter.java @@ -2,6 +2,7 @@ package com.rymcu.forest.config; import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.serializer.SerializerFeature; import com.rymcu.forest.core.result.GlobalResultGenerator; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import org.slf4j.Logger; @@ -51,7 +52,7 @@ public class ShiroLoginFilter extends FormAuthenticationFilter { httpServletResponse.setCharacterEncoding("UTF-8"); httpServletResponse.setHeader("sessionstatus", "timeOut"); httpServletResponse.addHeader("loginPath", this.getLoginUrl()); - httpServletResponse.getWriter().write(JSONObject.toJSONString(GlobalResultGenerator.genErrorResult("未登录或已登录超时,请重新登录"),true)); + httpServletResponse.getWriter().write(JSONObject.toJSONString(GlobalResultGenerator.genErrorResult("未登录或已登录超时,请重新登录"), SerializerFeature.PrettyFormat)); return false; }else { if (log.isTraceEnabled()) { From 2779700f4995f3ecf67f935996a680ccf535d1e1 Mon Sep 17 00:00:00 2001 From: ronger Date: Mon, 23 May 2022 13:01:36 +0800 Subject: [PATCH 5/5] =?UTF-8?q?:lock:=20xss=20=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/rymcu/forest/util/XssUtils.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/rymcu/forest/util/XssUtils.java b/src/main/java/com/rymcu/forest/util/XssUtils.java index abc1343..6760653 100644 --- a/src/main/java/com/rymcu/forest/util/XssUtils.java +++ b/src/main/java/com/rymcu/forest/util/XssUtils.java @@ -17,6 +17,7 @@ import java.util.regex.Pattern; * @packageName com.rymcu.forest.util */ public class XssUtils { + private static final String regex = "(
[\\s|\\S]+?
)|([\\s|\\S]+?)"; /** * 滤除content中的危险 HTML 代码, 主要是脚本代码, 滚动字幕代码以及脚本事件处理代码 @@ -48,10 +49,11 @@ public class XssUtils { } public static String filterHtmlCode(String content) { - String regex = "
[\\s|\\S]+?
"; + if(StringUtils.isBlank(content)) { + return content; + } // 拿到匹配的pre标签List List resultFindAll = ReUtil.findAll(regex, content, 0, new ArrayList<>()); - String result = ""; // size大于0,就做替换 if (resultFindAll.size() > 0) { // 生成一个待替换唯一字符串 @@ -63,17 +65,15 @@ public class XssUtils { Pattern pattern = Pattern.compile(preTagReplace); // 替换pre标签内容 String preFilter = ReUtil.replaceAll(content, regex, preTagReplace); - System.err.println("pre标签替换"); - System.err.println(preFilter); - final String[] filterResult = {HtmlUtil.filter(preFilter)}; - resultFindAll.forEach(obj -> { - filterResult[0] = ReUtil.replaceFirst(pattern, filterResult[0], obj); - }); - result = filterResult[0]; + // 拦截xss + final String[] filterResult = {replaceHtmlCode(preFilter)}; + + // 依次将替换后的pre标签换回来 + resultFindAll.forEach(obj -> filterResult[0] = ReUtil.replaceFirst(pattern, filterResult[0], obj)); + return filterResult[0]; } else { - result = HtmlUtil.filter(content); + return replaceHtmlCode(content); } - return result; } }