From 9f169d9cf2da8b110e21ba80655800e1187e5a1b Mon Sep 17 00:00:00 2001 From: linhaojun Date: Sat, 17 Sep 2022 17:58:34 +0800 Subject: [PATCH 01/16] =?UTF-8?q?:art:=20=E9=87=8D=E6=9E=84=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/aurora/aspect/OperationLogAspect.java | 4 +- .../java/com/aurora/constant/CommonConst.java | 5 + .../com/aurora/constant/RedisPrefixConst.java | 39 +------ ...UserDetailDTO.java => UserDetailsDTO.java} | 13 ++- .../filter/JwtAuthenticationTokenFilter.java | 49 ++------- .../handler/AccessDecisionManagerImpl.java | 3 +- .../AuthenticationSuccessHandlerImpl.java | 27 +++-- .../java/com/aurora/service/TokenService.java | 23 ++++ .../service/impl/ArticleServiceImpl.java | 2 +- .../service/impl/CommentServiceImpl.java | 2 +- .../aurora/service/impl/MenuServiceImpl.java | 2 +- .../aurora/service/impl/TalkServiceImpl.java | 2 +- .../aurora/service/impl/TokenServiceImpl.java | 100 ++++++++++++++++++ .../service/impl/UserAuthServiceImpl.java | 22 +--- .../service/impl/UserDetailServiceImpl.java | 10 +- .../service/impl/UserInfoServiceImpl.java | 26 +++-- .../impl/AbstractSocialLoginStrategyImpl.java | 33 +++--- .../main/java/com/aurora/utils/JwtUtils.java | 92 ---------------- .../main/java/com/aurora/utils/UserUtils.java | 15 +-- 19 files changed, 221 insertions(+), 248 deletions(-) rename aurora-springboot/src/main/java/com/aurora/dto/{UserDetailDTO.java => UserDetailsDTO.java} (90%) create mode 100644 aurora-springboot/src/main/java/com/aurora/service/TokenService.java create mode 100644 aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java delete mode 100644 aurora-springboot/src/main/java/com/aurora/utils/JwtUtils.java diff --git a/aurora-springboot/src/main/java/com/aurora/aspect/OperationLogAspect.java b/aurora-springboot/src/main/java/com/aurora/aspect/OperationLogAspect.java index 445a12c..e19d11c 100644 --- a/aurora-springboot/src/main/java/com/aurora/aspect/OperationLogAspect.java +++ b/aurora-springboot/src/main/java/com/aurora/aspect/OperationLogAspect.java @@ -84,9 +84,9 @@ public class OperationLogAspect { // 返回结果 operationLog.setResponseData(JSON.toJSONString(keys)); // 请求用户ID - operationLog.setUserId(UserUtils.getLoginUser().getId()); + operationLog.setUserId(UserUtils.getUserDetailsDTO().getId()); // 请求用户 - operationLog.setNickname(UserUtils.getLoginUser().getNickname()); + operationLog.setNickname(UserUtils.getUserDetailsDTO().getNickname()); // 请求IP String ipAddress = IpUtils.getIpAddress(request); operationLog.setIpAddress(ipAddress); diff --git a/aurora-springboot/src/main/java/com/aurora/constant/CommonConst.java b/aurora-springboot/src/main/java/com/aurora/constant/CommonConst.java index e04d938..7de076c 100644 --- a/aurora-springboot/src/main/java/com/aurora/constant/CommonConst.java +++ b/aurora-springboot/src/main/java/com/aurora/constant/CommonConst.java @@ -104,4 +104,9 @@ public class CommonConst { */ public static final Integer DEFAULT_ABOUT_ID = 1; + /** + * 20分钟 + */ + public final static Integer TWENTY_MINUTES = 20; + } diff --git a/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java b/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java index fdc3fd8..1a73f35 100644 --- a/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java +++ b/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java @@ -26,36 +26,6 @@ public class RedisPrefixConst { */ public static final String ARTICLE_VIEWS_COUNT = "article_views_count"; - /** - * 文章点赞量 - */ - public static final String ARTICLE_LIKE_COUNT = "article_like_count"; - - /** - * 用户点赞文章 - */ - public static final String ARTICLE_USER_LIKE = "article_user_like:"; - - /** - * 说说点赞量 - */ - public static final String TALK_LIKE_COUNT = "talk_like_count"; - - /** - * 用户点赞说说 - */ - public static final String TALK_USER_LIKE = "talk_user_like:"; - - /** - * 评论点赞量 - */ - public static final String COMMENT_LIKE_COUNT = "comment_like_count"; - - /** - * 用户点赞评论 - */ - public static final String COMMENT_USER_LIKE = "comment_user_like:"; - /** * 网站配置 */ @@ -71,11 +41,6 @@ public class RedisPrefixConst { */ public static final String VISITOR_AREA = "visitor_area"; - /** - * 页面封面 - */ - public static final String PAGE_COVER = "page_cover"; - /** * 关于我信息 */ @@ -88,8 +53,8 @@ public class RedisPrefixConst { /** - * token黑名单 + * 已登录的用户 */ - public static String TOKEN_BLACKLIST = "token_blacklist"; + public static final String LOGIN_USER = "login_user"; } diff --git a/aurora-springboot/src/main/java/com/aurora/dto/UserDetailDTO.java b/aurora-springboot/src/main/java/com/aurora/dto/UserDetailsDTO.java similarity index 90% rename from aurora-springboot/src/main/java/com/aurora/dto/UserDetailDTO.java rename to aurora-springboot/src/main/java/com/aurora/dto/UserDetailsDTO.java index aa8cf3f..18be36b 100644 --- a/aurora-springboot/src/main/java/com/aurora/dto/UserDetailDTO.java +++ b/aurora-springboot/src/main/java/com/aurora/dto/UserDetailsDTO.java @@ -27,7 +27,7 @@ import java.util.stream.Collectors; @Builder @AllArgsConstructor @NoArgsConstructor -public class UserDetailDTO implements UserDetails { +public class UserDetailsDTO implements UserDetails { /** * 用户账号id @@ -62,7 +62,7 @@ public class UserDetailDTO implements UserDetails { /** * 用户角色 */ - private List roleList; + private List roles; /** * 用户昵称 @@ -114,6 +114,13 @@ public class UserDetailDTO implements UserDetails { */ private String os; + /** + * 过期时间 + */ + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @JsonSerialize(using = LocalDateTimeSerializer.class) + private LocalDateTime expireTime; + /** * 最后登录时间 */ @@ -125,7 +132,7 @@ public class UserDetailDTO implements UserDetails { @Override @Transient public Collection getAuthorities() { - return roleList.stream() + return roles.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toSet()); } diff --git a/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java b/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java index 71142ea..6787c1d 100644 --- a/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java +++ b/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java @@ -1,18 +1,15 @@ package com.aurora.filter; -import com.aurora.dto.UserDetailDTO; -import com.aurora.exception.BizException; -import com.aurora.service.RedisService; -import com.aurora.utils.JwtUtils; -import io.jsonwebtoken.Claims; +import com.aurora.dto.UserDetailsDTO; +import com.aurora.service.TokenService; +import com.aurora.utils.UserUtils; import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; @@ -20,52 +17,24 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Objects; -import static com.aurora.constant.RedisPrefixConst.TOKEN_BLACKLIST; - @Component public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @Autowired - public RedisService redisService; + public TokenService tokenService; @Autowired public AuthenticationEntryPoint authenticationEntryPoint; - @SneakyThrows @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) { - String token = request.getHeader("token"); - if (StringUtils.isEmpty(token) || token.equals("null")) { - filterChain.doFilter(request, response); - return; - } - String userId; - try { - Claims claims = JwtUtils.parseJWT(token); - userId = claims.getSubject(); - } catch (Exception e) { - throwBizException(request, response, "token非法或者超时!"); - return; - } - Boolean isMember = redisService.sIsMember(TOKEN_BLACKLIST, token); - if (isMember.equals(true)) { - throwBizException(request, response, "用户未登录!"); - return; + UserDetailsDTO userDetailsDTO = tokenService.getUserDetailDTO(request); + if (Objects.nonNull(userDetailsDTO) && Objects.isNull(UserUtils.getAuthentication())) { + tokenService.contractToken(userDetailsDTO); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetailsDTO, null, userDetailsDTO.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); } - UserDetailDTO user = (UserDetailDTO) redisService.hGet("login_user", userId); - if (Objects.isNull(user)) { - throwBizException(request, response, "用户未登录!"); - return; - } - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authenticationToken); filterChain.doFilter(request, response); } - - @SneakyThrows - public void throwBizException(HttpServletRequest request, HttpServletResponse response, String message) { - request.setAttribute("bizException", new BizException(message)); - request.getRequestDispatcher("/bizException").forward(request, response); - } } diff --git a/aurora-springboot/src/main/java/com/aurora/handler/AccessDecisionManagerImpl.java b/aurora-springboot/src/main/java/com/aurora/handler/AccessDecisionManagerImpl.java index 730778f..74d8ebb 100644 --- a/aurora-springboot/src/main/java/com/aurora/handler/AccessDecisionManagerImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/handler/AccessDecisionManagerImpl.java @@ -7,6 +7,7 @@ import org.springframework.security.authentication.InsufficientAuthenticationExc import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Component; + import java.util.Collection; import java.util.List; import java.util.stream.Collectors; @@ -29,7 +30,7 @@ public class AccessDecisionManagerImpl implements AccessDecisionManager { return; } } - throw new AccessDeniedException("没有操作权限"); + throw new AccessDeniedException("权限不足"); } @Override diff --git a/aurora-springboot/src/main/java/com/aurora/handler/AuthenticationSuccessHandlerImpl.java b/aurora-springboot/src/main/java/com/aurora/handler/AuthenticationSuccessHandlerImpl.java index 5da7de0..bec7ca8 100644 --- a/aurora-springboot/src/main/java/com/aurora/handler/AuthenticationSuccessHandlerImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/handler/AuthenticationSuccessHandlerImpl.java @@ -2,13 +2,12 @@ package com.aurora.handler; import com.alibaba.fastjson.JSON; import com.aurora.constant.CommonConst; -import com.aurora.dto.UserDetailDTO; +import com.aurora.dto.UserDetailsDTO; import com.aurora.dto.UserInfoDTO; import com.aurora.entity.UserAuth; import com.aurora.mapper.UserAuthMapper; -import com.aurora.service.RedisService; +import com.aurora.service.TokenService; import com.aurora.utils.BeanCopyUtils; -import com.aurora.utils.JwtUtils; import com.aurora.utils.UserUtils; import com.aurora.vo.Result; import org.springframework.beans.factory.annotation.Autowired; @@ -23,6 +22,8 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Objects; +import static com.aurora.constant.CommonConst.TRUE; + @Component public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler { @@ -31,17 +32,15 @@ public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHa private UserAuthMapper userAuthMapper; @Autowired - private RedisService redisService; + private TokenService tokenService; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - UserInfoDTO userLoginDTO = BeanCopyUtils.copyObject(UserUtils.getLoginUser(), UserInfoDTO.class); + UserInfoDTO userLoginDTO = BeanCopyUtils.copyObject(UserUtils.getUserDetailsDTO(), UserInfoDTO.class); if (Objects.nonNull(authentication)) { - UserDetailDTO user = (UserDetailDTO) authentication.getPrincipal(); - String id = user.getId().toString(); - String jwt = JwtUtils.createJWT(id); - redisService.hSet("login_user", id, user); - userLoginDTO.setToken(jwt); + UserDetailsDTO userDetailsDTO = (UserDetailsDTO) authentication.getPrincipal(); + String token = tokenService.createToken(userDetailsDTO); + userLoginDTO.setToken(token); } response.setContentType(CommonConst.APPLICATION_JSON); response.getWriter().write(JSON.toJSONString(Result.ok(userLoginDTO))); @@ -51,10 +50,10 @@ public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHa @Async public void updateUserInfo() { UserAuth userAuth = UserAuth.builder() - .id(UserUtils.getLoginUser().getId()) - .ipAddress(UserUtils.getLoginUser().getIpAddress()) - .ipSource(UserUtils.getLoginUser().getIpSource()) - .lastLoginTime(UserUtils.getLoginUser().getLastLoginTime()) + .id(UserUtils.getUserDetailsDTO().getId()) + .ipAddress(UserUtils.getUserDetailsDTO().getIpAddress()) + .ipSource(UserUtils.getUserDetailsDTO().getIpSource()) + .lastLoginTime(UserUtils.getUserDetailsDTO().getLastLoginTime()) .build(); userAuthMapper.updateById(userAuth); } diff --git a/aurora-springboot/src/main/java/com/aurora/service/TokenService.java b/aurora-springboot/src/main/java/com/aurora/service/TokenService.java new file mode 100644 index 0000000..cc47c88 --- /dev/null +++ b/aurora-springboot/src/main/java/com/aurora/service/TokenService.java @@ -0,0 +1,23 @@ +package com.aurora.service; + +import com.aurora.dto.UserDetailsDTO; +import io.jsonwebtoken.Claims; + +import javax.servlet.http.HttpServletRequest; + +public interface TokenService { + + String createToken(UserDetailsDTO userDetailsDTO); + + String createToken(String subject); + + void refreshToken(UserDetailsDTO userDetailsDTO); + + void contractToken(UserDetailsDTO userDetailsDTO); + + Claims parseToken(String token); + + UserDetailsDTO getUserDetailDTO(HttpServletRequest request); + + void delLoginUser(Integer userId); +} diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java index e57e729..2201cfb 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java @@ -217,7 +217,7 @@ public class ArticleServiceImpl extends ServiceImpl impl if (Objects.nonNull(category)) { article.setCategoryId(category.getId()); } - article.setUserId(UserUtils.getLoginUser().getUserInfoId()); + article.setUserId(UserUtils.getUserDetailsDTO().getUserInfoId()); this.saveOrUpdate(article); // 保存文章标签 saveArticleTag(articleVO, article.getId()); diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java index 9e268bf..0805069 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java @@ -83,7 +83,7 @@ public class CommentServiceImpl extends ServiceImpl impl Integer isCommentReview = websiteConfig.getIsCommentReview(); commentVO.setCommentContent(HTMLUtils.filter(commentVO.getCommentContent())); Comment comment = Comment.builder() - .userId(UserUtils.getLoginUser().getUserInfoId()) + .userId(UserUtils.getUserDetailsDTO().getUserInfoId()) .replyUserId(commentVO.getReplyUserId()) .topicId(commentVO.getTopicId()) .commentContent(commentVO.getCommentContent()) diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/MenuServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/MenuServiceImpl.java index cb1055a..3f88fa4 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/MenuServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/MenuServiceImpl.java @@ -136,7 +136,7 @@ public class MenuServiceImpl extends ServiceImpl implements Me @Override public List listUserMenus() { // 查询用户菜单信息 - List menus = menuMapper.listMenusByUserInfoId(UserUtils.getLoginUser().getUserInfoId()); + List menus = menuMapper.listMenusByUserInfoId(UserUtils.getUserDetailsDTO().getUserInfoId()); // 获取目录列表 List catalogs = listCatalogs(menus); // 获取目录下的子菜单 diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/TalkServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/TalkServiceImpl.java index c9ea72a..9ec102d 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/TalkServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/TalkServiceImpl.java @@ -85,7 +85,7 @@ public class TalkServiceImpl extends ServiceImpl implements Ta @Override public void saveOrUpdateTalk(TalkVO talkVO) { Talk talk = BeanCopyUtils.copyObject(talkVO, Talk.class); - talk.setUserId(UserUtils.getLoginUser().getUserInfoId()); + talk.setUserId(UserUtils.getUserDetailsDTO().getUserInfoId()); this.saveOrUpdate(talk); } diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java new file mode 100644 index 0000000..b02020b --- /dev/null +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java @@ -0,0 +1,100 @@ +package com.aurora.service.impl; + +import com.aurora.dto.UserDetailsDTO; +import com.aurora.service.RedisService; +import com.aurora.service.TokenService; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.http.HttpServletRequest; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.Base64; +import java.util.UUID; + +import static com.aurora.constant.CommonConst.TWENTY_MINUTES; +import static com.aurora.constant.RedisPrefixConst.LOGIN_USER; + + +@Service +public class TokenServiceImpl implements TokenService { + + private final static String header = "token"; + + private final static String secret = "huaweimian"; + + private final static Integer expireTime = 7 * 24 * 60 * 60; + + @Autowired + private RedisService redisService; + + @Override + public String createToken(UserDetailsDTO userDetailsDTO) { + refreshToken(userDetailsDTO); + String userId = userDetailsDTO.getId().toString(); + return createToken(userId); + } + + @Override + public String createToken(String subject) { + SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; + SecretKey secretKey = generalKey(); + return Jwts.builder().setId(getUuid()).setSubject(subject) + .setIssuer("huaweimian") + .signWith(signatureAlgorithm, secretKey).compact(); + } + + @Override + public void refreshToken(UserDetailsDTO userDetailsDTO) { + userDetailsDTO.setExpireTime(userDetailsDTO.getLastLoginTime().plusSeconds(expireTime)); + String userId = userDetailsDTO.getId().toString(); + redisService.hSet(LOGIN_USER, userId, userDetailsDTO, expireTime); + } + + @Override + public void contractToken(UserDetailsDTO userDetailsDTO) { + LocalDateTime expireTime = userDetailsDTO.getExpireTime(); + LocalDateTime currentTime = LocalDateTime.now(); + if (Duration.between(currentTime, expireTime).toMinutes() <= TWENTY_MINUTES) { + refreshToken(userDetailsDTO); + } + } + + @Override + public Claims parseToken(String token) { + SecretKey secretKey = generalKey(); + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody(); + } + + @Override + public UserDetailsDTO getUserDetailDTO(HttpServletRequest request) { + String token = request.getHeader(TokenServiceImpl.header); + if (StringUtils.hasText(token) && !token.equals("null")) { + Claims claims = parseToken(token); + String userId = claims.getSubject(); + return (UserDetailsDTO) redisService.hGet(LOGIN_USER, userId); + } + return null; + } + + @Override + public void delLoginUser(Integer userId) { + redisService.hDel(LOGIN_USER, String.valueOf(userId)); + } + + public String getUuid() { + return UUID.randomUUID().toString().replaceAll("-", ""); + } + + public SecretKey generalKey() { + byte[] encodedKey = Base64.getDecoder().decode(secret); + return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); + } + +} diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/UserAuthServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/UserAuthServiceImpl.java index 1c76d14..6d71c30 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/UserAuthServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/UserAuthServiceImpl.java @@ -14,9 +14,9 @@ import com.aurora.mapper.UserInfoMapper; import com.aurora.mapper.UserRoleMapper; import com.aurora.service.AuroraInfoService; import com.aurora.service.RedisService; +import com.aurora.service.TokenService; import com.aurora.service.UserAuthService; import com.aurora.strategy.context.SocialLoginStrategyContext; -import com.aurora.utils.JwtUtils; import com.aurora.utils.PageUtils; import com.aurora.utils.UserUtils; import com.aurora.vo.*; @@ -31,9 +31,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCrypt; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; @@ -67,7 +64,7 @@ public class UserAuthServiceImpl implements UserAuthService { private AuroraInfoService auroraInfoService; @Autowired - private HttpServletRequest request; + private TokenService tokenService; @Autowired private RabbitTemplate rabbitTemplate; @@ -171,11 +168,11 @@ public class UserAuthServiceImpl implements UserAuthService { public void updateAdminPassword(PasswordVO passwordVO) { // 查询旧密码是否正确 UserAuth user = userAuthMapper.selectOne(new LambdaQueryWrapper() - .eq(UserAuth::getId, UserUtils.getLoginUser().getId())); + .eq(UserAuth::getId, UserUtils.getUserDetailsDTO().getId())); // 正确则修改密码,错误则提示不正确 if (Objects.nonNull(user) && BCrypt.checkpw(passwordVO.getOldPassword(), user.getPassword())) { UserAuth userAuth = UserAuth.builder() - .id(UserUtils.getLoginUser().getId()) + .id(UserUtils.getUserDetailsDTO().getId()) .password(BCrypt.hashpw(passwordVO.getNewPassword(), BCrypt.gensalt())) .build(); userAuthMapper.updateById(userAuth); @@ -199,16 +196,7 @@ public class UserAuthServiceImpl implements UserAuthService { @SneakyThrows @Override public UserLogoutStatusDTO logout() { - String token = request.getHeader("token"); - if (StringUtils.isEmpty(token)) { - throw new BizException("用户未登录"); - } - UserDetailDTO user = UserUtils.getLoginUser(); - String userId = user.getId().toString(); - // 将token加入黑名单列表 - redisService.sAddExpire(TOKEN_BLACKLIST, JwtUtils.JWT_TTL, token); - // 删除redis中登录的用户信息 - redisService.hDel("login_user", userId); + tokenService.delLoginUser(UserUtils.getUserDetailsDTO().getId()); return new UserLogoutStatusDTO("注销成功"); } diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/UserDetailServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/UserDetailServiceImpl.java index 8a89f09..5250d6e 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/UserDetailServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/UserDetailServiceImpl.java @@ -1,7 +1,7 @@ package com.aurora.service.impl; -import com.aurora.dto.UserDetailDTO; +import com.aurora.dto.UserDetailsDTO; import com.aurora.entity.UserAuth; import com.aurora.entity.UserInfo; import com.aurora.exception.BizException; @@ -55,24 +55,24 @@ public class UserDetailServiceImpl implements UserDetailsService { return convertUserDetail(userAuth, request); } - public UserDetailDTO convertUserDetail(UserAuth user, HttpServletRequest request) { + public UserDetailsDTO convertUserDetail(UserAuth user, HttpServletRequest request) { // 查询账号信息 UserInfo userInfo = userInfoMapper.selectById(user.getUserInfoId()); // 查询账号角色 - List roleList = roleMapper.listRolesByUserInfoId(userInfo.getId()); + List roles = roleMapper.listRolesByUserInfoId(userInfo.getId()); // 获取设备信息 String ipAddress = IpUtils.getIpAddress(request); String ipSource = IpUtils.getIpSource(ipAddress); UserAgent userAgent = IpUtils.getUserAgent(request); // 封装权限集合 - return UserDetailDTO.builder() + return UserDetailsDTO.builder() .id(user.getId()) .loginType(user.getLoginType()) .userInfoId(userInfo.getId()) .username(user.getUsername()) .password(user.getPassword()) .email(userInfo.getEmail()) - .roleList(roleList) + .roles(roles) .nickname(userInfo.getNickname()) .avatar(userInfo.getAvatar()) .intro(userInfo.getIntro()) diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/UserInfoServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/UserInfoServiceImpl.java index 0239d78..d183bc6 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/UserInfoServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/UserInfoServiceImpl.java @@ -1,14 +1,17 @@ package com.aurora.service.impl; -import com.aurora.dto.UserDetailDTO; +import com.aurora.dto.UserDetailsDTO; import com.aurora.dto.UserInfoDTO; import com.aurora.dto.UserOnlineDTO; +import com.aurora.entity.UserAuth; import com.aurora.entity.UserInfo; import com.aurora.entity.UserRole; import com.aurora.enums.FilePathEnum; import com.aurora.exception.BizException; +import com.aurora.mapper.UserAuthMapper; import com.aurora.mapper.UserInfoMapper; import com.aurora.service.RedisService; +import com.aurora.service.TokenService; import com.aurora.service.UserInfoService; import com.aurora.service.UserRoleService; import com.aurora.strategy.context.UploadStrategyContext; @@ -37,6 +40,12 @@ public class UserInfoServiceImpl extends ServiceImpl i @Autowired private UserInfoMapper userInfoMapper; + @Autowired + private UserAuthMapper userAuthMapper; + + @Autowired + private TokenService tokenService; + @Autowired private RedisService redisService; @@ -52,7 +61,7 @@ public class UserInfoServiceImpl extends ServiceImpl i public void updateUserInfo(UserInfoVO userInfoVO) { // 封装用户信息 UserInfo userInfo = UserInfo.builder() - .id(UserUtils.getLoginUser().getUserInfoId()) + .id(UserUtils.getUserDetailsDTO().getUserInfoId()) .nickname(userInfoVO.getNickname()) .intro(userInfoVO.getIntro()) .website(userInfoVO.getWebsite()) @@ -66,7 +75,7 @@ public class UserInfoServiceImpl extends ServiceImpl i String avatar = uploadStrategyContext.executeUploadStrategy(file, FilePathEnum.AVATAR.getPath()); // 更新用户信息 UserInfo userInfo = UserInfo.builder() - .id(UserUtils.getLoginUser().getUserInfoId()) + .id(UserUtils.getUserDetailsDTO().getUserInfoId()) .avatar(avatar) .build(); userInfoMapper.updateById(userInfo); @@ -83,7 +92,7 @@ public class UserInfoServiceImpl extends ServiceImpl i throw new BizException("验证码错误!"); } UserInfo userInfo = UserInfo.builder() - .id(UserUtils.getLoginUser().getUserInfoId()) + .id(UserUtils.getUserDetailsDTO().getUserInfoId()) .email(emailVO.getEmail()) .build(); userInfoMapper.updateById(userInfo); @@ -139,11 +148,11 @@ public class UserInfoServiceImpl extends ServiceImpl i public PageResult listOnlineUsers(ConditionVO conditionVO) { Map userMaps = redisService.hGetAll("login_user"); Collection values = userMaps.values(); - ArrayList userDetailDTOs = new ArrayList<>(); + ArrayList userDetailsDTOs = new ArrayList<>(); for (Object value : values) { - userDetailDTOs.add((UserDetailDTO) value); + userDetailsDTOs.add((UserDetailsDTO) value); } - List userOnlineDTOs = BeanCopyUtils.copyList(userDetailDTOs, UserOnlineDTO.class); + List userOnlineDTOs = BeanCopyUtils.copyList(userDetailsDTOs, UserOnlineDTO.class); List onlineUsers = userOnlineDTOs.stream() .filter(item -> StringUtils.isBlank(conditionVO.getKeywords()) || item.getNickname().contains(conditionVO.getKeywords())) .sorted(Comparator.comparing(UserOnlineDTO::getLastLoginTime).reversed()) @@ -157,7 +166,8 @@ public class UserInfoServiceImpl extends ServiceImpl i @Override public void removeOnlineUser(Integer userInfoId) { - redisService.hDel("login_user", String.valueOf(userInfoId)); + Integer userId = userAuthMapper.selectOne(new LambdaQueryWrapper().eq(UserAuth::getUserInfoId, userInfoId)).getId(); + tokenService.delLoginUser(userId); } @Override diff --git a/aurora-springboot/src/main/java/com/aurora/strategy/impl/AbstractSocialLoginStrategyImpl.java b/aurora-springboot/src/main/java/com/aurora/strategy/impl/AbstractSocialLoginStrategyImpl.java index f5ce879..298ce88 100644 --- a/aurora-springboot/src/main/java/com/aurora/strategy/impl/AbstractSocialLoginStrategyImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/strategy/impl/AbstractSocialLoginStrategyImpl.java @@ -2,7 +2,7 @@ package com.aurora.strategy.impl; import com.aurora.dto.SocialTokenDTO; import com.aurora.dto.SocialUserInfoDTO; -import com.aurora.dto.UserDetailDTO; +import com.aurora.dto.UserDetailsDTO; import com.aurora.dto.UserInfoDTO; import com.aurora.entity.UserAuth; import com.aurora.entity.UserInfo; @@ -12,12 +12,11 @@ import com.aurora.exception.BizException; import com.aurora.mapper.UserAuthMapper; import com.aurora.mapper.UserInfoMapper; import com.aurora.mapper.UserRoleMapper; -import com.aurora.service.RedisService; +import com.aurora.service.TokenService; import com.aurora.service.impl.UserDetailServiceImpl; import com.aurora.strategy.SocialLoginStrategy; import com.aurora.utils.BeanCopyUtils; import com.aurora.utils.IpUtils; -import com.aurora.utils.JwtUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.springframework.beans.factory.annotation.Autowired; @@ -53,7 +52,7 @@ public abstract class AbstractSocialLoginStrategyImpl implements SocialLoginStra private UserDetailServiceImpl userDetailService; @Autowired - private RedisService redisService; + private TokenService tokenService; @Resource private HttpServletRequest request; @@ -61,7 +60,7 @@ public abstract class AbstractSocialLoginStrategyImpl implements SocialLoginStra @Override public UserInfoDTO login(String data) { // 创建登录信息 - UserDetailDTO userDetailDTO; + UserDetailsDTO userDetailsDTO; // 获取第三方token信息 SocialTokenDTO socialToken = getSocialToken(data); // 获取用户ip信息 @@ -71,25 +70,23 @@ public abstract class AbstractSocialLoginStrategyImpl implements SocialLoginStra UserAuth user = getUserAuth(socialToken); if (Objects.nonNull(user)) { // 返回数据库用户信息 - userDetailDTO = getUserDetail(user, ipAddress, ipSource); + userDetailsDTO = getUserDetail(user, ipAddress, ipSource); } else { // 获取第三方用户信息,保存到数据库返回 - userDetailDTO = saveUserDetail(socialToken, ipAddress, ipSource); + userDetailsDTO = saveUserDetail(socialToken, ipAddress, ipSource); } // 判断账号是否禁用 - if (userDetailDTO.getIsDisable().equals(TRUE)) { + if (userDetailsDTO.getIsDisable().equals(TRUE)) { throw new BizException("用户帐号已被锁定"); } // 将登录信息放入springSecurity管理 - UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetailDTO, null, userDetailDTO.getAuthorities()); + UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetailsDTO, null, userDetailsDTO.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(auth); // 返回用户信息 - UserInfoDTO userInfoDTO = BeanCopyUtils.copyObject(userDetailDTO, UserInfoDTO.class); - String id = userDetailDTO.getId().toString(); - String jwt = JwtUtils.createJWT(id); - redisService.hSet("login_user", id, userDetailDTO); - userInfoDTO.setToken(jwt); + UserInfoDTO userInfoDTO = BeanCopyUtils.copyObject(userDetailsDTO, UserInfoDTO.class); + String token = tokenService.createToken(userDetailsDTO); + userInfoDTO.setToken(token); return userInfoDTO; } @@ -126,9 +123,9 @@ public abstract class AbstractSocialLoginStrategyImpl implements SocialLoginStra * @param user 用户账号 * @param ipAddress ip地址 * @param ipSource ip源 - * @return {@link UserDetailDTO} 用户信息 + * @return {@link UserDetailsDTO} 用户信息 */ - private UserDetailDTO getUserDetail(UserAuth user, String ipAddress, String ipSource) { + private UserDetailsDTO getUserDetail(UserAuth user, String ipAddress, String ipSource) { // 更新登录信息 userAuthMapper.update(new UserAuth(), new LambdaUpdateWrapper() .set(UserAuth::getLastLoginTime, LocalDateTime.now()) @@ -145,9 +142,9 @@ public abstract class AbstractSocialLoginStrategyImpl implements SocialLoginStra * @param socialToken token信息 * @param ipAddress ip地址 * @param ipSource ip源 - * @return {@link UserDetailDTO} 用户信息 + * @return {@link UserDetailsDTO} 用户信息 */ - private UserDetailDTO saveUserDetail(SocialTokenDTO socialToken, String ipAddress, String ipSource) { + private UserDetailsDTO saveUserDetail(SocialTokenDTO socialToken, String ipAddress, String ipSource) { // 获取第三方用户信息 SocialUserInfoDTO socialUserInfo = getSocialUserInfo(socialToken); // 保存用户信息 diff --git a/aurora-springboot/src/main/java/com/aurora/utils/JwtUtils.java b/aurora-springboot/src/main/java/com/aurora/utils/JwtUtils.java deleted file mode 100644 index da54521..0000000 --- a/aurora-springboot/src/main/java/com/aurora/utils/JwtUtils.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.aurora.utils; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.JwtBuilder; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; - -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; -import java.util.Base64; -import java.util.Date; -import java.util.UUID; - -/** - * @author 花未眠 - * JWT工具类 - */ -public class JwtUtils { - - //有效期为 - public static final Long JWT_TTL = 7 * 24 * 60 * 60 * 1000L;// 1 * 60 * 60 *1000 一个小时 - //设置秘钥明文 - public static final String JWT_KEY = "huaweimian"; - - public static String getUUID() { - return UUID.randomUUID().toString().replaceAll("-", ""); - } - - /** - * 生成jtw - */ - public static String createJWT(String subject) { - JwtBuilder builder = getJwtBuilder(subject, null, getUUID());// 设置过期时间 - return builder.compact(); - } - - /** - * 生成jwt - */ - public static String createJWT(String subject, Long ttlMillis) { - JwtBuilder builder = getJwtBuilder(subject, ttlMillis, getUUID());// 设置过期时间 - return builder.compact(); - } - - private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) { - SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; - SecretKey secretKey = generalKey(); - long nowMillis = System.currentTimeMillis(); - Date now = new Date(nowMillis); - if (ttlMillis == null) { - ttlMillis = JwtUtils.JWT_TTL; - } - long expMillis = nowMillis + ttlMillis; - Date expDate = new Date(expMillis); - return Jwts.builder() - .setId(uuid) //唯一的ID - .setSubject(subject) // 主题 可以是JSON数据 - .setIssuer("sg") // 签发者 - .setIssuedAt(now) // 签发时间 - .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥 - .setExpiration(expDate); - } - - /** - * 创建token - */ - public static String createJWT(String id, String subject, Long ttlMillis) { - JwtBuilder builder = getJwtBuilder(subject, ttlMillis, id);// 设置过期时间 - return builder.compact(); - } - - /** - * 生成加密后的秘钥 secretKey - */ - public static SecretKey generalKey() { - byte[] encodedKey = Base64.getDecoder().decode(JwtUtils.JWT_KEY); - return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); - } - - /** - * 解析 - */ - public static Claims parseJWT(String jwt) throws Exception { - SecretKey secretKey = generalKey(); - return Jwts.parser() - .setSigningKey(secretKey) - .parseClaimsJws(jwt) - .getBody(); - } - - -} \ No newline at end of file diff --git a/aurora-springboot/src/main/java/com/aurora/utils/UserUtils.java b/aurora-springboot/src/main/java/com/aurora/utils/UserUtils.java index 7ccdb26..14638b7 100644 --- a/aurora-springboot/src/main/java/com/aurora/utils/UserUtils.java +++ b/aurora-springboot/src/main/java/com/aurora/utils/UserUtils.java @@ -1,6 +1,7 @@ package com.aurora.utils; -import com.aurora.dto.UserDetailDTO; +import com.aurora.dto.UserDetailsDTO; +import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; @@ -12,12 +13,12 @@ import org.springframework.stereotype.Component; @Component public class UserUtils { - /** - * 获取当前登录用户 - * @return 用户登录信息 - */ - public static UserDetailDTO getLoginUser() { - return (UserDetailDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + public static UserDetailsDTO getUserDetailsDTO() { + return (UserDetailsDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + } + + public static Authentication getAuthentication() { + return SecurityContextHolder.getContext().getAuthentication(); } } From 5f8cfd03bdd43275e558b853d004554c784df9f6 Mon Sep 17 00:00:00 2001 From: linhaojun Date: Mon, 19 Sep 2022 12:18:25 +0800 Subject: [PATCH 02/16] =?UTF-8?q?:art:=20=E4=BF=AE=E5=A4=8Dtoken=E7=BB=AD?= =?UTF-8?q?=E7=BA=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/aurora/filter/JwtAuthenticationTokenFilter.java | 2 +- .../src/main/java/com/aurora/service/TokenService.java | 2 +- .../main/java/com/aurora/service/impl/TokenServiceImpl.java | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java b/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java index 6787c1d..a63e27d 100644 --- a/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java +++ b/aurora-springboot/src/main/java/com/aurora/filter/JwtAuthenticationTokenFilter.java @@ -31,7 +31,7 @@ public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) { UserDetailsDTO userDetailsDTO = tokenService.getUserDetailDTO(request); if (Objects.nonNull(userDetailsDTO) && Objects.isNull(UserUtils.getAuthentication())) { - tokenService.contractToken(userDetailsDTO); + tokenService.renewToken(userDetailsDTO); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetailsDTO, null, userDetailsDTO.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authenticationToken); } diff --git a/aurora-springboot/src/main/java/com/aurora/service/TokenService.java b/aurora-springboot/src/main/java/com/aurora/service/TokenService.java index cc47c88..cdb242f 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/TokenService.java +++ b/aurora-springboot/src/main/java/com/aurora/service/TokenService.java @@ -13,7 +13,7 @@ public interface TokenService { void refreshToken(UserDetailsDTO userDetailsDTO); - void contractToken(UserDetailsDTO userDetailsDTO); + void renewToken(UserDetailsDTO userDetailsDTO); Claims parseToken(String token); diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java index b02020b..89cd660 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java @@ -52,13 +52,13 @@ public class TokenServiceImpl implements TokenService { @Override public void refreshToken(UserDetailsDTO userDetailsDTO) { - userDetailsDTO.setExpireTime(userDetailsDTO.getLastLoginTime().plusSeconds(expireTime)); + LocalDateTime currentTime = LocalDateTime.now(); + userDetailsDTO.setExpireTime(currentTime.plusSeconds(expireTime)); String userId = userDetailsDTO.getId().toString(); redisService.hSet(LOGIN_USER, userId, userDetailsDTO, expireTime); } - @Override - public void contractToken(UserDetailsDTO userDetailsDTO) { + public void renewToken(UserDetailsDTO userDetailsDTO) { LocalDateTime expireTime = userDetailsDTO.getExpireTime(); LocalDateTime currentTime = LocalDateTime.now(); if (Duration.between(currentTime, expireTime).toMinutes() <= TWENTY_MINUTES) { From 0113c32a87cb9d2500a9b7fdd987e4fc8b74cafd Mon Sep 17 00:00:00 2001 From: linhaojun Date: Mon, 19 Sep 2022 13:19:47 +0800 Subject: [PATCH 03/16] =?UTF-8?q?:rocket:=20=E6=B7=BB=E5=8A=A0=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/CommentServiceImpl.java | 74 +++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java index 0805069..efbb7d7 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/CommentServiceImpl.java @@ -2,7 +2,10 @@ package com.aurora.service.impl; import com.alibaba.fastjson.JSON; import com.aurora.dto.*; +import com.aurora.entity.Article; import com.aurora.entity.Comment; +import com.aurora.entity.Talk; +import com.aurora.entity.UserInfo; import com.aurora.enums.CommentTypeEnum; import com.aurora.exception.BizException; import com.aurora.mapper.ArticleMapper; @@ -37,8 +40,7 @@ import java.util.stream.Collectors; import static com.aurora.constant.CommonConst.*; import static com.aurora.constant.MQPrefixConst.EMAIL_EXCHANGE; -import static com.aurora.enums.CommentTypeEnum.getCommentEnum; -import static com.aurora.enums.CommentTypeEnum.getCommentPath; +import static com.aurora.enums.CommentTypeEnum.*; @Service public class CommentServiceImpl extends ServiceImpl implements CommentService { @@ -76,9 +78,7 @@ public class CommentServiceImpl extends ServiceImpl impl @Override public void saveComment(CommentVO commentVO) { - if (!types.contains(commentVO.getType())) { - throw new BizException("评论类型不存在!"); - } + checkCommentVO(commentVO); WebsiteConfigDTO websiteConfig = auroraInfoService.getWebsiteConfig(); Integer isCommentReview = websiteConfig.getIsCommentReview(); commentVO.setCommentContent(HTMLUtils.filter(commentVO.getCommentContent())); @@ -151,6 +151,70 @@ public class CommentServiceImpl extends ServiceImpl impl this.updateBatchById(comments); } + public void checkCommentVO(CommentVO commentVO) { + // 校验评论类型是否存在 + if (!types.contains(commentVO.getType())) { + throw new BizException("参数校验异常"); + } + // 类型为文章和说说时,类型id不能为空,且判断文章或说说是否存在 + if (Objects.requireNonNull(getCommentEnum(commentVO.getType())) == ARTICLE || Objects.requireNonNull(getCommentEnum(commentVO.getType())) == TALK) { + // 类型id为空则报异常 + if (Objects.isNull(commentVO.getTopicId())) { + throw new BizException("参数校验异常"); + } else { + // 类型id不为空判断文章是否存在 + if (Objects.requireNonNull(getCommentEnum(commentVO.getType())) == ARTICLE) { + Article article = articleMapper.selectOne(new LambdaQueryWrapper
().select(Article::getId, Article::getUserId).eq(Article::getId, commentVO.getTopicId())); + if (Objects.isNull(article)) { + throw new BizException("参数校验异常"); + } + } + // 类型id不为空判断说说是否存在 + if (Objects.requireNonNull(getCommentEnum(commentVO.getType())) == TALK) { + Talk talk = talkMapper.selectOne(new LambdaQueryWrapper().select(Talk::getId, Talk::getUserId).eq(Talk::getId, commentVO.getTopicId())); + if (Objects.isNull(talk)) { + throw new BizException("参数校验异常"); + } + } + } + } + // 类型为友链,about,留言时,topicId必须为空 + if (Objects.requireNonNull(getCommentEnum(commentVO.getType())) == LINK + || Objects.requireNonNull(getCommentEnum(commentVO.getType())) == ABOUT + || Objects.requireNonNull(getCommentEnum(commentVO.getType())) == MESSAGE) { + if (Objects.nonNull(commentVO.getTopicId())) { + throw new BizException("参数校验异常"); + } + } + // 父评论时 replyUserId 为空 + if (Objects.isNull(commentVO.getParentId())) { + if (Objects.nonNull(commentVO.getReplyUserId())) { + throw new BizException("参数校验异常"); + } + } + // 子评论时 + if (Objects.nonNull(commentVO.getParentId())) { + Comment parentComment = commentMapper.selectOne(new LambdaQueryWrapper().select(Comment::getId, Comment::getParentId, Comment::getType).eq(Comment::getId, commentVO.getParentId())); + if (Objects.isNull(parentComment)) { + throw new BizException("参数校验异常"); + } + if (Objects.nonNull(parentComment.getParentId())) { + throw new BizException("参数校验异常"); + } + if (!commentVO.getType().equals(parentComment.getType())) { + throw new BizException("参数校验异常"); + } + if (Objects.isNull(commentVO.getReplyUserId())) { + throw new BizException("参数校验异常"); + } else { + UserInfo existUser = userInfoMapper.selectOne(new LambdaQueryWrapper().select(UserInfo::getId).eq(UserInfo::getId, commentVO.getReplyUserId())); + if (Objects.isNull(existUser)) { + throw new BizException("参数校验异常"); + } + } + } + } + public void notice(Comment comment) { // 查询回复用户邮箱号 Integer userId = BLOGGER_ID; From 448005287c187536365c57eac760dcb2157741ba Mon Sep 17 00:00:00 2001 From: linhaojun Date: Mon, 19 Sep 2022 23:57:54 +0800 Subject: [PATCH 04/16] =?UTF-8?q?:rocket:=20=E6=B7=BB=E5=8A=A0=E6=96=87?= =?UTF-8?q?=E7=AB=A0=E7=9A=84=E5=8A=A0=E5=AF=86=E8=AE=BF=E9=97=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/aurora/constant/RedisPrefixConst.java | 4 + .../aurora/controller/ArticleController.java | 9 ++- .../java/com/aurora/dto/ArticleCardDTO.java | 1 + .../main/java/com/aurora/entity/Article.java | 1 + .../java/com/aurora/enums/StatusCodeEnum.java | 8 +- .../com/aurora/service/ArticleService.java | 2 + .../service/impl/ArticleServiceImpl.java | 30 ++++++++ .../aurora/service/impl/TokenServiceImpl.java | 1 + .../java/com/aurora/vo/ArticlePasswordVO.java | 16 ++++ .../main/resources/mapper/ArticleMapper.xml | 29 ++++--- aurora-vue/aurora-blog/src/api/api.ts | 3 + .../ArticleCard/src/ArticleCard.vue | 45 ++++++++--- .../src/components/Header/src/Controls.vue | 75 +++++++++++++++++-- .../src/components/Tag/src/TagItem.vue | 4 +- aurora-vue/aurora-blog/src/stores/user.ts | 3 +- aurora-vue/aurora-blog/src/views/Article.vue | 25 ++++++- 16 files changed, 222 insertions(+), 34 deletions(-) create mode 100644 aurora-springboot/src/main/java/com/aurora/vo/ArticlePasswordVO.java diff --git a/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java b/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java index 1a73f35..876f64d 100644 --- a/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java +++ b/aurora-springboot/src/main/java/com/aurora/constant/RedisPrefixConst.java @@ -57,4 +57,8 @@ public class RedisPrefixConst { */ public static final String LOGIN_USER = "login_user"; + /** + * 文章授权访问名单 + */ + public static final String USER_ARTICLE_ACCESS = "article_access"; } diff --git a/aurora-springboot/src/main/java/com/aurora/controller/ArticleController.java b/aurora-springboot/src/main/java/com/aurora/controller/ArticleController.java index 29ba7d7..aeb40ff 100644 --- a/aurora-springboot/src/main/java/com/aurora/controller/ArticleController.java +++ b/aurora-springboot/src/main/java/com/aurora/controller/ArticleController.java @@ -57,6 +57,13 @@ public class ArticleController { return Result.ok(articleService.getArticleById(articleId)); } + @ApiOperation("校验文章访问密码") + @PostMapping("/articles/access") + public Result accessArticle(@Valid @RequestBody ArticlePasswordVO articlePasswordVO) { + articleService.accessArticle(articlePasswordVO); + return Result.ok(); + } + @ApiOperation("根据标签id获取文章") @GetMapping("/articles/tagId") public Result> listArticlesByTagId(@RequestParam Integer tagId) { @@ -139,5 +146,5 @@ public class ArticleController { public Result> listArticlesBySearch(ConditionVO condition) { return Result.ok(articleService.listArticlesBySearch(condition)); } - + } diff --git a/aurora-springboot/src/main/java/com/aurora/dto/ArticleCardDTO.java b/aurora-springboot/src/main/java/com/aurora/dto/ArticleCardDTO.java index e65bff3..5e50a3f 100644 --- a/aurora-springboot/src/main/java/com/aurora/dto/ArticleCardDTO.java +++ b/aurora-springboot/src/main/java/com/aurora/dto/ArticleCardDTO.java @@ -24,6 +24,7 @@ public class ArticleCardDTO { private UserInfo author; private String categoryName; private List tags; + private Integer status; private LocalDateTime createTime; private LocalDateTime updateTime; } diff --git a/aurora-springboot/src/main/java/com/aurora/entity/Article.java b/aurora-springboot/src/main/java/com/aurora/entity/Article.java index ee3ea6f..ef26872 100644 --- a/aurora-springboot/src/main/java/com/aurora/entity/Article.java +++ b/aurora-springboot/src/main/java/com/aurora/entity/Article.java @@ -30,6 +30,7 @@ public class Article { private Integer isDelete; private Integer status; private Integer type; + private String password; private String originalUrl; @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; diff --git a/aurora-springboot/src/main/java/com/aurora/enums/StatusCodeEnum.java b/aurora-springboot/src/main/java/com/aurora/enums/StatusCodeEnum.java index 483a869..61c9e22 100644 --- a/aurora-springboot/src/main/java/com/aurora/enums/StatusCodeEnum.java +++ b/aurora-springboot/src/main/java/com/aurora/enums/StatusCodeEnum.java @@ -43,13 +43,13 @@ public enum StatusCodeEnum { */ USERNAME_NOT_EXIST(52002, "用户名不存在"), /** - * qq登录错误 + * 文章密码认证未通过 */ - QQ_LOGIN_ERROR(53001, "qq登录错误"), + ARTICLE_ACCESS_FAIL(52003, "文章密码认证未通过"), /** - * 微博登录错误 + * qq登录错误 */ - WEIBO_LOGIN_ERROR(53002, "微博登录错误"); + QQ_LOGIN_ERROR(53001, "qq登录错误"); /** * 状态码 diff --git a/aurora-springboot/src/main/java/com/aurora/service/ArticleService.java b/aurora-springboot/src/main/java/com/aurora/service/ArticleService.java index 5b8b745..983fedc 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/ArticleService.java +++ b/aurora-springboot/src/main/java/com/aurora/service/ArticleService.java @@ -19,6 +19,8 @@ public interface ArticleService extends IService
{ ArticleDTO getArticleById(Integer articleId); + void accessArticle(ArticlePasswordVO articlePasswordVO); + PageResult listArticlesByTagId(Integer tagId); PageResult listArchives(); diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java index 2201cfb..6b5c071 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/ArticleServiceImpl.java @@ -8,6 +8,7 @@ import com.aurora.entity.Category; import com.aurora.entity.Tag; import com.aurora.enums.FileExtEnum; import com.aurora.enums.FilePathEnum; +import com.aurora.enums.StatusCodeEnum; import com.aurora.exception.BizException; import com.aurora.mapper.ArticleMapper; import com.aurora.mapper.ArticleTagMapper; @@ -42,6 +43,7 @@ import java.util.stream.Collectors; import static com.aurora.constant.MQPrefixConst.SUBSCRIBE_EXCHANGE; import static com.aurora.constant.RedisPrefixConst.*; import static com.aurora.enums.ArticleStatusEnum.*; +import static com.aurora.enums.StatusCodeEnum.ARTICLE_ACCESS_FAIL; @Service public class ArticleServiceImpl extends ServiceImpl implements ArticleService { @@ -115,6 +117,21 @@ public class ArticleServiceImpl extends ServiceImpl impl @SneakyThrows @Override public ArticleDTO getArticleById(Integer articleId) { + Article articleForCheck = articleMapper.selectOne(new LambdaQueryWrapper
().eq(Article::getId, articleId)); + if (Objects.isNull(articleForCheck)) { + return null; + } + if (articleForCheck.getStatus().equals(2)) { + Boolean isAccess; + try { + isAccess = redisService.sIsMember(USER_ARTICLE_ACCESS + ":" + UserUtils.getUserDetailsDTO().getId(), articleId); + } catch (Exception exception) { + throw new BizException(ARTICLE_ACCESS_FAIL); + } + if (isAccess.equals(false)) { + throw new BizException(ARTICLE_ACCESS_FAIL); + } + } updateArticleViewsCount(articleId); CompletableFuture asyncArticle = CompletableFuture.supplyAsync(() -> articleMapper.getArticleById(articleId)); CompletableFuture asyncPreArticle = CompletableFuture.supplyAsync(() -> { @@ -144,6 +161,19 @@ public class ArticleServiceImpl extends ServiceImpl impl return article; } + @Override + public void accessArticle(ArticlePasswordVO articlePasswordVO) { + Article article = articleMapper.selectOne(new LambdaQueryWrapper
().eq(Article::getId, articlePasswordVO.getArticleId())); + if (Objects.isNull(article)) { + throw new BizException("文章不存在"); + } + if (article.getPassword().equals(articlePasswordVO.getArticlePassword())) { + redisService.sAdd(USER_ARTICLE_ACCESS + ":" + UserUtils.getUserDetailsDTO().getId(), articlePasswordVO.getArticleId()); + } else { + throw new BizException("密码错误"); + } + } + @SneakyThrows @Override public PageResult listArticlesByTagId(Integer tagId) { diff --git a/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java b/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java index 89cd660..c6a0bdb 100644 --- a/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java +++ b/aurora-springboot/src/main/java/com/aurora/service/impl/TokenServiceImpl.java @@ -58,6 +58,7 @@ public class TokenServiceImpl implements TokenService { redisService.hSet(LOGIN_USER, userId, userDetailsDTO, expireTime); } + @Override public void renewToken(UserDetailsDTO userDetailsDTO) { LocalDateTime expireTime = userDetailsDTO.getExpireTime(); LocalDateTime currentTime = LocalDateTime.now(); diff --git a/aurora-springboot/src/main/java/com/aurora/vo/ArticlePasswordVO.java b/aurora-springboot/src/main/java/com/aurora/vo/ArticlePasswordVO.java new file mode 100644 index 0000000..775f103 --- /dev/null +++ b/aurora-springboot/src/main/java/com/aurora/vo/ArticlePasswordVO.java @@ -0,0 +1,16 @@ +package com.aurora.vo; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ArticlePasswordVO { + private Integer articleId; + private String articlePassword; +} diff --git a/aurora-springboot/src/main/resources/mapper/ArticleMapper.xml b/aurora-springboot/src/main/resources/mapper/ArticleMapper.xml index 8232057..1fc870e 100644 --- a/aurora-springboot/src/main/resources/mapper/ArticleMapper.xml +++ b/aurora-springboot/src/main/resources/mapper/ArticleMapper.xml @@ -8,6 +8,7 @@ + @@ -65,6 +66,7 @@ SUBSTR(article_content, 1, 500) AS article_content, is_top, is_featured, + status, a.create_time AS create_time, a.update_time AS update_time, u.nickname AS author_nickname, @@ -91,7 +93,7 @@ LEFT JOIN t_category c ON a.category_id = c.id LEFT JOIN t_user_info u ON a.user_id = u.id where a.is_delete = 0 - and a.status = 1 + and a.status in (1, 2) order by is_top desc, is_featured desc