diff --git a/src/main/java/net/mingsoft/cms/action/CategoryAction.java b/src/main/java/net/mingsoft/cms/action/CategoryAction.java index 1c69404c..8dfe6017 100755 --- a/src/main/java/net/mingsoft/cms/action/CategoryAction.java +++ b/src/main/java/net/mingsoft/cms/action/CategoryAction.java @@ -86,6 +86,7 @@ public class CategoryAction extends BaseAction { }) @RequestMapping(value="/list",method = {RequestMethod.GET, RequestMethod.POST}) @ResponseBody + @RequiresPermissions("cms:category:view") public ResultData list(@ModelAttribute @ApiIgnore CategoryEntity category) { BasicUtil.startPage(); List categoryList = categoryBiz.query(category); @@ -110,6 +111,7 @@ public class CategoryAction extends BaseAction { @ApiOperation(value = "获取分类列表接口") @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query") @GetMapping("/get") + @RequiresPermissions("cms:category:view") @ResponseBody public ResultData get(@ModelAttribute @ApiIgnore CategoryEntity category){ if(category.getId()==null) { diff --git a/src/main/java/net/mingsoft/cms/action/ContentAction.java b/src/main/java/net/mingsoft/cms/action/ContentAction.java index b456ca6f..8b9fc51f 100755 --- a/src/main/java/net/mingsoft/cms/action/ContentAction.java +++ b/src/main/java/net/mingsoft/cms/action/ContentAction.java @@ -31,6 +31,7 @@ import net.mingsoft.basic.annotation.LogAnn; import net.mingsoft.basic.bean.EUListBean; import net.mingsoft.basic.constant.e.BusinessTypeEnum; import net.mingsoft.basic.util.BasicUtil; +import net.mingsoft.basic.util.SqlInjectionUtil; import net.mingsoft.basic.util.StringUtil; import net.mingsoft.cms.bean.ContentBean; import net.mingsoft.cms.biz.ICategoryBiz; @@ -113,7 +114,10 @@ public class ContentAction extends BaseAction { }) @PostMapping("/list") @ResponseBody + @RequiresPermissions("cms:content:view") public ResultData list(@ModelAttribute @ApiIgnore ContentBean content) { + // 检查SQL注入 + SqlInjectionUtil.filterContent(content.getCategoryId()); BasicUtil.startPage(); List contentList = contentBiz.query(content); return ResultData.build().success(new EUListBean(contentList,(int) BasicUtil.endPage(contentList).getTotal())); @@ -136,6 +140,7 @@ public class ContentAction extends BaseAction { @ApiImplicitParam(name = "id", value = "编号", required =true,paramType="query") @GetMapping("/get") @ResponseBody + @RequiresPermissions("cms:content:view") public ResultData get(@ModelAttribute @ApiIgnore ContentEntity content){ if(content.getId()==null) { return ResultData.build().error(); diff --git a/src/main/java/net/mingsoft/cms/action/web/MCmsAction.java b/src/main/java/net/mingsoft/cms/action/web/MCmsAction.java index b796825d..ee35ebb7 100755 --- a/src/main/java/net/mingsoft/cms/action/web/MCmsAction.java +++ b/src/main/java/net/mingsoft/cms/action/web/MCmsAction.java @@ -26,6 +26,7 @@ package net.mingsoft.cms.action.web; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.PageUtil; +import com.alibaba.fastjson.JSON; import freemarker.core.ParseException; import freemarker.template.MalformedTemplateNameException; import freemarker.template.TemplateNotFoundException; @@ -541,12 +542,12 @@ public class MCmsAction extends net.mingsoft.cms.action.BaseAction { /** * 存储自定义模型字段和接口参数 * - * @author 铭飞开源团队 + * @author 铭软开源团队 * @date 2019年3月5日 */ class DiyModelMap { - String key; - Object value; + private String key; + private Object value; public String getKey() { return key; @@ -563,6 +564,11 @@ public class MCmsAction extends net.mingsoft.cms.action.BaseAction { public void setValue(Object value) { this.value = value; } + + @Override + public String toString() { + return JSON.toJSONString(this); + } } } diff --git a/src/main/java/net/mingsoft/cms/aop/CategoryAop.java b/src/main/java/net/mingsoft/cms/aop/CategoryAop.java new file mode 100644 index 00000000..81d359d8 --- /dev/null +++ b/src/main/java/net/mingsoft/cms/aop/CategoryAop.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2012-2022 铭软科技(mingsoft.net) + * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有 + * 遵循铭软科技《保密协议》 + */ + +package net.mingsoft.cms.aop; + +import cn.hutool.core.io.FileUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import net.mingsoft.basic.util.BasicUtil; +import net.mingsoft.cms.entity.CategoryEntity; +import net.mingsoft.mdiy.biz.IDictBiz; +import net.mingsoft.mdiy.entity.DictEntity; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.After; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.util.List; +import java.util.stream.Collectors; + + +/** + * 增加移动审批权限 + */ + +@Aspect +@Component("CategoryAop") +public class CategoryAop extends net.mingsoft.basic.aop.BaseAop { + + + @Value("${ms.diy.html-dir:html}") + private String htmlDir; + + + @Pointcut("execution(* net.mingsoft.cms.action.CategoryAction.delete(..)) ") + public void delete() { + } + + /** + * 删除栏目后并删除文章对应的静态化文件 + * + * @param jp + */ + @After("delete()") + public void delete(JoinPoint jp) { + List categoryEntities = (List) getJsonParam(jp); + for (CategoryEntity categoryEntity : categoryEntities) { + // 删除静态文件 + deleteCategoryHtml(categoryEntity.getCategoryPath()); + } + } + + + /** + * @param categoryPath 栏目目录 + * 删除栏目静态文件 + */ + public void deleteCategoryHtml(String categoryPath) { + // html真实路径 + String htmlPath = BasicUtil.getRealPath(htmlDir); + // appDir + String appDir = BasicUtil.getApp().getAppDir(); + // 删除静态文件 + // 文件夹路径组成 html真实路径 + appdir + 栏目路径 + boolean flag = FileUtil.del(htmlPath + + File.separator + appDir + + categoryPath + ); + if (flag) { + LOG.info("删除静态文件夹成功!"); + } else { + LOG.info("删除失败!"); + } + } + +} diff --git a/src/main/java/net/mingsoft/cms/aop/ContentAop.java b/src/main/java/net/mingsoft/cms/aop/ContentAop.java index 6359c3bb..afb4cfa5 100755 --- a/src/main/java/net/mingsoft/cms/aop/ContentAop.java +++ b/src/main/java/net/mingsoft/cms/aop/ContentAop.java @@ -7,10 +7,10 @@ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: - + *

* The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. - + *

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR @@ -22,20 +22,33 @@ package net.mingsoft.cms.aop; +import cn.hutool.core.io.FileUtil; import net.mingsoft.basic.aop.BaseAop; import net.mingsoft.basic.util.BasicUtil; +import net.mingsoft.cms.biz.ICategoryBiz; import net.mingsoft.cms.biz.IContentBiz; import net.mingsoft.cms.biz.IHistoryLogBiz; +import net.mingsoft.cms.entity.CategoryEntity; import net.mingsoft.cms.entity.ContentEntity; import net.mingsoft.cms.entity.HistoryLogEntity; +import net.mingsoft.mdiy.util.ParserUtil; import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.io.File; +import java.util.ArrayList; import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author 铭飞开源团队 @@ -45,18 +58,25 @@ import java.util.Date; @Aspect public class ContentAop extends BaseAop { + /** * 注入文章业务 */ @Autowired private IContentBiz contentBiz; + @Autowired + private ICategoryBiz categoryBiz; + /** * 注入浏览记录业务 */ @Autowired private IHistoryLogBiz historyLogBiz; + @Value("${ms.diy.html-dir:html}") + private String htmlDir; + /** * 文章浏览记录, * 如果该文章该ip已经记录过,则不在重复记录 @@ -65,17 +85,17 @@ public class ContentAop extends BaseAop { * @throws Throwable */ @Around("execution(* net.mingsoft.cms.action.web.ContentAction.get(..))") - public Object get(ProceedingJoinPoint pjp) throws Throwable{ + public Object get(ProceedingJoinPoint pjp) throws Throwable { // 获取方法参数 ContentEntity content = getType(pjp, ContentEntity.class); // 如果id为空则直接发行 - if(content.getId()==null) { + if (content.getId() == null) { return pjp.proceed(); } content = contentBiz.getById(content.getId()); //如果文章不存在则直接发行 - if(content == null){ + if (content == null) { return pjp.proceed(); } @@ -84,23 +104,80 @@ public class ContentAop extends BaseAop { historyLog.setContentId(content.getId()); historyLog.setHlIp(BasicUtil.getIp()); historyLog.setHlIsMobile(BasicUtil.isMobileDevice()); - HistoryLogEntity _historyLog = (HistoryLogEntity)historyLogBiz.getEntity(historyLog); + HistoryLogEntity _historyLog = (HistoryLogEntity) historyLogBiz.getEntity(historyLog); //如果该ip该文章没有浏览记录则保存浏览记录 //并且更新点击数 - if(_historyLog == null || StringUtils.isBlank(_historyLog.getId())){ + if (_historyLog == null || StringUtils.isBlank(_historyLog.getId())) { historyLog.setCreateDate(new Date()); historyLogBiz.saveEntity(historyLog); //更新点击数 ContentEntity updateContent = new ContentEntity(); updateContent.setId(content.getId()); - if(content.getContentHit() == null){ + if (content.getContentHit() == null) { updateContent.setContentHit(1); - }else{ - updateContent.setContentHit(content.getContentHit()+1); + } else { + updateContent.setContentHit(content.getContentHit() + 1); } contentBiz.updateEntity(updateContent); } return pjp.proceed(); } + + + @Pointcut("execution(* net.mingsoft.cms.action.ContentAction.delete(..))") + public void delete() { + } + + /** + * 删除文章后并删除文章对应的静态化文件 + * @param jp + */ + @After("delete()") + public void delete(JoinPoint jp) { + List contents = (List) getJsonParam(jp); + + // 获取栏目ID对应文章ID数组 map + Map> categoryIdByContentIds = contents.stream() + .collect(Collectors.groupingBy(ContentEntity::getCategoryId, Collectors.mapping(ContentEntity::getId, Collectors.toList()))); + List categoryIds = new ArrayList<>(categoryIdByContentIds.keySet()); + // 考虑到在全部中删除文章 栏目不同 + for (String categoryId : categoryIds) { + // 获取栏目 + CategoryEntity category = categoryBiz.getById(categoryId); + // 获取栏目路径 + String categoryPath = category.getCategoryPath(); + for (String contentId : categoryIdByContentIds.get(categoryId)) { + // 删除静态文件 + deleteHtml(categoryPath, contentId); + } + } + } + + + /** + * @param categoryPath 栏目目录 + * @param contentId 文章ID + * 根据文章实体删除静态文件 + */ + private void deleteHtml(String categoryPath, String contentId) { + // html真实路径 + String htmlPath = BasicUtil.getRealPath(htmlDir); + // appDir + String appDir = BasicUtil.getApp().getAppDir(); + + // 删除静态文件 + // 文件路径组成 html真实路径 + appdir + 栏目路径 + 文章ID + .html + boolean flag = FileUtil.del(htmlPath + + File.separator + appDir + + categoryPath + + File.separator + contentId + + ParserUtil.HTML_SUFFIX); + if (flag) { + LOG.info("删除静态文件成功!"); + } else { + LOG.info("删除失败!"); + } + + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0615c7ab..7fc942a1 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -12,6 +12,7 @@ logging: config: classpath:log4j-spring.xml ms: + shiro-key: 4AvVhmFLUs0KTA3Kprsdag== #生产必须修改此值否则会存在安全风险,可以通过 https://base64.us/随机生产一个Base64值 html-dir: html rand-code: @@ -23,7 +24,10 @@ ms: manager: path: /ms #后台访问的路径,如:http://项目/ms/login.do,生产的时候建议修改 check-code: true #默认开启验证码验证,false验证码不验证 - + xss: + xssEnable: true #xss过滤器的开关 + filterUrl: /** #过滤的url,多个用逗号分开 + excludeUrl: /ms**,/static**,/template**,/file/upload.do #排除的url,多个用逗号分开 upload: enable-web: true #启用web层的上传 template: template #模板文件夹支持重命名,不支持路径