sandu-common/src/main/java/com/sandu/common/log/AccessLog.java
@@ -26,9 +26,7 @@ /** æ¹æ³å */ private String method; /** * ç±»å 0-åå° 1-åå° */ private Integer type; /** åæ° */ sandu-common/src/main/java/com/sandu/common/log/Log.java
@@ -1,3 +1,9 @@ /** * Copyright (C) 2018-2020 * All rights reserved, Designed By www.yixiang.co * 注æï¼ * æ¬è½¯ä»¶ä¸ºwww.yixiang.coå¼åç å¶ */ package com.sandu.common.log; import java.lang.annotation.ElementType; @@ -6,20 +12,13 @@ import java.lang.annotation.Target; /** * * @author chenjiantian */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { /** * æ¥å¿æè¿° * @return */ String value() default ""; /** * ç±»å 0-åå° 1-åå° * @return */ int type() default 0; } sandu-common/src/main/java/com/sandu/common/log/LogAspect.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,83 @@ /** * Copyright (C) 2018-2020 * All rights reserved, Designed By www.yixiang.co * 注æï¼ * æ¬è½¯ä»¶ä¸ºwww.yixiang.coå¼åç å¶ */ package com.sandu.common.log; import com.sandu.common.enums.LogTypeEnums; import com.sandu.common.util.RequestHolder; import com.sandu.common.util.ThrowableUtil; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; /** * @author hupeng * @date 2018-11-24 */ @Component @Aspect @Slf4j public class LogAspect { private final LogServiceImpl logService; ThreadLocal<Long> currentTime = new ThreadLocal<>(); public LogAspect(LogServiceImpl logService) { this.logService = logService; } /** * é ç½®åå ¥ç¹ */ @Pointcut("@annotation(com.sandu.common.log.Log)") public void logPointcut() { // è¯¥æ¹æ³æ æ¹æ³ä½,主è¦ä¸ºäºè®©åç±»ä¸å ¶ä»æ¹æ³ä½¿ç¨æ¤åå ¥ç¹ } /** * é ç½®ç¯ç»éç¥,使ç¨å¨æ¹æ³logPointcut()䏿³¨åçåå ¥ç¹ * * @param joinPoint join point for advice */ @Around("logPointcut()") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { Object result; currentTime.set(System.currentTimeMillis()); result = joinPoint.proceed(); AccessLog log = new AccessLog(); log.setLogType(LogTypeEnums.NORMAL.getCode()); log.setTime(System.currentTimeMillis() - currentTime.get()); currentTime.remove(); logService.saveOperation(RequestHolder.getHttpServletRequest(), joinPoint, log); return result; } /** * é ç½®å¼å¸¸éç¥ * * @param joinPoint join point for advice * @param e exception */ @AfterThrowing(pointcut = "logPointcut()", throwing = "e") public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { AccessLog log = new AccessLog(); log.setTime(System.currentTimeMillis() - currentTime.get()); currentTime.remove(); log.setLogType(LogTypeEnums.ERROR.getCode()); log.setExceptionDetail(ThrowableUtil.getStackTrace(e)); HttpServletRequest request = RequestHolder.getHttpServletRequest(); logService.saveOperation(request, (ProceedingJoinPoint) joinPoint, log); } } sandu-common/src/main/java/com/sandu/common/log/LogDao.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,12 @@ package com.sandu.common.log; import com.sandu.common.domain.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * @author chenjiantian * @date 2021/7/20 14:53 */ @Mapper public interface LogDao extends BaseMapper<AccessLog> { } sandu-common/src/main/java/com/sandu/common/log/LogService.java
@@ -1,27 +1,58 @@ package com.sandu.common.log; import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentInfo; import cn.hutool.http.useragent.UserAgentUtil; import com.sandu.common.security.SecurityUtils; import com.sandu.common.service.impl.BaseServiceImpl; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.scheduling.annotation.Async; import org.springframework.transaction.annotation.Transactional; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.util.Optional; /** * @author hupeng * @date 2018-11-24 */ public interface LogService { @Service public class LogService extends BaseServiceImpl<LogDao, AccessLog> implements LogServiceImpl { /** * ä¿åæ¥å¿æ°æ® * * @param request / * @param joinPoint / * @param operationLog / */ @Async @Transactional(rollbackFor = Exception.class) void saveOperation(HttpServletRequest request, ProceedingJoinPoint joinPoint, AccessLog operationLog); @Override public void saveOperation(HttpServletRequest request, ProceedingJoinPoint joinPoint, AccessLog accessLog) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Log aopLog = method.getAnnotation(Log.class); // æ¹æ³è·¯å¾ String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()"; StringBuilder params = new StringBuilder("{"); //åæ°å¼ Object[] argValues = joinPoint.getArgs(); //åæ°åç§° String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); if (argValues != null) { for (int i = 0; i < argValues.length; i++) { params.append(" ").append(argNames[i]).append(": ").append(argValues[i]); } } accessLog.setDescription(aopLog.value()); //ç±»å 0-åå° 1-åå° accessLog.setType(aopLog.type()); accessLog.setUid(SecurityUtils.getUserId()); UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); accessLog.setBrowser(Optional.ofNullable(userAgent).map(UserAgent::getBrowser).map(UserAgentInfo::getName).orElse("")); accessLog.setRequestIp(ServletUtil.getClientIP(request)); accessLog.setMethod(methodName); accessLog.setUsername(SecurityUtils.getUsername()); accessLog.setParams(params.toString() + " }"); this.save(accessLog); } } sandu-common/src/main/java/com/sandu/common/log/LogServiceImpl.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,32 @@ /** * Copyright (C) 2018-2020 * All rights reserved, Designed By www.yixiang.co * 注æï¼ * æ¬è½¯ä»¶ä¸ºwww.yixiang.coå¼åç å¶ */ package com.sandu.common.log; import com.sandu.common.service.BaseService; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.scheduling.annotation.Async; import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletRequest; /** * @author hupeng * @date 2018-11-24 */ public interface LogServiceImpl { /** * ä¿åæ¥å¿æ°æ® * @param request / * @param joinPoint / * @param operationLog / */ @Async @Transactional(rollbackFor = Exception.class) void saveOperation(HttpServletRequest request, ProceedingJoinPoint joinPoint, AccessLog operationLog); } sandu-common/src/main/java/com/sandu/common/redis/online/OnlineUser.java
@@ -1,26 +1,26 @@ //package com.sandu.common.redis.online; // //import lombok.AllArgsConstructor; //import lombok.Data; //import lombok.NoArgsConstructor; // //import java.time.LocalDateTime; // ///** // * @author chenjiantian // * @date 2021/8/6 16:31 // */ //@Data //@AllArgsConstructor //@NoArgsConstructor //public class OnlineUser { // // private Long userId; // // è¿éæææºå· // private String userName; // private String token; // private String ip; // private String browser; // private LocalDateTime loginTime; // //} package com.sandu.common.redis.online; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDateTime; /** * @author chenjiantian * @date 2021/8/6 16:31 */ @Data @AllArgsConstructor @NoArgsConstructor public class OnlineUser { private Long userId; // è¿éæææºå· private String userName; private String token; private String ip; private String browser; private LocalDateTime loginTime; } sandu-common/src/main/java/com/sandu/common/redis/online/OnlineUserService.java
@@ -1,115 +1,115 @@ //package com.sandu.common.redis.online; // //import cn.hutool.extra.servlet.ServletUtil; //import cn.hutool.http.useragent.UserAgent; //import cn.hutool.http.useragent.UserAgentInfo; //import cn.hutool.http.useragent.UserAgentUtil; //import com.baomidou.mybatisplus.core.toolkit.StringUtils; //import com.sandu.common.redis.RedisService; //import com.sandu.common.security.config.SecurityProperties; //import lombok.extern.slf4j.Slf4j; //import org.springframework.security.core.userdetails.UserDetails; // //import javax.servlet.http.HttpServletRequest; //import java.time.LocalDateTime; //import java.util.ArrayList; //import java.util.List; //import java.util.Optional; //import java.util.Set; // ///** // * @author chenjiantian // * @date 2021/8/6 16:26 // * å¨çº¿ç¨æ·æå¡ç±» // * å¨ BaseRedisConfig æ³¨å ¥ // */ //@Slf4j //public class OnlineUserService { // // private final SecurityProperties properties; // private final RedisService redisService; // // public OnlineUserService(SecurityProperties properties, RedisService redisService) { // this.properties = properties; // this.redisService = redisService; // } // // /** // * ä¿åå¨çº¿ç¨æ·ä¿¡æ¯ // */ // public void save(UserDetails userDetails, String token, Long userId,HttpServletRequest request) { // String ip = ServletUtil.getClientIP(request); // UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); // String browser = Optional.ofNullable(userAgent).map(UserAgent::getBrowser).map(UserAgentInfo::getName).orElse(""); // OnlineUser onlineUser = new OnlineUser(userId,userDetails.getUsername(), token, ip, browser, LocalDateTime.now()); //// redisService.set(properties.getOnlineKey() + token, onlineUser, properties.getTokenValidityInSeconds() / 1000); // redisService.set(properties.getOnlineKey() + userDetails.getUsername(), onlineUser); // } // // /** // * æ¥è¯¢å ¨é¨æ°æ® // * // * @param filter // * @return // */ // public List<OnlineUser> getAll(String filter) { // Set<String> keys = redisService.keys(properties.getOnlineKey() + "*"); // // List<OnlineUser> onlineUsers = new ArrayList<>(); // for (String key : keys) { // OnlineUser onlineUser = (OnlineUser) redisService.get(key); // if (StringUtils.isNotBlank(filter)) { // if (onlineUser.toString().contains(filter)) { // onlineUsers.add(onlineUser); // } // } else { // onlineUsers.add(onlineUser); // } // } // onlineUsers.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime())); // return onlineUsers; // } // // private boolean kickOut(String token) throws Exception { // token = properties.getOnlineKey() + token; // return redisService.del(token); // } // // public OnlineUser getOne(String key) { // return (OnlineUser) redisService.get(key); // } // // /** // * æ£æµç¨æ·æ¯å¦å¨ä¹åå·²ç»ç»å½ï¼å·²ç»ç»å½è¸¢ä¸çº¿ // * // * @param userName ç¨æ·å // */ // public void checkLoginOnUser(String userName, String ignoreToken) { //// List<OnlineUser> onlineUsers = getAll(userName); //// if (onlineUsers == null || onlineUsers.isEmpty()) { //// return; //// } // OnlineUser onlineUser = getOne(properties.getOnlineKey() + userName); // if(onlineUser == null){ package com.sandu.common.redis.online; import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentInfo; import cn.hutool.http.useragent.UserAgentUtil; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.sandu.common.redis.RedisService; import com.sandu.common.security.config.SecurityProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.userdetails.UserDetails; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; /** * @author chenjiantian * @date 2021/8/6 16:26 * å¨çº¿ç¨æ·æå¡ç±» * å¨ BaseRedisConfig æ³¨å ¥ */ @Slf4j public class OnlineUserService { private final SecurityProperties properties; private final RedisService redisService; public OnlineUserService(SecurityProperties properties, RedisService redisService) { this.properties = properties; this.redisService = redisService; } /** * ä¿åå¨çº¿ç¨æ·ä¿¡æ¯ */ public void save(UserDetails userDetails, String token, Long userId,HttpServletRequest request) { String ip = ServletUtil.getClientIP(request); UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); String browser = Optional.ofNullable(userAgent).map(UserAgent::getBrowser).map(UserAgentInfo::getName).orElse(""); OnlineUser onlineUser = new OnlineUser(userId,userDetails.getUsername(), token, ip, browser, LocalDateTime.now()); // redisService.set(properties.getOnlineKey() + token, onlineUser, properties.getTokenValidityInSeconds() / 1000); redisService.set(properties.getOnlineKey() + userDetails.getUsername(), onlineUser); } /** * æ¥è¯¢å ¨é¨æ°æ® * * @param filter * @return */ public List<OnlineUser> getAll(String filter) { Set<String> keys = redisService.keys(properties.getOnlineKey() + "*"); List<OnlineUser> onlineUsers = new ArrayList<>(); for (String key : keys) { OnlineUser onlineUser = (OnlineUser) redisService.get(key); if (StringUtils.isNotBlank(filter)) { if (onlineUser.toString().contains(filter)) { onlineUsers.add(onlineUser); } } else { onlineUsers.add(onlineUser); } } onlineUsers.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime())); return onlineUsers; } private boolean kickOut(String token) throws Exception { token = properties.getOnlineKey() + token; return redisService.del(token); } public OnlineUser getOne(String key) { return (OnlineUser) redisService.get(key); } /** * æ£æµç¨æ·æ¯å¦å¨ä¹åå·²ç»ç»å½ï¼å·²ç»ç»å½è¸¢ä¸çº¿ * * @param userName ç¨æ·å */ public void checkLoginOnUser(String userName, String ignoreToken) { // List<OnlineUser> onlineUsers = getAll(userName); // if (onlineUsers == null || onlineUsers.isEmpty()) { // return; // } //// for (OnlineUser onlineUser : onlineUsers) { // if (onlineUser.getUserName().equals(userName)) { // try { // String token = onlineUser.getToken(); // if (StringUtils.isNotBlank(ignoreToken) && !ignoreToken.equals(token)) { // this.kickOut(token); // } else if (StringUtils.isBlank(ignoreToken)) { // this.kickOut(token); // } // } catch (Exception e) { // log.error("checkUser is error", e); // } // } //// } // } // // public void updateOne(OnlineUser onlineUser) { // redisService.set(properties.getOnlineKey() + onlineUser.getUserName(), onlineUser); // } //} OnlineUser onlineUser = getOne(properties.getOnlineKey() + userName); if(onlineUser == null){ return; } // for (OnlineUser onlineUser : onlineUsers) { if (onlineUser.getUserName().equals(userName)) { try { String token = onlineUser.getToken(); if (StringUtils.isNotBlank(ignoreToken) && !ignoreToken.equals(token)) { this.kickOut(token); } else if (StringUtils.isBlank(ignoreToken)) { this.kickOut(token); } } catch (Exception e) { log.error("checkUser is error", e); } } // } } public void updateOne(OnlineUser onlineUser) { redisService.set(properties.getOnlineKey() + onlineUser.getUserName(), onlineUser); } } sandu-common/src/main/java/com/sandu/common/security/SecurityUtils.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,90 @@ /** * Copyright (C) 2018-2020 * All rights reserved, Designed By www.yixiang.co * 注æï¼ * æ¬è½¯ä»¶ä¸ºwww.yixiang.coå¼åç å¶ */ package com.sandu.common.security; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import com.sandu.common.redis.online.OnlineUser; import com.sandu.common.redis.online.OnlineUserService; import com.sandu.common.security.config.SecurityProperties; import com.sandu.common.security.jwt.JwtTokenProvider; import com.sandu.common.util.RequestHolder; import com.sandu.common.util.SpringContextHolder; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import javax.servlet.http.HttpServletRequest; /** * è·åå½åç»å½çç¨æ· * * @author Zheng Jie * @date 2019-01-17 */ public class SecurityUtils { public static UserDetails getUserDetails() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { // throw new BusinessException(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()); return null; } if (authentication.getPrincipal() instanceof UserDetails) { UserDetails userDetails = (UserDetails) authentication.getPrincipal(); UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class); return userDetailsService.loadUserByUsername(userDetails.getUsername()); } return null; // throw new BusinessException(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()); } /** * è·åç³»ç»ç¨æ·åç§° * * @return ç³»ç»ç¨æ·åç§° */ public static String getUsername() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { // throw new BusinessException(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()); return "æ ç»å½"; } // UserDetails userDetails = (UserDetails) authentication.getPrincipal(); // return userDetails.getUsername(); return (String)authentication.getPrincipal(); } /** * è·åç³»ç»ç¨æ·id * * @return ç³»ç»ç¨æ·id */ public static Long getUserId() { SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class); if (!properties.isCacheOnline()) { Object obj = getUserDetails(); if (obj == null) { return null; } JSONObject json = new JSONObject(obj); return json.getJSONObject("user").get("id", Long.class); } else { HttpServletRequest httpServletRequest = RequestHolder.getHttpServletRequest(); JwtTokenProvider tokenProvider = SpringContextHolder.getBean(JwtTokenProvider.class); OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class); String username = tokenProvider.getSubjectForce(tokenProvider.getToken(httpServletRequest)); OnlineUser one = onlineUserService.getOne(properties.getOnlineKey() + username); if (one != null && StrUtil.equals(one.getToken(), tokenProvider.getToken(httpServletRequest))) { return one.getUserId(); } else { return null; } } } } ximon-admin/src/main/java/com/sandu/ximon/admin/controller/AdminController.java
@@ -9,6 +9,7 @@ import com.sandu.common.domain.ResponseVO; import com.sandu.common.enums.AdminStatusStatus; import com.sandu.common.enums.ResponseStatusEnums; import com.sandu.common.log.Log; import com.sandu.common.object.BaseConditionVO; import com.sandu.common.security.LoginUserInfo; import com.sandu.common.security.annotation.AnonymousAccess; @@ -62,7 +63,7 @@ private final RoleService roleService; private final TokenProvider tokenProvider; @Log("åå°ç¨æ·ç»å½") @AnonymousAccess @PostMapping(value = "/login") public ResponseVO<Object> login(@RequestBody AdminLoginParam loginParam) {