diff --git a/README.md b/README.md index c45ad0d02..b25cad861 100644 --- a/README.md +++ b/README.md @@ -157,10 +157,14 @@ youlai-mall | ------------------------------------------------------------ | ------------------------------------------------------------ | | ![image-20210622000304570](https://gitee.com/haoxr/image/raw/master/image-20210622000304570.png) | ![image-20210622000046029](https://gitee.com/haoxr/image/raw/master/image-20210622000046029.png) | +## 项目文档 +[项目文档地址](https://www.cnblogs.com/haoxianrui/) -## Stargazers over time +## Star趋势 +- Github [![Github](https://starchart.cc/hxrui/youlai-mall.svg)](https://starchart.cc/hxrui/youlai-mall) +- Gitee [![Gitee](https://whnb.wang/stars/youlaitech/youlai-mall)](https://whnb.wang/stars/youlaitech/youlai-mall) ## contributors @@ -168,7 +172,7 @@ youlai-mall ## 联系信息 -因为微信交流群超过200人了,只能通过邀请进入群聊,添加开发人员(PS:日常上班时间建议选择没有头像的)后由其拉进群,相互交流学习,备注“**有来**”即可。 +因为微信交流群满200人只能通过邀请进入,如果想进入交流群学习可添加以下开发人员,备注“**有来**“由其拉进群。 | ![](https://gitee.com/haoxr/image/raw/master/default/113__6c5ed5b1b73ea9cd4cf32848ed350c07_b9b214638a2a406e52dbf51e9bf9a2ef.png) | ![](https://gitee.com/haoxr/image/raw/master/hxr.jpg) | ![](https://gitee.com/haoxr/image/raw/master/huawei.jpg) | ![](https://gitee.com/haoxr/image/raw/master/default/1625149769(1).png) | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | diff --git a/docs/nacos/DEFAULT_GROUP.zip b/docs/nacos/DEFAULT_GROUP.zip index 68211b613..46b0b9012 100644 Binary files a/docs/nacos/DEFAULT_GROUP.zip and b/docs/nacos/DEFAULT_GROUP.zip differ diff --git a/pom.xml b/pom.xml index 5423715cc..5c78e03b6 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ org.springframework.boot spring-boot-starter-parent - 2.5.0 + 2.5.2 @@ -247,4 +247,16 @@ + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + true + + + + diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DashboardController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DashboardController.java similarity index 99% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DashboardController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DashboardController.java index 4b4879063..772c1c2bf 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DashboardController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DashboardController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DeptController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DeptController.java similarity index 99% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DeptController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DeptController.java index 68dbf4aeb..8fd5f8b49 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DeptController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DeptController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DictController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DictController.java similarity index 99% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DictController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DictController.java index 189b5f180..49f486f15 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DictController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DictController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.lang.Assert; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DictItemController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DictItemController.java similarity index 99% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DictItemController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DictItemController.java index f661b60a5..d0fb56cce 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/DictItemController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/DictItemController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/FileController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/FileController.java similarity index 98% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/FileController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/FileController.java index ad60e2c15..bfab7cee6 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/FileController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/FileController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.util.IdUtil; import com.youlai.admin.service.impl.MinioService; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/MenuController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/MenuController.java similarity index 99% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/MenuController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/MenuController.java index ecbb24e6a..a2ff46bfa 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/MenuController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/MenuController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/OauthClientController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/OauthClientController.java similarity index 98% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/OauthClientController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/OauthClientController.java index 09c07764f..011b07217 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/OauthClientController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/OauthClientController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/PermissionController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/PermissionController.java similarity index 99% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/PermissionController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/PermissionController.java index 848a50522..091f7853f 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/PermissionController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/PermissionController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/RoleController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/RoleController.java similarity index 95% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/RoleController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/RoleController.java index 4457b0bd4..366e3a51f 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/RoleController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/RoleController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; @@ -90,9 +90,11 @@ public class RoleController { @PostMapping public Result add(@RequestBody SysRole role) { int count = iSysRoleService.count(new LambdaQueryWrapper() - .eq(SysRole::getCode, role.getCode()) + .eq(SysRole::getCode, role.getCode() ) + .or() + .eq(SysRole::getName,role.getName()) ); - Assert.isTrue(count == 0, "角色编码已存在"); + Assert.isTrue(count == 0, "角色名称或角色编码重复,请检查!"); boolean result = iSysRoleService.save(role); return Result.judge(result); } @@ -108,9 +110,11 @@ public class RoleController { @RequestBody SysRole role) { int count = iSysRoleService.count(new LambdaQueryWrapper() .eq(SysRole::getCode, role.getCode()) + .or() + .eq(SysRole::getName,role.getName()) .ne(SysRole::getId, id) ); - Assert.isTrue(count == 0, "角色编码已存在"); + Assert.isTrue(count == 0, "角色名称或角色编码重复,请检查!"); boolean result = iSysRoleService.updateById(role); if (result) { iSysPermissionService.refreshPermRolesRules(); diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/RouteController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/RouteController.java similarity index 95% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/RouteController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/RouteController.java index c6f9103a4..69861b360 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/RouteController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/RouteController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import com.youlai.admin.pojo.vo.RouteVO; import com.youlai.admin.service.ISysMenuService; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/TokenController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/TokenController.java similarity index 96% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/TokenController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/TokenController.java index 7ba841b55..32e636bfb 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/TokenController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/TokenController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import com.youlai.admin.service.ITokenService; import com.youlai.common.result.Result; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/UserController.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/UserController.java similarity index 99% rename from youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/UserController.java rename to youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/UserController.java index 78799a26a..c2642d3bd 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/v1/UserController.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/controller/UserController.java @@ -1,4 +1,4 @@ -package com.youlai.admin.controller.v1; +package com.youlai.admin.controller; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; diff --git a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/service/impl/SysMenuServiceImpl.java b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/service/impl/SysMenuServiceImpl.java index 3d1353b6b..da97e814f 100644 --- a/youlai-admin/admin-boot/src/main/java/com/youlai/admin/service/impl/SysMenuServiceImpl.java +++ b/youlai-admin/admin-boot/src/main/java/com/youlai/admin/service/impl/SysMenuServiceImpl.java @@ -106,7 +106,7 @@ public class SysMenuServiceImpl extends ServiceImpl impl .forEach(menu -> { RouteVO routeVO = new RouteVO(); - routeVO.setName(menu.getRouteName()); // 根据name路由跳转 this.$router.push({path:xxx}) + routeVO.setName(menu.getId() + ""); // 根据name路由跳转 this.$router.push({path:xxx}) routeVO.setPath(menu.getRoutePath()); // 根据path路由跳转 this.$router.push({name:xxx}) routeVO.setRedirect(menu.getRedirect()); routeVO.setComponent(menu.getComponent()); diff --git a/youlai-admin/admin-boot/src/main/resources/bootstrap-dev.yml b/youlai-admin/admin-boot/src/main/resources/bootstrap-dev.yml index 6e64965d4..153c5eb17 100644 --- a/youlai-admin/admin-boot/src/main/resources/bootstrap-dev.yml +++ b/youlai-admin/admin-boot/src/main/resources/bootstrap-dev.yml @@ -11,26 +11,3 @@ spring: config: server-addr: ${spring.cloud.nacos.discovery.server-addr} file-extension: yaml - sentinel: - enabled: true - eager: true # 取消控制台懒加载,项目启动即连接Sentinel - transport: - client-ip: localhost - dashboard: localhost:8080 - datasource: - # 限流规则,flow为key,随便定义 - flow: - nacos: - server-addr: ${spring.cloud.nacos.discovery.server-addr} - dataId: ${spring.application.name}-flow-rules - groupId: SENTINEL_GROUP - data-type: json - rule-type: flow - # 降级规则 - degrade: - nacos: - server-addr: ${spring.cloud.nacos.discovery.server-addr} - dataId: ${spring.application.name}-degrade-rules - groupId: SENTINEL_GROUP - data-type: json - rule-type: degrade diff --git a/youlai-auth/src/main/java/com/youlai/auth/controller/OAuthController.java b/youlai-auth/src/main/java/com/youlai/auth/controller/OAuthController.java index 6f54d1038..c4a9ccff0 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/controller/OAuthController.java +++ b/youlai-auth/src/main/java/com/youlai/auth/controller/OAuthController.java @@ -61,7 +61,7 @@ public class OAuthController { * 方式一:client_id、client_secret放在请求路径中(注:当前版本已废弃) * 方式二:放在请求头(Request Headers)中的Authorization字段,且经过加密,例如 Basic Y2xpZW50OnNlY3JldA== 明文等于 client:secret */ - String clientId = JwtUtils.getAuthClientId(); + String clientId = JwtUtils.getOAuthClientId(); OAuthClientEnum client = OAuthClientEnum.getByClientId(clientId); switch (client) { case TEST: // knife4j接口测试文档使用 client_id/client_secret : client/123456 diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java b/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java index 12aa06cd8..b0d82d0b1 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/config/AuthorizationServerConfig.java @@ -124,11 +124,9 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap /** * 密码编码器 - *

+ * * 委托方式,根据密码的前缀选择对应的encoder,例如:{bcypt}前缀->标识BCYPT算法加密;{noop}->标识不使用任何加密即明文的方式 * 密码判读 DaoAuthenticationProvider#additionalAuthenticationChecks - * - * @return */ @Bean public PasswordEncoder passwordEncoder() { diff --git a/youlai-auth/src/main/java/com/youlai/auth/security/service/UserDetailsServiceImpl.java b/youlai-auth/src/main/java/com/youlai/auth/security/service/UserDetailsServiceImpl.java index 3642c1051..588dd8dcb 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/security/service/UserDetailsServiceImpl.java +++ b/youlai-auth/src/main/java/com/youlai/auth/security/service/UserDetailsServiceImpl.java @@ -34,7 +34,7 @@ public class UserDetailsServiceImpl implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - String clientId = JwtUtils.getAuthClientId(); + String clientId = JwtUtils.getOAuthClientId(); OAuthClientEnum client = OAuthClientEnum.getByClientId(clientId); Result result; diff --git a/youlai-auth/src/main/resources/bootstrap-dev.yml b/youlai-auth/src/main/resources/bootstrap-dev.yml index 78b27f212..4c0ab6f9c 100644 --- a/youlai-auth/src/main/resources/bootstrap-dev.yml +++ b/youlai-auth/src/main/resources/bootstrap-dev.yml @@ -9,38 +9,8 @@ spring: discovery: server-addr: http://localhost:8848 config: - # docker启动nacos-server需要配置 server-addr: ${spring.cloud.nacos.discovery.server-addr} file-extension: yaml group: DEFAULT_GROUP - sentinel: - enabled: true - eager: true # 取消控制台懒加载,项目启动即连接Sentinel - transport: - client-ip: localhost - dashboard: localhost:8080 - datasource: - # 降级规则 - degrade: - nacos: - server-addr: ${spring.cloud.nacos.discovery.server-addr} - dataId: ${spring.application.name}-degrade-rules - groupId: SENTINEL_GROUP - data-type: json - rule-type: degrade -# 开启feign对sentinel的支持 -feign: - sentinel: - enabled: true -# jwt 配置 -jwt: - config: - enabled: true - key-location: jwt.jks - key-alias: jwt - key-pass: 123456 - iss: youlai.tech - sub: all - access-exp-days: 30 \ No newline at end of file diff --git a/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java b/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java index a7b8fb165..22bfd21ce 100644 --- a/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java +++ b/youlai-common/common-core/src/main/java/com/youlai/common/constant/AuthConstants.java @@ -2,7 +2,6 @@ package com.youlai.common.constant; public interface AuthConstants { - /** * 认证请求头key */ diff --git a/youlai-common/common-web/src/main/java/com/youlai/common/web/util/JwtUtils.java b/youlai-common/common-web/src/main/java/com/youlai/common/web/util/JwtUtils.java index c4bba4d66..dcc31ab7c 100644 --- a/youlai-common/common-web/src/main/java/com/youlai/common/web/util/JwtUtils.java +++ b/youlai-common/common-web/src/main/java/com/youlai/common/web/util/JwtUtils.java @@ -10,26 +10,40 @@ import org.apache.logging.log4j.util.Strings; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import sun.misc.BASE64Decoder; - import javax.servlet.http.HttpServletRequest; +import java.net.URLDecoder; import java.util.List; -import java.util.stream.Collectors; +/** + * JWT工具类 + * + * @author xianrui + */ @Slf4j public class JwtUtils { + @SneakyThrows public static JSONObject getJwtPayload() { - String jwtPayload = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader(AuthConstants.JWT_PAYLOAD_KEY); - JSONObject jsonObject = JSONUtil.parseObj(jwtPayload); + String payload = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader(AuthConstants.JWT_PAYLOAD_KEY); + JSONObject jsonObject = JSONUtil.parseObj(URLDecoder.decode(payload,"UTF-8")); return jsonObject; } + /** + * 解析JWT获取用户ID + * + * @return + */ public static Long getUserId() { Long id = getJwtPayload().getLong(AuthConstants.USER_ID_KEY); return id; } - + /** + * 解析JWT获取获取用户名 + * + * @return + */ public static String getUsername() { String username = getJwtPayload().getStr(AuthConstants.USER_NAME_KEY); return username; @@ -37,7 +51,7 @@ public class JwtUtils { /** * 获取登录认证的客户端ID - *

+ * * 兼容两种方式获取Oauth2客户端信息(client_id、client_secret) * 方式一:client_id、client_secret放在请求路径中 * 方式二:放在请求头(Request Headers)中的Authorization字段,且经过加密,例如 Basic Y2xpZW50OnNlY3JldA== 明文等于 client:secret @@ -45,7 +59,7 @@ public class JwtUtils { * @return */ @SneakyThrows - public static String getAuthClientId() { + public static String getOAuthClientId() { String clientId; HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); @@ -66,15 +80,17 @@ public class JwtUtils { return clientId; } + /** + * JWT获取用户角色列表 + * + * @return 角色列表 + */ public static List getRoles() { + List roles = null; JSONObject payload = getJwtPayload(); - if (payload != null && payload.size() > 0) { - List list = payload.get(AuthConstants.JWT_AUTHORITIES_KEY, List.class); - List roles = list.stream().collect(Collectors.toList()); - return roles; + if (payload != null && payload.containsKey(AuthConstants.JWT_AUTHORITIES_KEY)) { + roles = payload.get(AuthConstants.JWT_AUTHORITIES_KEY, List.class); } - return null; + return roles; } - - } diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/component/RedisChannelListener.java b/youlai-gateway/src/main/java/com/youlai/gateway/component/RedisChannelListener.java index c9e9017bc..b21a19058 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/component/RedisChannelListener.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/component/RedisChannelListener.java @@ -1,6 +1,5 @@ package com.youlai.gateway.component; -import cn.hutool.core.util.StrUtil; import com.youlai.common.constant.GlobalConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.Message; @@ -11,13 +10,13 @@ import java.nio.charset.StandardCharsets; public class RedisChannelListener implements MessageListener { @Autowired - private AdminRoleLocalCache adminRoleLocalCache; + private UrlPermRolesLocalCache urlPermRolesLocalCache; @Override public void onMessage(Message message, byte[] bytes) { String msg = new String(message.getBody(), StandardCharsets.UTF_8); String channel = new String(message.getChannel(), StandardCharsets.UTF_8); - adminRoleLocalCache.remove(GlobalConstants.URL_PERM_ROLES_KEY); + urlPermRolesLocalCache.remove(GlobalConstants.URL_PERM_ROLES_KEY); } } diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/component/AdminRoleLocalCache.java b/youlai-gateway/src/main/java/com/youlai/gateway/component/UrlPermRolesLocalCache.java similarity index 94% rename from youlai-gateway/src/main/java/com/youlai/gateway/component/AdminRoleLocalCache.java rename to youlai-gateway/src/main/java/com/youlai/gateway/component/UrlPermRolesLocalCache.java index 3724847f2..59a4e16b8 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/component/AdminRoleLocalCache.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/component/UrlPermRolesLocalCache.java @@ -6,7 +6,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; -import java.util.Map; import java.util.concurrent.TimeUnit; /** @@ -17,7 +16,7 @@ import java.util.concurrent.TimeUnit; */ @Slf4j @Component -public class AdminRoleLocalCache { +public class UrlPermRolesLocalCache { private Cache localCache = null; @PostConstruct diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/security/ResourceServerManager.java b/youlai-gateway/src/main/java/com/youlai/gateway/security/ResourceServerManager.java index b6438ff03..166baaa12 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/security/ResourceServerManager.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/security/ResourceServerManager.java @@ -5,7 +5,7 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import com.youlai.common.constant.AuthConstants; import com.youlai.common.constant.GlobalConstants; -import com.youlai.gateway.component.AdminRoleLocalCache; +import com.youlai.gateway.component.UrlPermRolesLocalCache; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -22,15 +22,14 @@ import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; import reactor.core.publisher.Mono; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; /** * 网关自定义鉴权管理器 * - * @author haoxr - * @date 2020-05-01 + * @author xianrui */ @Component @RequiredArgsConstructor @@ -38,11 +37,13 @@ import java.util.Set; public class ResourceServerManager implements ReactiveAuthorizationManager { private final RedisTemplate redisTemplate; - private final AdminRoleLocalCache adminRoleLocalCache; - // 是否演示环境 - @Value("${demo}") - private Boolean isDemoEnv; + // 本地缓存 + private final UrlPermRolesLocalCache urlPermRolesLocalCache; + + // 是否开启本地缓存 + @Value("${local-cache.enabled}") + private Boolean localCacheEnabled; @Override public Mono check(Mono mono, AuthorizationContext authorizationContext) { @@ -51,69 +52,68 @@ public class ResourceServerManager implements ReactiveAuthorizationManager permRolesRules = (Map) adminRoleLocalCache.getCache(GlobalConstants.URL_PERM_ROLES_KEY); - if (isDemoEnv) { - // 缓存取【URL权限标识->角色集合】权限规则 - if (null == permRolesRules) { - permRolesRules = redisTemplate.opsForHash().entries(GlobalConstants.URL_PERM_ROLES_KEY); - adminRoleLocalCache.setLocalCache(GlobalConstants.URL_PERM_ROLES_KEY, permRolesRules); + // 缓存取 URL权限-角色集合 规则数据 + // urlPermRolesRules = [{'key':'GET:/api/v1/users/*','value':['ADMIN','TEST']},...] + Map urlPermRolesRules; + if (localCacheEnabled) { + urlPermRolesRules = (Map) urlPermRolesLocalCache.getCache(GlobalConstants.URL_PERM_ROLES_KEY); + if (null == urlPermRolesRules) { + urlPermRolesRules = redisTemplate.opsForHash().entries(GlobalConstants.URL_PERM_ROLES_KEY); + urlPermRolesLocalCache.setLocalCache(GlobalConstants.URL_PERM_ROLES_KEY, urlPermRolesRules); } + } else { + urlPermRolesRules = redisTemplate.opsForHash().entries(GlobalConstants.URL_PERM_ROLES_KEY); } - // 根据 “请求路径” 和 权限规则中的“URL权限标识”进行Ant匹配,得出拥有权限的角色集合 - Set hasPermissionRoles = CollectionUtil.newHashSet(); // 【声明定义】有权限的角色集合 - boolean needToCheck = false; // 【声明定义】是否需要被拦截检查的请求,如果缓存中权限规则中没有任何URL权限标识和此次请求的URL匹配,默认不需要被鉴权 - if (CollectionUtil.isNotEmpty(permRolesRules)) { - for (Map.Entry ruleEntry : permRolesRules.entrySet()) { - String perm = ruleEntry.getKey(); // 缓存权限规则的键:URL权限标识 - if (pathMatcher.match(perm, restfulPath)) { - List roles = Convert.toList(String.class, ruleEntry.getValue()); // 缓存权限规则的值:有请求路径访问权限的角色集合 - hasPermissionRoles.addAll(Convert.toList(String.class, roles)); - if (needToCheck == false) { - needToCheck = true; - } + // 根据请求路径判断有访问权限的角色列表 + List authorizedRoles = new ArrayList<>(); // 拥有访问权限的角色 + boolean requireCheck = false; // 是否需要鉴权,默认“没有设置权限规则”不用鉴权 + + for (Map.Entry permRoles : urlPermRolesRules.entrySet()) { + String perm = permRoles.getKey(); + if (pathMatcher.match(perm, restfulPath)) { + List roles = Convert.toList(String.class, permRoles.getValue()); + authorizedRoles.addAll(Convert.toList(String.class, roles)); + if (requireCheck == false) { + requireCheck = true; } } } - - log.info("拥有接口访问权限的角色:{}", hasPermissionRoles.toString()); - // 没有设置权限规则放行;注:如果默认想拦截所有的请求请移除needToCheck变量逻辑即可,根据需求定制 - if (needToCheck == false) { + if (requireCheck == false) { return Mono.just(new AuthorizationDecision(true)); } - // 判断用户JWT中携带的角色是否有能通过权限拦截的角色 + // 判断JWT中携带的用户角色是否有权限访问 Mono authorizationDecisionMono = mono .filter(Authentication::isAuthenticated) .flatMapIterable(Authentication::getAuthorities) .map(GrantedAuthority::getAuthority) .any(authority -> { - log.info("用户权限 : {}", authority); // ROLE_ROOT - String role = authority.substring(AuthConstants.AUTHORITY_PREFIX.length()); // 角色编码:ROOT - if (GlobalConstants.ROOT_ROLE_CODE.equals(role)) { // 如果是超级管理员则放行 - return true; + String roleCode = authority.substring(AuthConstants.AUTHORITY_PREFIX.length()); // 用户的角色 + if (GlobalConstants.ROOT_ROLE_CODE.equals(roleCode)) { + return true; // 如果是超级管理员则放行 } - boolean hasPermission = CollectionUtil.isNotEmpty(hasPermissionRoles) && hasPermissionRoles.contains(role); // 用户角色中只要有一个满足则通过权限校验 - return hasPermission; + boolean hasAuthorized = CollectionUtil.isNotEmpty(authorizedRoles) && authorizedRoles.contains(roleCode); + return hasAuthorized; }) .map(AuthorizationDecision::new) .defaultIfEmpty(new AuthorizationDecision(false)); diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/security/SecurityGlobalFilter.java b/youlai-gateway/src/main/java/com/youlai/gateway/security/SecurityGlobalFilter.java index e1ac9db51..357e75962 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/security/SecurityGlobalFilter.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/security/SecurityGlobalFilter.java @@ -11,7 +11,6 @@ import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.logging.log4j.util.Strings; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; @@ -24,22 +23,23 @@ import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; +import java.net.URLEncoder; + /** * 安全拦截全局过滤器 * - * @author haoxr - * @date 2020-06-12 + * @author xianrui */ @Component -@RequiredArgsConstructor @Slf4j +@RequiredArgsConstructor public class SecurityGlobalFilter implements GlobalFilter, Ordered { private final RedisTemplate redisTemplate; - // 是否演示环境 - @Value("${demo}") - private Boolean isDemoEnv; + + @Value("${spring.profiles.active}") + private String env; @SneakyThrows @Override @@ -48,8 +48,8 @@ public class SecurityGlobalFilter implements GlobalFilter, Ordered { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); - // 演示环境禁止删除和修改 - if (isDemoEnv + // 线上演示环境禁止修改和删除 + if (env.equals("prod") && (HttpMethod.DELETE.toString().equals(request.getMethodValue()) // 删除方法 || HttpMethod.PUT.toString().equals(request.getMethodValue())) // 修改方法 ) { @@ -75,7 +75,7 @@ public class SecurityGlobalFilter implements GlobalFilter, Ordered { // 存在token且不是黑名单,request写入JWT的载体信息 request = exchange.getRequest().mutate() - .header(AuthConstants.JWT_PAYLOAD_KEY, payload) + .header(AuthConstants.JWT_PAYLOAD_KEY, URLEncoder.encode(payload,"UTF-8")) .build(); exchange = exchange.mutate().request(request).build(); return chain.filter(exchange); diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHandler.java b/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHandler.java index 24099a7cd..1091eb1a4 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHandler.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHandler.java @@ -11,7 +11,7 @@ import springfox.documentation.swagger.web.*; import java.util.Optional; /** - * @Author haoxr + * @author xianrui * @Date 2021-02-25 16:34 * @Version 1.0.0 * @ https://gitee.com/xiaoym/swagger-bootstrap-ui-demo/blob/master/knife4j-spring-cloud-gateway/service-doc/src/main/java/com/xiaominfo/swagger/service/doc/handler/SwaggerHandler.java diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHeaderFilter.java b/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHeaderFilter.java index d2463cf1b..422e2509a 100644 --- a/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHeaderFilter.java +++ b/youlai-gateway/src/main/java/com/youlai/gateway/swagger/SwaggerHeaderFilter.java @@ -8,9 +8,9 @@ import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; /** - * @auth haoxr + * @link https://gitee.com/xiaoym/swagger-bootstrap-ui-demo/blob/master/knife4j-spring-cloud-gateway/service-doc/src/main/java/com/xiaominfo/swagger/service/doc/config/SwaggerHeaderFilter.java + * @auth xianrui * @date 2021-02-25 16:29 - * @link https://gitee.com/xiaoym/swagger-bootstrap-ui-demo/blob/master/knife4j-spring-cloud-gateway/service-doc/src/main/java/com/xiaominfo/swagger/service/doc/config/SwaggerHeaderFilter.java */ @Component public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory { diff --git a/youlai-gateway/src/main/resources/bootstrap-dev.yml b/youlai-gateway/src/main/resources/bootstrap-dev.yml index 74118fdbd..e9889ab1d 100644 --- a/youlai-gateway/src/main/resources/bootstrap-dev.yml +++ b/youlai-gateway/src/main/resources/bootstrap-dev.yml @@ -13,29 +13,7 @@ spring: config: server-addr: ${spring.cloud.nacos.discovery.server-addr} file-extension: yaml - sentinel: - enabled: false # 网关流控开关 - eager: true # 取消控制台懒加载,项目启动即连接Sentinel - transport: - client-ip: localhost - dashboard: localhost:8080 - datasource: - # 网关限流规则,gw-flow为key,随便定义 - gw-flow: - nacos: - server-addr: ${spring.cloud.nacos.discovery.server-addr} - dataId: ${spring.application.name}-gw-flow-rules - groupId: SENTINEL_GROUP - data-type: json - rule-type: gw-flow - # 网关API自定义分组 - gw-api-group: - nacos: - server-addr: ${spring.cloud.nacos.discovery.server-addr} - dataId: ${spring.application.name}-gw-api-group-rules - groupId: SENTINEL_GROUP - data-type: json - rule-type: gw-api-group + diff --git a/youlai-gateway/src/main/resources/bootstrap-prod.yml b/youlai-gateway/src/main/resources/bootstrap-prod.yml index d759d91c4..f25fe2241 100644 --- a/youlai-gateway/src/main/resources/bootstrap-prod.yml +++ b/youlai-gateway/src/main/resources/bootstrap-prod.yml @@ -15,24 +15,3 @@ spring: server-addr: ${spring.cloud.nacos.discovery.server-addr} file-extension: yaml namespace: prod_namespace_id - sentinel: - eager: true - transport: - dashboard: e.youlai.tech:8858 - datasource: - # 网关限流 - gw-flow: - nacos: - server-addr: ${spring.cloud.nacos.discovery.server-addr} - dataId: ${spring.application.name}-gw-flow-rules - groupId: SENTINEL_GROUP - data-type: json - rule-type: gw-flow - # 网关API自定义分组 - gw-api-group: - nacos: - server-addr: ${spring.cloud.nacos.discovery.server-addr} - dataId: ${spring.application.name}-gw-api-group-rules - groupId: SENTINEL_GROUP - data-type: json - rule-type: gw-api-group