Browse Source

越权问题处理

feature/evaluate
wangxianzhang 3 years ago
parent
commit
99f6995d00
  1. 2
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/dto/form/HasOperPermissionFormDTO.java
  2. 2
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/feign/CommonOperAccessOpenFeignClient.java
  3. 26
      epmet-gateway/src/main/java/com/epmet/GatewayApplication.java
  4. 11
      epmet-gateway/src/main/java/com/epmet/auth/InternalAuthProcessor.java
  5. 11
      epmet-gateway/src/main/java/com/epmet/filter/CpProperty.java
  6. 5
      epmet-gateway/src/main/java/com/epmet/filter/EpmetGatewayFilter.java
  7. 5
      epmet-gateway/src/main/resources/bootstrap-urls.yml
  8. 1
      epmet-gateway/src/main/resources/bootstrap.yml
  9. 2
      epmet-module/oper-access/oper-access-client/src/main/java/com/epmet/dto/form/HasOperPermissionFormDTO.java
  10. 13
      epmet-module/oper-access/oper-access-server/src/main/java/com/epmet/controller/OperMenuController.java
  11. 4
      epmet-module/oper-access/oper-access-server/src/main/java/com/epmet/redis/OperMenuRedis.java

2
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/dto/form/HasOperPermissionFormDTO.java

@ -19,4 +19,6 @@ public class HasOperPermissionFormDTO {
@NotBlank(message = "请求http方法不能为空") @NotBlank(message = "请求http方法不能为空")
private String method; private String method;
@NotBlank(message = "操作者ID不能为空")
private String operId;
} }

2
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/feign/CommonOperAccessOpenFeignClient.java

@ -14,8 +14,8 @@ import org.springframework.web.bind.annotation.RequestBody;
* @Author yinzuomei * @Author yinzuomei
* @Date 2020/5/21 15:17 本服务对外开放的API,其他服务通过引用此client调用该服务 * @Date 2020/5/21 15:17 本服务对外开放的API,其他服务通过引用此client调用该服务
*/ */
// , url = "http://localhost:8093"
@FeignClient(name = ServiceConstant.OPER_ACCESS_SERVER, fallbackFactory = CommonOperAccessOpenFeignClientFallbackFactory.class) @FeignClient(name = ServiceConstant.OPER_ACCESS_SERVER, fallbackFactory = CommonOperAccessOpenFeignClientFallbackFactory.class)
//@FeignClient(name = ServiceConstant.OPER_ACCESS_SERVER, fallbackFactory = CommonOperAccessOpenFeignClientFallbackFactory.class, url = "http://localhost:8093")
public interface CommonOperAccessOpenFeignClient { public interface CommonOperAccessOpenFeignClient {
/** /**
* @param * @param

26
epmet-gateway/src/main/java/com/epmet/GatewayApplication.java

@ -8,9 +8,15 @@
package com.epmet; package com.epmet;
import com.alibaba.fastjson.JSON;
import com.epmet.commons.tools.aspect.ServletExceptionHandler; import com.epmet.commons.tools.aspect.ServletExceptionHandler;
import com.epmet.commons.tools.config.RedissonConfig; import com.epmet.commons.tools.config.RedissonConfig;
import com.epmet.commons.tools.config.ThreadDispatcherConfig; import com.epmet.commons.tools.config.ThreadDispatcherConfig;
import com.epmet.commons.tools.redis.RedisKeys;
import com.epmet.commons.tools.redis.RedisUtils;
import com.epmet.filter.CpProperty;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@ -18,6 +24,9 @@ import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.FilterType;
import javax.annotation.PostConstruct;
import java.util.List;
/** /**
* 网关服务 * 网关服务
* *
@ -31,7 +40,24 @@ import org.springframework.context.annotation.FilterType;
@ComponentScan(basePackages = {"com.epmet.*"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {RedissonConfig.class, ThreadDispatcherConfig.class, ServletExceptionHandler.class})) @ComponentScan(basePackages = {"com.epmet.*"}, excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {RedissonConfig.class, ThreadDispatcherConfig.class, ServletExceptionHandler.class}))
public class GatewayApplication { public class GatewayApplication {
@Autowired
private CpProperty cpProperty;
@Autowired
private RedisUtils redisUtils;
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args); SpringApplication.run(GatewayApplication.class, args);
} }
/**
* 初始化运营端校验资源列表
*/
@PostConstruct
public void initOperExamineResources() {
if (!redisUtils.hasKey(RedisKeys.getOperExamineResourceUrls())) {
List<CpProperty.OperExamineResource> operExamineResourceUrls = cpProperty.getOperExamineResourceUrls();
redisUtils.setString(RedisKeys.getOperExamineResourceUrls(), JSON.toJSONString(operExamineResourceUrls));
}
}
} }

