👽 代码优化

pull/18/head
ruibaby 2018-05-30 18:17:34 +08:00
parent 42e37e95f3
commit a1e7d80cc8
17 changed files with 44 additions and 470 deletions

12
pom.xml
View File

@ -131,18 +131,6 @@
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>

View File

@ -1,33 +0,0 @@
package cc.ryanc.halo.config;
import cc.ryanc.halo.security.XssFilter;
import com.google.common.collect.Maps;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* @author : RYAN0UP
* @version : 1.0
* @date : 2018/5/4
*/
@Configuration
public class XssConfig {
@Bean
public FilterRegistrationBean xssFilterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new XssFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.setEnabled(true);
filterRegistrationBean.addUrlPatterns("/*");
Map<String, String> initParameters = Maps.newHashMap();
//后台不做拦截请求
initParameters.put("excludes", "/admin/*");
initParameters.put("isIncludeRichText", "true");
filterRegistrationBean.setInitParameters(initParameters);
return filterRegistrationBean;
}
}

View File

@ -1,32 +0,0 @@
package cc.ryanc.halo.security;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.safety.Whitelist;
/**
* @author : RYAN0UP
* @version : 1.0
* @date : 2018/5/4
*/
public class JsoupUtil {
/**
*
*/
private static final Whitelist whitelist = Whitelist.basicWithImages();
private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
static {
whitelist.addAttributes(":all", "style");
}
public static String clean(String content) {
if (StringUtils.isNotBlank(content)) {
content = content.trim();
}
return Jsoup.clean(content, "", whitelist, outputSettings);
}
}

View File

@ -1,77 +0,0 @@
package cc.ryanc.halo.security;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author : RYAN0UP
* @version : 1.0
* @date : 2018/5/4
*/
public class XssFilter implements Filter {
/**
*
*/
private static boolean IS_INCLUDE_RICH_TEXT = false;
private List<String> excludes = new ArrayList<>();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp)) {
filterChain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request, IS_INCLUDE_RICH_TEXT);
filterChain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
if (excludes == null || excludes.isEmpty()) {
return false;
}
String url = request.getServletPath();
for (String pattern : excludes) {
Pattern p = Pattern.compile("^" + pattern);
Matcher m = p.matcher(url);
if (m.find()) {
return true;
}
}
return false;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String isIncludeRichText = filterConfig.getInitParameter("isIncludeRichText");
if (StringUtils.isNotBlank(isIncludeRichText)) {
IS_INCLUDE_RICH_TEXT = BooleanUtils.toBoolean(isIncludeRichText);
}
String temp = filterConfig.getInitParameter("excludes");
if (temp != null) {
String[] url = temp.split(",");
for (int i = 0; url != null && i < url.length; i++) {
excludes.add(url[i]);
}
}
}
@Override
public void destroy() {
}
}

View File

@ -1,81 +0,0 @@
package cc.ryanc.halo.security;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* @author : RYAN0UP
* @version : 1.0
* @date : 2018/5/4
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
HttpServletRequest orgRequest = null;
private boolean isIncludeRichText = false;
public XssHttpServletRequestWrapper(HttpServletRequest request, boolean isIncludeRichText) {
super(request);
orgRequest = request;
this.isIncludeRichText = isIncludeRichText;
}
/**
* request
*
* @param req req
* @return HttpServletRequest
*/
public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
if (req instanceof XssHttpServletRequestWrapper) {
return ((XssHttpServletRequestWrapper) req).getOrgRequest();
}
return req;
}
@Override
public String getParameter(String name) {
Boolean flag = ("content".equals(name) || name.endsWith("WithHtml"));
if (flag && !isIncludeRichText) {
return super.getParameter(name);
}
name = JsoupUtil.clean(name);
String value = super.getParameter(name);
if (StringUtils.isNotBlank(value)) {
value = JsoupUtil.clean(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] arr = super.getParameterValues(name);
if (arr != null) {
for (int i = 0; i < arr.length; i++) {
arr[i] = JsoupUtil.clean(arr[i]);
}
}
return arr;
}
@Override
public String getHeader(String name) {
name = JsoupUtil.clean(name);
String value = super.getHeader(name);
if (StringUtils.isNotBlank(value)) {
value = JsoupUtil.clean(value);
}
return value;
}
/**
* request
*
* @return HttpServletRequest
*/
public HttpServletRequest getOrgRequest() {
return orgRequest;
}
}

