支持文章加密

pull/139/head
ruibaby 2019-01-17 22:03:50 +08:00
parent bba2e3a7e0
commit 3818be62e3
7 changed files with 121 additions and 22 deletions

View File

@ -1,7 +1,6 @@
package cc.ryanc.halo.model.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import javax.persistence.*;
@ -130,6 +129,11 @@ public class Post implements Serializable {
*/
private Integer allowComment = 0;
/**
* 访
*/
private String postPassword;
/**
*
*/

View File

@ -149,7 +149,7 @@ public class PostServiceImpl implements PostService {
*/
@Override
public Page<Post> searchPosts(String keyword, String postType, Integer postStatus, Pageable pageable) {
return postRepository.findByPostTypeAndPostStatusAndPostTitleLikeOrPostTypeAndPostStatusAndPostContentLike(
Page<Post> posts = postRepository.findByPostTypeAndPostStatusAndPostTitleLikeOrPostTypeAndPostStatusAndPostContentLike(
postType,
postStatus,
"%" + keyword + "%",
@ -158,6 +158,12 @@ public class PostServiceImpl implements PostService {
"%" + keyword + "%",
pageable
);
for (Post post : posts.getContent()) {
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostSummary("该文章为加密文章");
}
}
return posts;
}
/**
@ -170,7 +176,13 @@ public class PostServiceImpl implements PostService {
*/
@Override
public Page<Post> findPostByStatus(Integer status, String postType, Pageable pageable) {
return postRepository.findPostsByPostStatusAndPostType(status, postType, pageable);
Page<Post> posts = postRepository.findPostsByPostStatusAndPostType(status, postType, pageable);
for (Post post : posts.getContent()) {
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostSummary("该文章为加密文章");
}
}
return posts;
}
/**
@ -182,7 +194,13 @@ public class PostServiceImpl implements PostService {
@Override
@Cacheable(value = POSTS_CACHE_NAME, key = "'posts_page_'+#pageable.pageNumber")
public Page<Post> findPostByStatus(Pageable pageable) {
return postRepository.findPostsByPostStatusAndPostType(PostStatusEnum.PUBLISHED.getCode(), PostTypeEnum.POST_TYPE_POST.getDesc(), pageable);
Page<Post> posts = postRepository.findPostsByPostStatusAndPostType(PostStatusEnum.PUBLISHED.getCode(), PostTypeEnum.POST_TYPE_POST.getDesc(), pageable);
for (Post post : posts.getContent()) {
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostSummary("该文章为加密文章");
}
}
return posts;
}
/**
@ -367,7 +385,13 @@ public class PostServiceImpl implements PostService {
*/
@Override
public Page<Post> findPostByYearAndMonth(String year, String month, Pageable pageable) {
return postRepository.findPostByYearAndMonth(year, month, null);
Page<Post> posts = postRepository.findPostByYearAndMonth(year, month, null);
for (Post post : posts.getContent()) {
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostSummary("该文章为加密文章");
}
}
return posts;
}
/**
@ -381,7 +405,13 @@ public class PostServiceImpl implements PostService {
@Override
@CachePut(value = POSTS_CACHE_NAME, key = "'posts_category_'+#category.cateId+'_'+#pageable.pageNumber")
public Page<Post> findPostByCategories(Category category, Pageable pageable) {
return postRepository.findPostByCategoriesAndPostStatus(category, PostStatusEnum.PUBLISHED.getCode(), pageable);
Page<Post> posts = postRepository.findPostByCategoriesAndPostStatus(category, PostStatusEnum.PUBLISHED.getCode(), pageable);
for (Post post : posts.getContent()) {
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostSummary("该文章为加密文章");
}
}
return posts;
}
/**
@ -395,7 +425,13 @@ public class PostServiceImpl implements PostService {
@Override
@CachePut(value = POSTS_CACHE_NAME, key = "'posts_tag_'+#tag.tagId+'_'+#pageable.pageNumber")
public Page<Post> findPostsByTags(Tag tag, Pageable pageable) {
return postRepository.findPostsByTagsAndPostStatus(tag, PostStatusEnum.PUBLISHED.getCode(), pageable);
Page<Post> posts = postRepository.findPostsByTagsAndPostStatus(tag, PostStatusEnum.PUBLISHED.getCode(), pageable);
for (Post post : posts.getContent()) {
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostSummary("该文章为加密文章");
}
}
return posts;
}
/**

View File

@ -18,6 +18,7 @@ import cc.ryanc.halo.web.controller.core.BaseController;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
@ -120,7 +121,7 @@ public class PostController extends BaseController {
//排序规则
final Sort sort = new Sort(Sort.Direction.DESC, "postId");
final Pageable pageable = PageRequest.of(page, size, sort);
model.addAttribute("posts", postService.searchPosts(keyword,PostTypeEnum.POST_TYPE_POST.getDesc(),PostStatusEnum.PUBLISHED.getCode(),pageable));
model.addAttribute("posts", postService.searchPosts(keyword, PostTypeEnum.POST_TYPE_POST.getDesc(), PostStatusEnum.PUBLISHED.getCode(), pageable));
} catch (Exception e) {
log.error("未知错误:{}", e.getMessage());
}
@ -186,6 +187,9 @@ public class PostController extends BaseController {
post.setUser(user);
post = postService.buildCategoriesAndTags(post, cateList, tagList);
post.setPostUrl(urlFilter(post.getPostUrl()));
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostPassword(SecureUtil.md5(post.getPostPassword()));
}
//当没有选择文章缩略图的时候,自动分配一张内置的缩略图
if (StrUtil.equals(post.getPostThumbnail(), BlogPropertiesEnum.DEFAULT_THUMBNAIL.getProp())) {
post.setPostThumbnail("/static/halo-frontend/images/thumbnail/thumbnail-" + RandomUtil.randomInt(1, 10) + ".jpg");
@ -223,6 +227,9 @@ public class PostController extends BaseController {
post.setPostDate(new Date());
}
post = postService.buildCategoriesAndTags(post, cateList, tagList);
if (StrUtil.isNotEmpty(post.getPostPassword())) {
post.setPostPassword(SecureUtil.md5(post.getPostPassword()));
}
//当没有选择文章缩略图的时候,自动分配一张内置的缩略图
if (StrUtil.equals(post.getPostThumbnail(), BlogPropertiesEnum.DEFAULT_THUMBNAIL.getProp())) {
post.setPostThumbnail("/static/halo-frontend/images/thumbnail/thumbnail-" + RandomUtil.randomInt(1, 10) + ".jpg");

View File

@ -13,19 +13,22 @@ import cc.ryanc.halo.web.controller.core.BaseController;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.servlet.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@ -43,9 +46,9 @@ import java.util.List;
@RequestMapping(value = "/archives")
public class FrontArchiveController extends BaseController {
private static final String POSTS_CACHE_NAME = "posts";
@Autowired
private PostService postService;
@Autowired
private CommentService commentService;
@ -53,7 +56,6 @@ public class FrontArchiveController extends BaseController {
*
*
* @param model model
*
* @return
*/
@GetMapping
@ -66,7 +68,6 @@ public class FrontArchiveController extends BaseController {
*
* @param model model
* @param page page
*
* @return /themes/{theme}/archives
*/
@GetMapping(value = "page/{page}")
@ -91,7 +92,6 @@ public class FrontArchiveController extends BaseController {
* @param model model
* @param year year
* @param month month
*
* @return /themes/{theme}/archives
*/
@GetMapping(value = "{year}/{month}")
@ -112,12 +112,12 @@ public class FrontArchiveController extends BaseController {
*
* @param postUrl
* @param model model
*
* @return /themes/{theme}/post
*/
@GetMapping(value = "{postUrl}")
public String getPost(@PathVariable String postUrl,
@RequestParam(value = "cp", defaultValue = "1") Integer cp,
HttpServletRequest request,
Model model) {
final Post post = postService.findByPostUrl(postUrl, PostTypeEnum.POST_TYPE_POST.getDesc());
if (null == post || !post.getPostStatus().equals(PostStatusEnum.PUBLISHED.getCode())) {
@ -130,12 +130,12 @@ public class FrontArchiveController extends BaseController {
if (null != prePost) {
//兼容老版本主题
model.addAttribute("beforePost", prePost);
model.addAttribute("prePost",prePost);
model.addAttribute("prePost", prePost);
}
if (null != nextPost) {
//兼容老版本主题
model.addAttribute("afterPost", nextPost);
model.addAttribute("nextPost",nextPost);
model.addAttribute("nextPost", nextPost);
}
List<Comment> comments = null;
if (StrUtil.equals(HaloConst.OPTIONS.get(BlogPropertiesEnum.NEW_COMMENT_NEED_CHECK.getProp()), TrueFalseEnum.TRUE.getDesc()) || HaloConst.OPTIONS.get(BlogPropertiesEnum.NEW_COMMENT_NEED_CHECK.getProp()) == null) {
@ -161,12 +161,44 @@ public class FrontArchiveController extends BaseController {
final ListPage<Comment> commentsPage = new ListPage<Comment>(CommentUtil.getComments(comments), cp, size);
final int[] rainbow = PageUtil.rainbow(cp, commentsPage.getTotalPage(), 3);
model.addAttribute("is_post", true);
model.addAttribute("post", post);
model.addAttribute("comments", commentsPage);
model.addAttribute("commentsCount", comments.size());
model.addAttribute("rainbow", rainbow);
model.addAttribute("tagWords", CollUtil.join(tagWords, ","));
postService.cacheViews(post.getPostId());
//判断文章是否有加密
if (StrUtil.isNotEmpty(post.getPostPassword())) {
Cookie cookie = ServletUtil.getCookie(request, "halo-post-password-" + post.getPostId());
if (null == cookie) {
post.setPostSummary("该文章为加密文章");
post.setPostContent("<form id=\"postPasswordForm\" method=\"post\" action=\"/archives/verifyPostPassword\"><p>该文章为加密文章,输入正确的密码即可访问。</p><input type=\"hidden\" id=\"postId\" name=\"postId\" value=\"" + post.getPostId() + "\"> <input type=\"password\" id=\"postPassword\" name=\"postPassword\"> <input type=\"submit\" id=\"passwordSubmit\" value=\"提交\"></form>");
}
}
model.addAttribute("post", post);
return this.render("post");
}
/**
*
*
* @param postId postId
* @param postPassword postPassword
* @param response response
* @return String
*/
@PostMapping(value = "/verifyPostPassword")
@CacheEvict(value = POSTS_CACHE_NAME, allEntries = true, beforeInvocation = true)
public String verifyPostPassword(@RequestParam(value = "postId") Long postId,
@RequestParam(value = "postPassword") String postPassword,
HttpServletResponse response) {
final Post post = postService.findByPostId(postId, PostTypeEnum.POST_TYPE_POST.getDesc());
if (null == post) {
return this.renderNotFound();
}
if (SecureUtil.md5(postPassword).equals(post.getPostPassword())) {
ServletUtil.addCookie(response, "halo-post-password-" + post.getPostId(), SecureUtil.md5(postPassword));
}
return "redirect:/archives/" + post.getPostUrl();
}
}

View File

@ -48,6 +48,11 @@ public class FrontOthersController {
final Pageable pageable = PageRequest.of(0, Integer.parseInt(rssPosts), sort);
final Page<Post> postsPage = postService.findPostByStatus(0, PostTypeEnum.POST_TYPE_POST.getDesc(), pageable);
final List<Post> posts = postsPage.getContent();
for (Post post : posts) {
if(StrUtil.isNotEmpty(post.getPostPassword())){
post.setPostContent("该文章为加密文章");
}
}
return postService.buildRss(posts);
}
@ -64,6 +69,11 @@ public class FrontOthersController {
final Pageable pageable = PageRequest.of(0, 999, sort);
final Page<Post> postsPage = postService.findPostByStatus(0, PostTypeEnum.POST_TYPE_POST.getDesc(), pageable);
final List<Post> posts = postsPage.getContent();
for (Post post : posts) {
if(StrUtil.isNotEmpty(post.getPostPassword())){
post.setPostContent("该文章为加密文章");
}
}
return postService.buildSiteMap(posts);
}
}

View File

@ -67,6 +67,10 @@
<option value="0" <#if (post.allowComment!)==0>selected</#if>><@spring.message code='common.select.no' /></option>
</select>
</div>
<div class="form-group">
<label for="postPassword" class="control-label">文章密码:</label>
<input type="password" class="form-control" id="postPassword" name="postPassword" value="${post.postPassword!}">
</div>
<div class="form-group">
<label for="postDate" class="control-label">发布时间:</label>
<input type="text" class="form-control" id="postDate" name="postDate" value="${post.postDate!?string('yyyy-MM-dd HH:mm')}">
@ -297,7 +301,8 @@
'cateList' : cateList.toString(),
'tagList' : $('#tagList').tagEditor('getTags')[0].tags.toString(),
'allowComment' : $('#allowComment').val(),
'postDate' : $("#postDate").val()
'postDate' : $("#postDate").val(),
'postPassword' : $("#postPassword").val()
},function (data) {
if(data.code === 1){
//清除自动保存的内容

View File

@ -65,6 +65,10 @@
<option value="0"><@spring.message code='common.select.no' /></option>
</select>
</div>
<div class="form-group">
<label for="postPassword" class="control-label">文章密码:</label>
<input type="password" class="form-control" id="postPassword" name="postPassword">
</div>
</div>
<div class="box-footer">
<button onclick="push(1)" class="btn btn-default btn-sm "><@spring.message code='admin.editor.save-draft' /></button>
@ -273,7 +277,8 @@
'postThumbnail': $('#selectImg').attr('src'),
'cateList' : cateList.toString(),
'tagList' : $('#tagList').tagEditor('getTags')[0].tags.toString(),
'allowComment' : $('#allowComment').val()
'allowComment' : $('#allowComment').val(),
'postPassword' : $("#postPassword").val()
},function (data) {
if(data.code === 1){
//清除自动保存的内容