11
epmet-gateway/src/main/java/com/epmet/auth/InternalAuthProcessor.java

@ -124,7 +124,7 @@ public class InternalAuthProcessor extends AuthProcessor {
// 针对运营端的url拦截和校验 // 针对运营端的url拦截和校验
if (AppClientConstant.APP_OPER.equals(app)) { if (AppClientConstant.APP_OPER.equals(app)) {
HttpMethod method = request.getMethod(); HttpMethod method = request.getMethod();
Boolean hasAccess = checkRequestOperResource(requestUri, method.toString()); Boolean hasAccess = checkRequestOperResource(userId, requestUri, method.toString());
if (!hasAccess) { if (!hasAccess) {
throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "资源未授权", "资源未授权"); throw new EpmetException(EpmetErrorCode.EPMET_COMMON_OPERATION_FAIL.getCode(), "资源未授权", "资源未授权");
} }
@ -140,10 +140,14 @@ public class InternalAuthProcessor extends AuthProcessor {
* @param method * @param method
* @return * @return
*/ */
private Boolean checkRequestOperResource(String uri, String method) { private Boolean checkRequestOperResource(String userId, String uri, String method) {
String resourceJsonString = (String)redisUtils.get(RedisKeys.getOperExamineResourceUrls()); String resourceJsonString = redisUtils.getString(RedisKeys.getOperExamineResourceUrls());
List<OperResouce> resources = JSON.parseObject(resourceJsonString, new TypeReference<List<OperResouce>>() {}); List<OperResouce> resources = JSON.parseObject(resourceJsonString, new TypeReference<List<OperResouce>>() {});
if (resources == null) {
return true;
}
for (OperResouce resource : resources) { for (OperResouce resource : resources) {
if (antPathMatcher.match(resource.getResourceUrl(), uri) if (antPathMatcher.match(resource.getResourceUrl(), uri)
&& resource.getResourceMethod().equals(method)) { && resource.getResourceMethod().equals(method)) {
@ -152,6 +156,7 @@ public class InternalAuthProcessor extends AuthProcessor {
HasOperPermissionFormDTO form = new HasOperPermissionFormDTO(); HasOperPermissionFormDTO form = new HasOperPermissionFormDTO();
form.setUri(uri); form.setUri(uri);
form.setMethod(method); form.setMethod(method);
form.setOperId(userId);
Result result = operAccessOpenFeignClient.hasOperPermission(form); Result result = operAccessOpenFeignClient.hasOperPermission(form);
if (result == null || !result.success()) { if (result == null || !result.success()) {
return false; return false;

11
epmet-gateway/src/main/java/com/epmet/filter/CpProperty.java

@ -42,4 +42,15 @@ public class CpProperty {
*/ */
private List<String> swaggerUrls; private List<String> swaggerUrls;
/**
* 运营端需要校验的url资源列表
*/
private List<OperExamineResource> operExamineResourceUrls;
@Data
public static class OperExamineResource {
private String resourceUrl;
private String resourceMethod;
}
} }

5
epmet-gateway/src/main/java/com/epmet/filter/EpmetGatewayFilter.java

@ -5,6 +5,7 @@ import com.epmet.auth.ExternalAuthProcessor;
import com.epmet.auth.InternalAuthProcessor; import com.epmet.auth.InternalAuthProcessor;
import com.epmet.commons.tools.constant.AppClientConstant; import com.epmet.commons.tools.constant.AppClientConstant;
import com.epmet.commons.tools.exception.EpmetErrorCode; import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.EpmetException;
import com.epmet.commons.tools.exception.ExceptionUtils; import com.epmet.commons.tools.exception.ExceptionUtils;
import com.epmet.commons.tools.exception.RenException; import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.utils.IpUtils; import com.epmet.commons.tools.utils.IpUtils;
@ -64,6 +65,10 @@ public class EpmetGatewayFilter implements GatewayFilter {
} }
return doFilter(exchange, chain); return doFilter(exchange, chain);
} catch (EpmetException re) {
// 人为抛出,则携带错误码和错误信息响应给前端
log.error("EpmetGatewayFilter认证出错RenException,错误信息:{}", ExceptionUtils.getErrorStackTrace(re));
return response(exchange, new Result<>().error(re.getCode(), re.getMessage()));
} catch (RenException re) { } catch (RenException re) {
// 人为抛出,则携带错误码和错误信息响应给前端 // 人为抛出,则携带错误码和错误信息响应给前端
log.error("EpmetGatewayFilter认证出错RenException,错误信息:{}", ExceptionUtils.getErrorStackTrace(re)); log.error("EpmetGatewayFilter认证出错RenException,错误信息:{}", ExceptionUtils.getErrorStackTrace(re));

5
epmet-gateway/src/main/resources/bootstrap-urls.yml

@ -0,0 +1,5 @@
epmet:
oper-examine-resource-urls:
# 角色编辑
- resourceUrl: /oper/access/operrole
resourceMethod: PUT

1
epmet-gateway/src/main/resources/bootstrap.yml

@ -12,6 +12,7 @@ spring:
name: epmet-gateway-server name: epmet-gateway-server
#环境 dev|test|prod #环境 dev|test|prod
profiles: profiles:
include: urls
active: @spring.profiles.active@ active: @spring.profiles.active@
messages: messages:
encoding: UTF-8 encoding: UTF-8

2
epmet-module/oper-access/oper-access-client/src/main/java/com/epmet/dto/form/HasOperPermissionFormDTO.java

@ -19,4 +19,6 @@ public class HasOperPermissionFormDTO {
@NotBlank(message = "请求http方法不能为空") @NotBlank(message = "请求http方法不能为空")
private String method; private String method;
@NotBlank(message = "操作者ID不能为空")
private String operId;
} }

13
epmet-module/oper-access/oper-access-server/src/main/java/com/epmet/controller/OperMenuController.java

@ -175,15 +175,12 @@ public class OperMenuController {
String uri = form.getUri(); String uri = form.getUri();
String method = form.getMethod(); String method = form.getMethod();
String loginUserApp = EpmetRequestHolder.getLoginUserApp(); // if (!AppClientConstant.APP_OPER.equals(loginUserApp)) {
String loginUserId = EpmetRequestHolder.getLoginUserId(); //// 只校验运营端,其他都返回true
// return new Result();
// }
if (!AppClientConstant.APP_OPER.equals(loginUserApp)) { Boolean isMathe = operMenuService.hasOperPermission(uri, method, form.getOperId());
// 只校验运营端,其他都返回true
return new Result();
}
Boolean isMathe = operMenuService.hasOperPermission(uri, method, loginUserId);
if (isMathe){ if (isMathe){
return new Result(); return new Result();
} else { } else {

4
epmet-module/oper-access/oper-access-server/src/main/java/com/epmet/redis/OperMenuRedis.java

@ -76,14 +76,14 @@ public class OperMenuRedis {
public List<OperResouce> getOperResourcesByUserId(String operId) { public List<OperResouce> getOperResourcesByUserId(String operId) {
String key = RedisKeys.operResourcesByUserId(operId); String key = RedisKeys.operResourcesByUserId(operId);
String json = (String) redisUtils.get(key); String json = redisUtils.getString(key);
return JSON.parseObject(json, new TypeReference<List<OperResouce>>(){}); return JSON.parseObject(json, new TypeReference<List<OperResouce>>(){});
} }
public void setOperResourcesByUserId(String operId, List<OperResouce> resouces) { public void setOperResourcesByUserId(String operId, List<OperResouce> resouces) {
String key = RedisKeys.operResourcesByUserId(operId); String key = RedisKeys.operResourcesByUserId(operId);
String jsonString = JSON.toJSONString(resouces); String jsonString = JSON.toJSONString(resouces);
redisUtils.set(key, jsonString); redisUtils.setString(key, jsonString);
} }
/** /**

Loading…
Cancel
Save