🔒 xss 过滤

This commit is contained in:
ronger 2022-05-23 09:46:44 +08:00
parent da934ff548
commit 38e0178af9
6 changed files with 40 additions and 69 deletions

View File

@ -109,7 +109,7 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
String articleTitle = article.getArticleTitle(); String articleTitle = article.getArticleTitle();
String articleTags = article.getArticleTags(); String articleTags = article.getArticleTags();
String articleContent = article.getArticleContent(); String articleContent = article.getArticleContent();
String articleContentHtml = XssUtils.replaceHtmlCode(article.getArticleContentHtml()); String articleContentHtml = XssUtils.filterHtmlCode(article.getArticleContentHtml());
User user = UserUtils.getCurrentUserByToken(); User user = UserUtils.getCurrentUserByToken();
if (Objects.isNull(user)) { if (Objects.isNull(user)) {
throw new BaseApiException(ErrorCode.INVALID_TOKEN); throw new BaseApiException(ErrorCode.INVALID_TOKEN);
@ -355,7 +355,7 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
if (!type.equals(articleList)) { if (!type.equals(articleList)) {
ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle()); ArticleContent articleContent = articleMapper.selectArticleContent(article.getIdArticle());
if (type.equals(articleView)) { if (type.equals(articleView)) {
article.setArticleContent(XssUtils.replaceHtmlCode(articleContent.getArticleContentHtml())); article.setArticleContent(XssUtils.filterHtmlCode(articleContent.getArticleContentHtml()));
// 获取所属作品集列表数据 // 获取所属作品集列表数据
List<PortfolioArticleDTO> portfolioArticleDTOList = articleMapper.selectPortfolioArticles(article.getIdArticle()); List<PortfolioArticleDTO> portfolioArticleDTOList = articleMapper.selectPortfolioArticles(article.getIdArticle());
portfolioArticleDTOList.forEach(this::genPortfolioArticles); portfolioArticleDTOList.forEach(this::genPortfolioArticles);
@ -363,7 +363,7 @@ public class ArticleServiceImpl extends AbstractService<Article> implements Arti
} else if (type.equals(articleEdit)) { } else if (type.equals(articleEdit)) {
article.setArticleContent(articleContent.getArticleContent()); article.setArticleContent(articleContent.getArticleContent());
} else { } else {
article.setArticleContent(XssUtils.replaceHtmlCode(articleContent.getArticleContentHtml())); article.setArticleContent(XssUtils.filterHtmlCode(articleContent.getArticleContentHtml()));
} }
} }
return article; return article;

View File

@ -41,7 +41,7 @@ public class CommentServiceImpl extends AbstractService<Comment> implements Comm
private List<CommentDTO> genComments(List<CommentDTO> commentDTOList) { private List<CommentDTO> genComments(List<CommentDTO> commentDTOList) {
commentDTOList.forEach(commentDTO -> { commentDTOList.forEach(commentDTO -> {
commentDTO.setTimeAgo(Utils.getTimeAgo(commentDTO.getCreatedTime())); commentDTO.setTimeAgo(Utils.getTimeAgo(commentDTO.getCreatedTime()));
commentDTO.setCommentContent(XssUtils.replaceHtmlCode(commentDTO.getCommentContent())); commentDTO.setCommentContent(XssUtils.filterHtmlCode(commentDTO.getCommentContent()));
if (commentDTO.getCommentAuthorId() != null) { if (commentDTO.getCommentAuthorId() != null) {
Author author = commentMapper.selectAuthor(commentDTO.getCommentAuthorId()); Author author = commentMapper.selectAuthor(commentDTO.getCommentAuthorId());
if (author != null) { if (author != null) {
@ -88,7 +88,7 @@ public class CommentServiceImpl extends AbstractService<Comment> implements Comm
comment.setCommentIP(ip); comment.setCommentIP(ip);
comment.setCommentUA(ua); comment.setCommentUA(ua);
comment.setCreatedTime(new Date()); comment.setCreatedTime(new Date());
comment.setCommentContent(XssUtils.replaceHtmlCode(comment.getCommentContent())); comment.setCommentContent(XssUtils.filterHtmlCode(comment.getCommentContent()));
commentMapper.insertSelective(comment); commentMapper.insertSelective(comment);
String commentSharpUrl = article.getArticlePermalink() + "#comment-" + comment.getIdComment(); String commentSharpUrl = article.getArticlePermalink() + "#comment-" + comment.getIdComment();
commentMapper.updateCommentSharpUrl(comment.getIdComment(), commentSharpUrl); commentMapper.updateCommentSharpUrl(comment.getIdComment(), commentSharpUrl);

View File

@ -76,7 +76,7 @@ public class PortfolioServiceImpl extends AbstractService<Portfolio> implements
portfolio.setPortfolioAuthorId(user.getIdUser()); portfolio.setPortfolioAuthorId(user.getIdUser());
portfolio.setCreatedTime(new Date()); portfolio.setCreatedTime(new Date());
portfolio.setUpdatedTime(portfolio.getCreatedTime()); portfolio.setUpdatedTime(portfolio.getCreatedTime());
portfolio.setPortfolioDescriptionHtml(XssUtils.replaceHtmlCode(portfolio.getPortfolioDescription())); portfolio.setPortfolioDescriptionHtml(XssUtils.filterHtmlCode(portfolio.getPortfolioDescription()));
portfolioMapper.insertSelective(portfolio); portfolioMapper.insertSelective(portfolio);
PortfolioIndexUtil.addIndex( PortfolioIndexUtil.addIndex(
PortfolioLucene.builder() PortfolioLucene.builder()

View File

@ -128,7 +128,7 @@ public class TagServiceImpl extends AbstractService<Tag> implements TagService {
Integer result; Integer result;
Map map = new HashMap(1); Map map = new HashMap(1);
tag.setTagDescription(XssUtils.replaceHtmlCode(tag.getTagDescription())); tag.setTagDescription(XssUtils.filterHtmlCode(tag.getTagDescription()));
if (tag.getIdTag() == null) { if (tag.getIdTag() == null) {
if (StringUtils.isBlank(tag.getTagTitle())) { if (StringUtils.isBlank(tag.getTagTitle())) {
map.put("message", "标签名不能为空!"); map.put("message", "标签名不能为空!");

View File

@ -49,8 +49,8 @@ public class TopicServiceImpl extends AbstractService<Topic> implements TopicSer
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Map saveTopic(Topic topic) { public Map saveTopic(Topic topic) {
Integer result = 0; Integer result;
topic.setTopicDescriptionHtml(XssUtils.replaceHtmlCode(topic.getTopicDescriptionHtml())); topic.setTopicDescriptionHtml(XssUtils.filterHtmlCode(topic.getTopicDescriptionHtml()));
Map map = new HashMap(1); Map map = new HashMap(1);
if (topic.getIdTopic() == null) { if (topic.getIdTopic() == null) {
if (StringUtils.isBlank(topic.getTopicTitle())) { if (StringUtils.isBlank(topic.getTopicTitle())) {

View File

@ -1,8 +1,14 @@
package com.rymcu.forest.util; package com.rymcu.forest.util;
import cn.hutool.core.util.ReUtil;
import cn.hutool.http.HtmlUtil; import cn.hutool.http.HtmlUtil;
import org.apache.commons.lang.StringUtils; 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. * Created on 2022/5/10 17:06.
* *
@ -31,16 +37,8 @@ public class XssUtils {
"onrowenter", "onrowexit", "onselectstart", "onload", "onunload", "onbeforeunload", "onblur", "onrowenter", "onrowexit", "onselectstart", "onload", "onunload", "onbeforeunload", "onblur",
"onerror", "onfocus", "onresize", "onscroll", "oncontextmenu", "alert" "onerror", "onfocus", "onresize", "onscroll", "oncontextmenu", "alert"
}; };
// content = replace(content, "<script", "<script", false);
// content = replace(content, "</script", "</script", false);
// content = replace(content, "<marquee", "<marquee", false);
// content = replace(content, "</marquee", "</marquee", false);
content = HtmlUtil.removeHtmlTag(content, "script"); content = HtmlUtil.removeHtmlTag(content, "script");
content = HtmlUtil.removeHtmlTag(content, "marquee"); content = HtmlUtil.removeHtmlTag(content, "marquee");
// 将单引号替换成下划线
// content = replace(content, "'", "_", false);
// 将双引号替换成下划线
// content = replace(content, "\"", "_", false);
// 滤除脚本事件代码 // 滤除脚本事件代码
for (int i = 0; i < eventKeywords.length; i++) { for (int i = 0; i < eventKeywords.length; i++) {
// 去除相关属性 // 去除相关属性
@ -49,60 +47,33 @@ public class XssUtils {
return content; return content;
} }
/** public static String filterHtmlCode(String content) {
* 将字符串 source 中的 oldStr 替换为 newStr, 并以大小写敏感方式进行查找 String regex = "<pre>[\\s|\\S]+?</pre>";
* // 拿到匹配的pre标签List
* @param source 需要替换的源字符串 List<String> resultFindAll = ReUtil.findAll(regex, content, 0, new ArrayList<>());
* @param oldStr 需要被替换的老字符串 String result = "";
* @param newStr 替换为的新字符串 // size大于0就做替换
*/ if (resultFindAll.size() > 0) {
private static String replace(String source, String oldStr, String newStr) { // 生成一个待替换唯一字符串
return replace(source, oldStr, newStr, true); String preTagReplace = UUID.randomUUID().toString() + System.currentTimeMillis();
} // 判断替换字符串是否唯一
while (ReUtil.findAll(preTagReplace, content, 0, new ArrayList<>()).size() > 0) {
/** preTagReplace = UUID.randomUUID().toString() + System.currentTimeMillis();
* 将字符串 source 中的 oldStr 替换为 newStr, matchCase 为是否设置大小写敏感查找
*
* @param source 需要替换的源字符串
* @param oldStr 需要被替换的老字符串
* @param newStr 替换为的新字符串
* @param matchCase 是否需要按照大小写敏感方式查找
*/
private static String replace(String source, String oldStr, String newStr,boolean matchCase) {
if (StringUtils.isBlank(source)) {
return null;
}
// 首先检查旧字符串是否存在, 不存在就不进行替换
if (!source.toLowerCase().contains(oldStr.toLowerCase())) {
return source;
}
int findStartPos = 0;
int a = 0;
while (a > -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;
} }
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;
} }
} }