View File

@ -196,40 +196,6 @@ public class HaloUtils {
return null;
}
/**
*
*
* @param fileName fileName
* @return true or false
*/
public static boolean removeFile(String fileName){
File file = new File(fileName);
if(file.exists() && file.delete()){
return true;
}
return false;
}
/**
*
*
* @param dir dir
* @return boolean
*/
public static boolean removeDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i=0; i<children.length; i++) {
boolean success = removeDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// 目录此时为空,可以删除
return dir.delete();
}
/**
*
*

View File

@ -1,167 +0,0 @@
package cc.ryanc.halo.utils;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* @author : RYAN0UP
* @version : 1.0
* @date : 2018/5/11
* Zip
*/
@Slf4j
public class ZipUtils {
/**
* Zip
*
* @param zipFilePath
* @param descDir
*/
public static void unZip(String zipFilePath,String descDir){
File zipFile=new File(zipFilePath);
File pathFile=new File(descDir);
if(!pathFile.exists()){
pathFile.mkdirs();
}
ZipFile zip=null;
InputStream in=null;
OutputStream out=null;
try {
zip=new ZipFile(zipFile);
Enumeration<?> entries=zip.entries();
while(entries.hasMoreElements()){
ZipEntry entry=(ZipEntry) entries.nextElement();
String zipEntryName=entry.getName();
in=zip.getInputStream(entry);
String outPath=(descDir+"/"+zipEntryName).replace("\\*", "/");
File file=new File(outPath.substring(0, outPath.lastIndexOf('/')));
if(!file.exists()){
file.mkdirs();
}
if(new File(outPath).isDirectory()){
continue;
}
out=new FileOutputStream(outPath);
byte[] buf=new byte[4*1024];
int len;
while((len=in.read(buf))>=0){
out.write(buf, 0, len);
}
in.close();
}
} catch (Exception e) {
log.error("解压失败:{0}",e.getMessage());
}finally{
try {
if(zip!=null)
zip.close();
if(in!=null)
in.close();
if(out!=null)
out.close();
} catch (IOException e) {
log.error("未知错误:{0}",e.getMessage());
}
}
}
/**
*
* https://github.com/otale/tale/blob/master/src/main/java/com/tale/utils/ZipUtils.java
*
* @param srcFolder
* @param destZipFile
* @throws Exception
*/
public static void zipFolder(String srcFolder, String destZipFile) throws Exception {
ZipOutputStream zip = null;
FileOutputStream fileWriter = null;
fileWriter = new FileOutputStream(destZipFile);
zip = new ZipOutputStream(fileWriter);
addFolderToZip("", srcFolder, zip);
zip.flush();
zip.close();
}
/**
*
* https://github.com/otale/tale/blob/master/src/main/java/com/tale/utils/ZipUtils.java
*
* @param filePath
* @param zipPath
* @throws Exception
*/
public static void zipFile(String filePath, String zipPath) throws Exception{
byte[] buffer = new byte[1024];
FileOutputStream fos = new FileOutputStream(zipPath);
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze= new ZipEntry("spy.log");
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream(filePath);
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
in.close();
zos.closeEntry();
//remember close it
zos.close();
}
/**
* Zip
* https://github.com/otale/tale/blob/master/src/main/java/com/tale/utils/ZipUtils.java
*
* @param path path
* @param srcFile srcFile
* @param zip zip
* @throws Exception
*/
public static void addFileToZip(String path, String srcFile, ZipOutputStream zip)
throws Exception {
File folder = new File(srcFile);
if (folder.isDirectory()) {
addFolderToZip(path, srcFile, zip);
} else {
byte[] buf = new byte[1024];
int len;
FileInputStream in = new FileInputStream(srcFile);
zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
while ((len = in.read(buf)) > 0) {
zip.write(buf, 0, len);
}
}
}
/**
* zip
* https://github.com/otale/tale/blob/master/src/main/java/com/tale/utils/ZipUtils.java
*
* @param path path
* @param srcFolder srcFolder
* @param zip zip
* @throws Exception
*/
public static void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws Exception {
File folder = new File(srcFolder);
if (null != path && folder.isDirectory()) {
for (String fileName : folder.list()) {
if ("".equals(path)) {
addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip);
} else {
addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip);
}
}
}
}
}

