diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/R.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/R.java index b097d4e0a..65a8defd5 100644 --- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/R.java +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/util/R.java @@ -31,9 +31,9 @@ import java.io.Serializable; * @param * @author lengleng */ -@ToString -@Accessors(chain=true) @Builder +@ToString +@Accessors(chain = true) @AllArgsConstructor public class R implements Serializable { private static final long serialVersionUID = 1L; diff --git a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java index 6c6fadceb..e60e08513 100644 --- a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java +++ b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/LogAutoConfiguration.java @@ -26,12 +26,15 @@ import lombok.AllArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; /** * @author lengleng * @date 2018/6/28 + *

* 日志自动配置 */ +@EnableAsync @Configuration @AllArgsConstructor @ConditionalOnWebApplication diff --git a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java index d62361653..71073b3ac 100644 --- a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java +++ b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/aspect/SysLogAspect.java @@ -27,14 +27,15 @@ import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; /** * 操作日志使用spring event异步入库 * * @author L.cm */ -@Aspect @Slf4j +@Aspect public class SysLogAspect { @Around("@annotation(sysLog)") diff --git a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java index 74d8801c5..8af58281d 100644 --- a/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java +++ b/pigx-common/pigx-common-log/src/main/java/com/pig4cloud/pigx/common/log/event/SysLogListener.java @@ -21,6 +21,7 @@ package com.pig4cloud.pigx.common.log.event; import com.pig4cloud.pigx.admin.api.entity.SysLog; import com.pig4cloud.pigx.admin.api.feign.RemoteLogService; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.event.EventListener; @@ -42,6 +43,6 @@ public class SysLogListener { @EventListener(SysLogEvent.class) public void saveSysLog(SysLogEvent event) { SysLog sysLog = (SysLog) event.getSource(); - remoteLogService.saveLog(sysLog); + remoteLogService.saveLog(sysLog, SecurityConstants.FROM_IN); } } diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/annotation/Inner.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/annotation/Inner.java new file mode 100644 index 000000000..82d7e4966 --- /dev/null +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/annotation/Inner.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.common.security.annotation; + +import java.lang.annotation.*; + +/** + * @author lengleng + * @date 2018/11/26 + *

+ * 服务调用不鉴权注解 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Inner { + + /** + * 是否AOP统一处理 + * + * @return false, true + */ + boolean value() default true; + + /** + * 需要特殊判空的字段(预留) + * + * @return {} + */ + String[] field() default {}; +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/GlobalExceptionHandlerResolver.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/GlobalExceptionHandlerResolver.java index 7a3b21fc7..4e145edfa 100644 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/GlobalExceptionHandlerResolver.java +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/GlobalExceptionHandlerResolver.java @@ -19,10 +19,10 @@ package com.pig4cloud.pigx.common.security.component; import com.pig4cloud.pigx.common.core.constant.CommonConstant; import com.pig4cloud.pigx.common.core.util.R; -import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.core.SpringSecurityMessageSource; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -51,7 +51,10 @@ public class GlobalExceptionHandlerResolver { @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public R handleGlobalException(Exception e) { log.error("全局异常信息 ex={}", e.getMessage(), e); - return new R<>(e); + return R.builder() + .msg(e.getLocalizedMessage()) + .code(CommonConstant.FAIL) + .build(); } /** @@ -63,9 +66,12 @@ public class GlobalExceptionHandlerResolver { @ExceptionHandler(AccessDeniedException.class) @ResponseStatus(HttpStatus.FORBIDDEN) public R handleAccessDeniedException(AccessDeniedException e) { - log.error("拒绝授权异常信息 ex={}",e.getLocalizedMessage(),e); + String msg = SpringSecurityMessageSource.getAccessor() + .getMessage("AbstractAccessDecisionManager.accessDenied" + , e.getMessage()); + log.error("拒绝授权异常信息 ex={}", msg, e); return R.builder() - .msg(e.getLocalizedMessage()) + .msg(msg) .code(CommonConstant.FAIL) .build(); } @@ -80,7 +86,7 @@ public class GlobalExceptionHandlerResolver { @ResponseStatus(HttpStatus.BAD_REQUEST) public R handleBodyValidException(MethodArgumentNotValidException exception) { List fieldErrors = exception.getBindingResult().getFieldErrors(); - log.error("参数绑定异常,ex = {}",fieldErrors.get(0).getDefaultMessage()); + log.error("参数绑定异常,ex = {}", fieldErrors.get(0).getDefaultMessage()); return R.builder() .msg(fieldErrors.get(0).getDefaultMessage()) .code(CommonConstant.FAIL) diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxSecurityInnerAspect.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxSecurityInnerAspect.java new file mode 100644 index 000000000..9f40c1bf3 --- /dev/null +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxSecurityInnerAspect.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018-2025, lengleng All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * Neither the name of the pig4cloud.com developer nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * Author: lengleng (wangiegie@gmail.com) + */ + +package com.pig4cloud.pigx.common.security.component; + +import cn.hutool.core.util.StrUtil; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.security.annotation.Inner; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author lengleng + * @date 2018/11/26 + *

+ * 服务间接口不鉴权处理逻辑 + */ +@Slf4j +@Aspect +@Component +@AllArgsConstructor +public class PigxSecurityInnerAspect { + private final HttpServletRequest request; + + @Around("@annotation(inner)") + public Object around(ProceedingJoinPoint point, Inner inner) throws Throwable { + String header = request.getHeader(SecurityConstants.FROM); + if (inner.value() && !StrUtil.equals(SecurityConstants.FROM_IN, header)) { + log.warn("访问接口 {} 没有权限", point.getSignature().getName()); + throw new AccessDeniedException("Access is denied"); + } + return point.proceed(); + } + +} diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsServiceImpl.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsServiceImpl.java index e6f713817..65c3149d2 100644 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsServiceImpl.java +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/service/PigxUserDetailsServiceImpl.java @@ -72,7 +72,7 @@ public class PigxUserDetailsServiceImpl implements PigxUserDetailsService { */ @Override public UserDetails loadUserBySocial(String inStr) throws UsernameNotFoundException { - return getUserDetails(remoteUserService.social(inStr)); + return getUserDetails(remoteUserService.social(inStr, SecurityConstants.FROM_IN)); } /** diff --git a/pigx-config/src/main/resources/config/pigx-upms-biz-dev.yml b/pigx-config/src/main/resources/config/pigx-upms-biz-dev.yml index 716fd594e..1f5366c63 100644 --- a/pigx-config/src/main/resources/config/pigx-upms-biz-dev.yml +++ b/pigx-config/src/main/resources/config/pigx-upms-biz-dev.yml @@ -10,9 +10,9 @@ security: - '/actuator/**' - '/v2/api-docs' - '/user/info/*' - - '/social/info/**' + - '/social/info/*' - '/mobile/*' - - '/log/**' + - '/log/save' # 数据源 spring: diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java index 54a3de806..683355714 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteLogService.java @@ -21,11 +21,13 @@ package com.pig4cloud.pigx.admin.api.feign; import com.pig4cloud.pigx.admin.api.entity.SysLog; import com.pig4cloud.pigx.admin.api.feign.factory.RemoteLogServiceFallbackFactory; +import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import com.pig4cloud.pigx.common.core.constant.ServiceNameConstant; import com.pig4cloud.pigx.common.core.util.R; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; /** * @author lengleng @@ -37,8 +39,9 @@ public interface RemoteLogService { * 保存日志 * * @param sysLog 日志实体 + * @param from 是否内部调用 * @return succes、false */ - @PostMapping("/log") - R saveLog(@RequestBody SysLog sysLog); + @PostMapping("/log/save") + R saveLog(@RequestBody SysLog sysLog, @RequestHeader(SecurityConstants.FROM) String from); } diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java index 0bfb7a559..41496485e 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/RemoteUserService.java @@ -53,10 +53,12 @@ public interface RemoteUserService { * 通过社交账号或手机号查询用户、角色信息 * * @param inStr appid@code + * @param from 调用标志 * @return */ @GetMapping("/social/info/{inStr}") - R social(@PathVariable("inStr") String inStr); + R social(@PathVariable("inStr") String inStr + , @RequestHeader(SecurityConstants.FROM) String from); /** * 查询上级部门的用户信息 diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java index 4d0fbca3d..c95c1a393 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteLogServiceFallbackImpl.java @@ -40,10 +40,11 @@ public class RemoteLogServiceFallbackImpl implements RemoteLogService { * 保存日志 * * @param sysLog + * @param from * @return R */ @Override - public R saveLog(SysLog sysLog) { + public R saveLog(SysLog sysLog, String from) { log.error("feign 插入日志失败", cause); return null; } diff --git a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java index bdf8eedbb..1702fc84a 100644 --- a/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java +++ b/pigx-upms/pigx-upms-api/src/main/java/com/pig4cloud/pigx/admin/api/feign/fallback/RemoteUserServiceFallbackImpl.java @@ -56,10 +56,11 @@ public class RemoteUserServiceFallbackImpl implements RemoteUserService { * 通过社交账号查询用户、角色信息 * * @param inStr appid@code + * @param from 内外标志 * @return */ @Override - public R social(String inStr) { + public R social(String inStr, String from) { log.error("feign 查询用户信息失败:{}", inStr, cause); return null; } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/LogController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/LogController.java index 1757c9c5d..03a740974 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/LogController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/LogController.java @@ -26,6 +26,7 @@ import com.pig4cloud.pigx.admin.api.entity.SysLog; import com.pig4cloud.pigx.admin.api.vo.PreLogVo; import com.pig4cloud.pigx.admin.service.SysLogService; import com.pig4cloud.pigx.common.core.util.R; +import com.pig4cloud.pigx.common.security.annotation.Inner; import io.swagger.annotations.Api; import lombok.AllArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; @@ -79,7 +80,8 @@ public class LogController { * @param sysLog 日志实体 * @return success/false */ - @PostMapping + @Inner + @PostMapping("/save") public R save(@Valid @RequestBody SysLog sysLog) { return new R<>(sysLogService.save(sysLog)); } diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysSocialDetailsController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysSocialDetailsController.java index fb9de4980..ae5b79e52 100755 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysSocialDetailsController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/SysSocialDetailsController.java @@ -23,6 +23,7 @@ import com.pig4cloud.pigx.admin.api.entity.SysSocialDetails; import com.pig4cloud.pigx.admin.service.SysSocialDetailsService; import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.common.security.annotation.Inner; import io.swagger.annotations.Api; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -111,6 +112,7 @@ public class SysSocialDetailsController { * @param inStr appid@code * @return */ + @Inner @GetMapping("/info/{inStr}") public R getUserInfo(@PathVariable String inStr) { return new R<>(sysSocialDetailsService.getUserInfo(inStr)); diff --git a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/UserController.java b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/UserController.java index fae123067..bf832570e 100644 --- a/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/UserController.java +++ b/pigx-upms/pigx-upms-biz/src/main/java/com/pig4cloud/pigx/admin/controller/UserController.java @@ -19,16 +19,15 @@ package com.pig4cloud.pigx.admin.controller; -import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.pig4cloud.pigx.admin.api.dto.UserDTO; import com.pig4cloud.pigx.admin.api.entity.SysUser; import com.pig4cloud.pigx.admin.service.SysUserService; -import com.pig4cloud.pigx.common.core.constant.SecurityConstants; import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.common.log.annotation.SysLog; +import com.pig4cloud.pigx.common.security.annotation.Inner; import com.pig4cloud.pigx.common.security.util.SecurityUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -51,34 +50,39 @@ public class UserController { private final SysUserService userService; /** - * 获取当前用户信息(角色、权限) - * 并且异步初始化用户部门信息 + * 获取当前用户全部信息 * - * @param from 请求标志,该接口会被 auth、 前端调用 - * @param username 用户名 - * @return 用户名 + * @return 用户信息 */ - @GetMapping(value = {"/info", "/info/{username}"}) - public R user(@PathVariable(required = false) String username, - @RequestHeader(required = false) String from) { - // 查询用户不为空时判断是不是内部请求 - if (StrUtil.isNotBlank(username) && !StrUtil.equals(SecurityConstants.FROM_IN, from)) { - return new R<>(null, "error"); - } - //为空时查询当前用户 - if (StrUtil.isBlank(username)) { - username = SecurityUtils.getUser().getUsername(); - } + @GetMapping(value = {"/info"}) + public R info() { + String username = SecurityUtils.getUser().getUsername(); SysUser sysUser = userService.getOne(Wrappers.query() .lambda().eq(SysUser::getUsername, username)); if (sysUser == null) { - return new R<>(); + return new R<>(Boolean.FALSE, "获取当前用户信息失败"); } return new R<>(userService.findUserInfo(sysUser)); } /** - * 通过ID查询当前用户信息 + * 获取指定用户全部信息 + * + * @return 用户信息 + */ + @Inner + @GetMapping("/info/{username}") + public R info(@PathVariable String username) { + SysUser user = userService.getOne(Wrappers.query() + .lambda().eq(SysUser::getUsername, username)); + if (user == null) { + return new R<>(Boolean.FALSE, String.format("用户信息为空 %s", username)); + } + return new R<>(userService.findUserInfo(user)); + } + + /** + * 通过ID查询用户信息 * * @param id ID * @return 用户信息 @@ -169,7 +173,7 @@ public class UserController { /** * @param username 用户名称 - * @return + * @return 上级部门用户列表 */ @GetMapping("/ancestor/{username}") public R listAncestorUsers(@PathVariable String username) { diff --git a/pigx-visual/pigx-sso-client-demo/src/main/java/com/pig4cloud/pigx/sso/PigxSsoClientDemoApplication.java b/pigx-visual/pigx-sso-client-demo/src/main/java/com/pig4cloud/pigx/sso/PigxSsoClientDemoApplication.java index 37c8ccc8d..25a0f5a64 100644 --- a/pigx-visual/pigx-sso-client-demo/src/main/java/com/pig4cloud/pigx/sso/PigxSsoClientDemoApplication.java +++ b/pigx-visual/pigx-sso-client-demo/src/main/java/com/pig4cloud/pigx/sso/PigxSsoClientDemoApplication.java @@ -26,7 +26,8 @@ import org.springframework.cloud.client.SpringCloudApplication; * @date 2018年11月15日17:06:26 *

* 单点登录客户端 - * 访问:http://localhost:4040/sso1/ + * 1. 启动实例访问:http://localhost:4040/sso1/ 提示登录,然后获取到用户信息 + * 2. 再启动一个实例: http://localhost:4040/sso1/ 不需要登录即可获取当前用户信息 */ @EnableOAuth2Sso @SpringCloudApplication