View File

@ -12,6 +12,7 @@ import cc.ryanc.halo.service.PostService;
import cc.ryanc.halo.service.UserService;
import cc.ryanc.halo.utils.HaloUtils;
import cc.ryanc.halo.web.controller.core.BaseController;
import cn.hutool.core.lang.Validator;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@ -28,8 +29,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author : RYAN0UP
@ -126,10 +125,7 @@ public class AdminController extends BaseController {
if (StringUtils.equals(aUser.getLoginEnable(), "false")) {
status = "disable";
} else {
//验证是否是邮箱登录
Pattern patternEmail = Pattern.compile("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}");
Matcher matcher = patternEmail.matcher(loginName);
if (matcher.find()) {
if (Validator.isEmail(loginName)) {
user = userService.userLoginByEmail(loginName, SecureUtil.md5(loginPwd)).get(0);
} else {
user = userService.userLoginByName(loginName, SecureUtil.md5(loginPwd)).get(0);

View File

@ -10,6 +10,7 @@ import cc.ryanc.halo.service.PostService;
import cc.ryanc.halo.service.UserService;
import cc.ryanc.halo.utils.HaloUtils;
import cc.ryanc.halo.web.controller.core.BaseController;
import cn.hutool.core.lang.Validator;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@ -31,8 +32,6 @@ import javax.websocket.server.PathParam;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author : RYAN0UP
@ -110,18 +109,16 @@ public class CommentController extends BaseController{
*/
@GetMapping("/revert")
public String moveToPublish(@PathParam("commentId") Long commentId,
@PathParam("status") Integer status){
@PathParam("status") Integer status,
HttpSession session){
Comment comment = commentService.updateCommentStatus(commentId,0);
Post post = comment.getPost();
//判断评论者的邮箱是否符合规则
Pattern patternEmail = Pattern.compile("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}");
Matcher matcher = patternEmail.matcher(comment.getCommentAuthorEmail());
User user = (User) session.getAttribute(HaloConst.USER_SESSION_KEY);
//判断是否启用邮件服务
if(StringUtils.equals(HaloConst.OPTIONS.get("smtp_email_enable"),"true") && StringUtils.equals(HaloConst.OPTIONS.get("comment_pass_notice"),"true")) {
try {
if (status == 1 && matcher.find()) {
if (status == 1 && Validator.isEmail(comment.getCommentAuthorEmail())) {
Map<String, Object> map = new HashMap<>();
if (StringUtils.equals(post.getPostType(), HaloConst.POST_TYPE_POST)) {
map.put("pageUrl", HaloConst.OPTIONS.get("blog_url") + "/archives/" + post.getPostUrl() + "#comment-id-" + comment.getCommentId());
@ -132,7 +129,7 @@ public class CommentController extends BaseController{
map.put("commentContent", comment.getCommentContent());
map.put("blogUrl", HaloConst.OPTIONS.get("blog_url"));
map.put("blogTitle", HaloConst.OPTIONS.get("blog_title"));
map.put("author", userService.findUser().getUserDisplayName());
map.put("author", user.getUserDisplayName());
mailService.sendTemplateMail(
comment.getCommentAuthorEmail(),
"您在" + HaloConst.OPTIONS.get("blog_title") + "的评论已审核通过!", map, "common/mail/mail_passed.ftl");
@ -198,7 +195,7 @@ public class CommentController extends BaseController{
comment.setCommentAuthorEmail(user.getUserEmail());
comment.setCommentAuthorUrl(HaloConst.OPTIONS.get("blog_url"));
comment.setCommentAuthorIp(HaloUtils.getIpAddr(request));
comment.setCommentAuthorAvatarMd5(SecureUtil.md5(userService.findUser().getUserEmail()));
comment.setCommentAuthorAvatarMd5(SecureUtil.md5(user.getUserEmail()));
comment.setCommentDate(new Date());
String lastContent = " //<a href='#comment-id-"+lastComment.getCommentId()+"'>@"+lastComment.getCommentAuthor()+"</a>:"+lastComment.getCommentContent();
comment.setCommentContent(commentContent+lastContent);
@ -208,13 +205,9 @@ public class CommentController extends BaseController{
comment.setIsAdmin(1);
commentService.saveByComment(comment);
//正则表达式判断对方的邮箱是否是正确的格式
Pattern patternEmail = Pattern.compile("\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}");
Matcher matcher = patternEmail.matcher(lastComment.getCommentAuthorEmail());
//邮件通知
if(StringUtils.equals(HaloConst.OPTIONS.get("smtp_email_enable"),"true") && StringUtils.equals(HaloConst.OPTIONS.get("comment_reply_notice"),"true")) {
if(matcher.find()){
if(Validator.isEmail(lastComment.getCommentAuthorEmail())){
Map<String, Object> map = new HashMap<>();
map.put("blogTitle",HaloConst.OPTIONS.get("blog_title"));
map.put("commentAuthor",lastComment.getCommentAuthor());

View File

@ -11,7 +11,6 @@ import cc.ryanc.halo.service.TagService;
import cc.ryanc.halo.utils.HaloUtils;
import cc.ryanc.halo.web.controller.core.BaseController;
import cn.hutool.http.HtmlUtil;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

View File

@ -7,8 +7,9 @@ import cc.ryanc.halo.model.dto.LogsRecord;
import cc.ryanc.halo.service.LogsService;
import cc.ryanc.halo.service.OptionsService;
import cc.ryanc.halo.utils.HaloUtils;
import cc.ryanc.halo.utils.ZipUtils;
import cc.ryanc.halo.web.controller.core.BaseController;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -106,8 +107,8 @@ public class ThemeController extends BaseController {
logsService.saveByLogs(
new Logs(LogsRecord.UPLOAD_THEME, file.getOriginalFilename(), HaloUtils.getIpAddr(request), new Date())
);
ZipUtils.unZip(themePath.getAbsolutePath(), new File(basePath.getAbsolutePath(), "templates/themes/").getAbsolutePath());
HaloUtils.removeFile(themePath.getAbsolutePath());
ZipUtil.unzip(themePath,new File(basePath.getAbsolutePath(), "templates/themes/"));
FileUtil.del(themePath);
HaloConst.THEMES.clear();
HaloConst.THEMES = HaloUtils.getThemes();
} else {
@ -132,7 +133,7 @@ public class ThemeController extends BaseController {
try {
File basePath = new File(ResourceUtils.getURL("classpath:").getPath());
File themePath = new File(basePath.getAbsolutePath(), "templates/themes/" + themeName);
HaloUtils.removeDir(themePath);
FileUtil.del(themePath);
HaloConst.THEMES.clear();
HaloConst.THEMES = HaloUtils.getThemes();
} catch (Exception e) {

View File

@ -10,6 +10,7 @@ import cc.ryanc.halo.service.PostService;
import cc.ryanc.halo.service.UserService;
import cc.ryanc.halo.utils.HaloUtils;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HtmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -98,15 +99,19 @@ public class FrontCommentController {
try{
Comment lastComment = null;
post = postService.findByPostId(post.getPostId()).get();
comment.setCommentAuthorEmail(comment.getCommentAuthorEmail().toLowerCase());
comment.setCommentAuthorEmail(HtmlUtil.encode(comment.getCommentAuthorEmail()).toLowerCase());
comment.setPost(post);
comment.setCommentDate(new Date());
comment.setCommentAuthorIp(HaloUtils.getIpAddr(request));
comment.setIsAdmin(0);
comment.setCommentAuthor(HtmlUtil.encode(comment.getCommentAuthor()));
if(comment.getCommentParent()>0){
lastComment = commentService.findCommentById(comment.getCommentParent()).get();
String lastContent = " //<a href='#comment-id-"+lastComment.getCommentId()+"'>@"+lastComment.getCommentAuthor()+"</a>:"+lastComment.getCommentContent();
comment.setCommentContent(StringUtils.substringAfter(comment.getCommentContent(),":")+lastContent);
comment.setCommentContent(StringUtils.substringAfter(HtmlUtil.encode(comment.getCommentContent()),":")+lastContent);
}else{
//将评论内容的字符专为安全字符
comment.setCommentContent(HtmlUtil.encode(comment.getCommentContent()));
}
if(StringUtils.isNotEmpty(comment.getCommentAuthorUrl())){
comment.setCommentAuthorUrl(URLUtil.formatUrl(comment.getCommentAuthorUrl()));

View File

@ -62,7 +62,7 @@
<#switch comment.commentStatus>
<#case 0>
<button class="btn btn-primary btn-xs " onclick="replyShow('${comment.commentId?c}','${comment.post.postId?c}')" <#if comment.isAdmin==1>disabled</#if>>回复</button>
<button class="btn btn-danger btn-xs " onclick="modelShow('/admin/comments/throw?commentId=${comment.commentId?c}&status=1','确定移动到回收站?')">丢弃</button>
<button class="btn btn-danger btn-xs " onclick="modelShow('/admin/comments/throw?commentId=${comment.commentId?c}&status=0','确定移动到回收站?')">丢弃</button>
<#break >
<#case 1>
<a data-pjax="true" class="btn btn-primary btn-xs " href="/admin/comments/revert?commentId=${comment.commentId?c}&status=1">通过</a>

View File

@ -29,7 +29,7 @@
<p>一款使用Java开发的简约&quot;轻&quot;,快的博客系统。</p>
<p>非常感谢你使用Halo进行创作。</p>
</blockquote>
<p>目前该博客系统为beta测试版有可能会出现一些莫名奇妙的bug所以希望各位在使用过程中及时向我反馈:</p>
<p>如果在使用过程中出现bug或者无法解决的问题希望各位在使用过程中及时向我反馈:</p>
<p>Github issues <a href='https://github.com/ruibaby/halo' target="_blank">https://github.com/ruibaby/halo</a></p>
<p>Blog : <a href="https://ryanc.cc" target="_blank">https://ryanc.cc</a> </p>
<p>Email : <a href='mailto:i@ryanc.cc'>i@ryanc.cc</a></p>

View File

@ -52,17 +52,32 @@
首页
<#break >
<#case "post.ftl">
文章内容
文章页面
<#break >
<#case "archives.ftl">
文章归档
文章归档页面
<#break >
<#case "links.ftl">
友情链接
友情链接页面
<#break >
<#case "module/macro.ftl">
宏模板
<#break >
<#case "tag.ftl">
单个标签页面
<#break >
<#case "tags.ftl">
标签列表页面
<#break>
<#case "category.ftl">
单个分类页面
<#break >
<#case "page.ftl">
自定义页面
<#break>
<#case "gallery.ftl">
图库页面
<#break>
</#switch>
</td>
</tr>

View File

@ -146,6 +146,7 @@
dropZoneTitle: '拖拽主题压缩包到这里 &hellip;<br>不支持多个主题同时上传',
showClose: false
}).on("fileuploaded",function (event,data,previewId,index) {
var data = data.jqXHR.responseJSON;
if(data.code==1){
$("#uploadForm").hide(400);
$.toast({

View File

@ -12,6 +12,6 @@ public class DemoUtilTest {
@Test
public void testZip(){
ZipUtils.unZip("/Users/ryan0up/Desktop/adminlog.html.zip","/Users/ryan0up/Desktop/");
//ZipUtils.unZip("/Users/ryan0up/Desktop/adminlog.html.zip","/Users/ryan0up/Desktop/");
}
}