Signed-off-by: Carpenter Lee <hooleeucas@163.com>master
@@ -15,12 +15,24 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.dashboard.config; | package com.alibaba.csp.sentinel.dashboard.config; | ||||
import java.io.IOException; | |||||
import java.io.PrintWriter; | |||||
import javax.servlet.Filter; | import javax.servlet.Filter; | ||||
import javax.servlet.FilterChain; | |||||
import javax.servlet.FilterConfig; | |||||
import javax.servlet.ServletException; | |||||
import javax.servlet.ServletRequest; | |||||
import javax.servlet.ServletResponse; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; | import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; | ||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.AuthUser; | |||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.boot.web.servlet.FilterRegistrationBean; | import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||||
import org.springframework.context.annotation.Bean; | import org.springframework.context.annotation.Bean; | ||||
import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||
@@ -35,6 +47,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | |||||
public class WebConfig implements WebMvcConfigurer { | public class WebConfig implements WebMvcConfigurer { | ||||
private final Logger logger = LoggerFactory.getLogger(WebConfig.class); | private final Logger logger = LoggerFactory.getLogger(WebConfig.class); | ||||
@Autowired | |||||
private AuthService<HttpServletRequest> authService; | |||||
@Override | @Override | ||||
public void addResourceHandlers(ResourceHandlerRegistry registry) { | public void addResourceHandlers(ResourceHandlerRegistry registry) { | ||||
@@ -62,4 +76,36 @@ public class WebConfig implements WebMvcConfigurer { | |||||
return registration; | return registration; | ||||
} | } | ||||
@Bean | |||||
public FilterRegistrationBean authenticationFilterRegistration() { | |||||
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(); | |||||
registration.setFilter(new Filter() { | |||||
@Override | |||||
public void init(FilterConfig filterConfig) throws ServletException { } | |||||
@Override | |||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, | |||||
FilterChain filterChain) throws IOException, ServletException { | |||||
HttpServletRequest request = (HttpServletRequest)servletRequest; | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
// authentication fail | |||||
if (authUser == null) { | |||||
PrintWriter writer = servletResponse.getWriter(); | |||||
writer.append("login needed"); | |||||
writer.flush(); | |||||
} else { | |||||
filterChain.doFilter(servletRequest, servletResponse); | |||||
} | |||||
} | |||||
@Override | |||||
public void destroy() { } | |||||
}); | |||||
registration.addUrlPatterns("/*"); | |||||
registration.setName("authenticationFilter"); | |||||
registration.setOrder(0); | |||||
return registration; | |||||
} | |||||
} | } |
@@ -18,14 +18,20 @@ package com.alibaba.csp.sentinel.dashboard.controller; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | ||||
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | ||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.AuthUser; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.PrivilegeType; | |||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | import com.alibaba.csp.sentinel.slots.block.RuleConstant; | ||||
import com.alibaba.csp.sentinel.util.StringUtil; | import com.alibaba.csp.sentinel.util.StringUtil; | ||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; | import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.AuthorityRuleEntity; | ||||
import com.alibaba.csp.sentinel.dashboard.domain.Result; | import com.alibaba.csp.sentinel.dashboard.domain.Result; | ||||
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -54,10 +60,16 @@ public class AuthorityRuleController { | |||||
@Autowired | @Autowired | ||||
private RuleRepository<AuthorityRuleEntity, Long> repository; | private RuleRepository<AuthorityRuleEntity, Long> repository; | ||||
@Autowired | |||||
private AuthService<HttpServletRequest> authService; | |||||
@GetMapping("/rules") | @GetMapping("/rules") | ||||
public Result<List<AuthorityRuleEntity>> apiQueryAllRulesForMachine(@RequestParam String app, | |||||
public Result<List<AuthorityRuleEntity>> apiQueryAllRulesForMachine(HttpServletRequest request, | |||||
@RequestParam String app, | |||||
@RequestParam String ip, | @RequestParam String ip, | ||||
@RequestParam Integer port) { | @RequestParam Integer port) { | ||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.READ_RULE); | |||||
if (StringUtil.isEmpty(app)) { | if (StringUtil.isEmpty(app)) { | ||||
return Result.ofFail(-1, "app cannot be null or empty"); | return Result.ofFail(-1, "app cannot be null or empty"); | ||||
} | } | ||||
@@ -107,7 +119,10 @@ public class AuthorityRuleController { | |||||
} | } | ||||
@PostMapping("/rule") | @PostMapping("/rule") | ||||
public Result<AuthorityRuleEntity> apiAddAuthorityRule(@RequestBody AuthorityRuleEntity entity) { | |||||
public Result<AuthorityRuleEntity> apiAddAuthorityRule(HttpServletRequest request, | |||||
@RequestBody AuthorityRuleEntity entity) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE); | |||||
Result<AuthorityRuleEntity> checkResult = checkEntityInternal(entity); | Result<AuthorityRuleEntity> checkResult = checkEntityInternal(entity); | ||||
if (checkResult != null) { | if (checkResult != null) { | ||||
return checkResult; | return checkResult; | ||||
@@ -129,8 +144,11 @@ public class AuthorityRuleController { | |||||
} | } | ||||
@PutMapping("/rule/{id}") | @PutMapping("/rule/{id}") | ||||
public Result<AuthorityRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Long id, | |||||
public Result<AuthorityRuleEntity> apiUpdateParamFlowRule(HttpServletRequest request, | |||||
@PathVariable("id") Long id, | |||||
@RequestBody AuthorityRuleEntity entity) { | @RequestBody AuthorityRuleEntity entity) { | ||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE); | |||||
if (id == null || id <= 0) { | if (id == null || id <= 0) { | ||||
return Result.ofFail(-1, "Invalid id"); | return Result.ofFail(-1, "Invalid id"); | ||||
} | } | ||||
@@ -158,7 +176,8 @@ public class AuthorityRuleController { | |||||
} | } | ||||
@DeleteMapping("/rule/{id}") | @DeleteMapping("/rule/{id}") | ||||
public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { | |||||
public Result<Long> apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id cannot be null"); | return Result.ofFail(-1, "id cannot be null"); | ||||
} | } | ||||
@@ -166,6 +185,7 @@ public class AuthorityRuleController { | |||||
if (oldEntity == null) { | if (oldEntity == null) { | ||||
return Result.ofSuccess(null); | return Result.ofSuccess(null); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE); | |||||
try { | try { | ||||
repository.delete(id); | repository.delete(id); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
@@ -18,14 +18,20 @@ package com.alibaba.csp.sentinel.dashboard.controller; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | ||||
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | ||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.AuthUser; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.PrivilegeType; | |||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | import com.alibaba.csp.sentinel.slots.block.RuleConstant; | ||||
import com.alibaba.csp.sentinel.util.StringUtil; | import com.alibaba.csp.sentinel.util.StringUtil; | ||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; | import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; | ||||
import com.alibaba.csp.sentinel.dashboard.domain.Result; | import com.alibaba.csp.sentinel.dashboard.domain.Result; | ||||
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemDegradeRuleStore; | import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemDegradeRuleStore; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -48,9 +54,15 @@ public class DegradeController { | |||||
@Autowired | @Autowired | ||||
private SentinelApiClient sentinelApiClient; | private SentinelApiClient sentinelApiClient; | ||||
@Autowired | |||||
private AuthService<HttpServletRequest> authService; | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/rules.json") | @RequestMapping("/rules.json") | ||||
public Result<List<DegradeRuleEntity>> queryMachineRules(String app, String ip, Integer port) { | |||||
public Result<List<DegradeRuleEntity>> queryMachineRules(HttpServletRequest request, String app, String ip, Integer port) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.READ_RULE); | |||||
if (StringUtil.isEmpty(app)) { | if (StringUtil.isEmpty(app)) { | ||||
return Result.ofFail(-1, "app can't be null or empty"); | return Result.ofFail(-1, "app can't be null or empty"); | ||||
} | } | ||||
@@ -72,8 +84,12 @@ public class DegradeController { | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/new.json") | @RequestMapping("/new.json") | ||||
public Result<DegradeRuleEntity> add(String app, String ip, Integer port, String limitApp, String resource, | |||||
Double count, Integer timeWindow, Integer grade) { | |||||
public Result<DegradeRuleEntity> add(HttpServletRequest request, | |||||
String app, String ip, Integer port, String limitApp, String resource, | |||||
Double count, Integer timeWindow, Integer grade) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.WRITE_RULE); | |||||
if (StringUtil.isBlank(app)) { | if (StringUtil.isBlank(app)) { | ||||
return Result.ofFail(-1, "app can't be null or empty"); | return Result.ofFail(-1, "app can't be null or empty"); | ||||
} | } | ||||
@@ -127,8 +143,10 @@ public class DegradeController { | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/save.json") | @RequestMapping("/save.json") | ||||
public Result<DegradeRuleEntity> updateIfNotNull(Long id, String app, String limitApp, String resource, | |||||
Double count, Integer timeWindow, Integer grade) { | |||||
public Result<DegradeRuleEntity> updateIfNotNull(HttpServletRequest request, | |||||
Long id, String app, String limitApp, String resource, | |||||
Double count, Integer timeWindow, Integer grade) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id can't be null"); | return Result.ofFail(-1, "id can't be null"); | ||||
} | } | ||||
@@ -141,6 +159,7 @@ public class DegradeController { | |||||
if (entity == null) { | if (entity == null) { | ||||
return Result.ofFail(-1, "id " + id + " dose not exist"); | return Result.ofFail(-1, "id " + id + " dose not exist"); | ||||
} | } | ||||
authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE); | |||||
if (StringUtil.isNotBlank(app)) { | if (StringUtil.isNotBlank(app)) { | ||||
entity.setApp(app.trim()); | entity.setApp(app.trim()); | ||||
} | } | ||||
@@ -176,7 +195,8 @@ public class DegradeController { | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/delete.json") | @RequestMapping("/delete.json") | ||||
public Result<Long> delete(Long id) { | |||||
public Result<Long> delete(HttpServletRequest request, Long id) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id can't be null"); | return Result.ofFail(-1, "id can't be null"); | ||||
} | } | ||||
@@ -185,6 +205,7 @@ public class DegradeController { | |||||
if (oldEntity == null) { | if (oldEntity == null) { | ||||
return Result.ofSuccess(null); | return Result.ofSuccess(null); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE); | |||||
try { | try { | ||||
repository.delete(id); | repository.delete(id); | ||||
} catch (Throwable throwable) { | } catch (Throwable throwable) { | ||||
@@ -18,6 +18,11 @@ package com.alibaba.csp.sentinel.dashboard.controller; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.AuthUser; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.PrivilegeType; | |||||
import com.alibaba.csp.sentinel.util.StringUtil; | import com.alibaba.csp.sentinel.util.StringUtil; | ||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | ||||
@@ -25,6 +30,7 @@ import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; | |||||
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | ||||
import com.alibaba.csp.sentinel.dashboard.domain.Result; | import com.alibaba.csp.sentinel.dashboard.domain.Result; | ||||
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter; | import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -51,14 +57,20 @@ public class FlowControllerV1 { | |||||
@Autowired | @Autowired | ||||
private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository; | private InMemoryRuleRepositoryAdapter<FlowRuleEntity> repository; | ||||
@Autowired | |||||
private AuthService<HttpServletRequest> authService; | |||||
@Autowired | @Autowired | ||||
private SentinelApiClient sentinelApiClient; | private SentinelApiClient sentinelApiClient; | ||||
@GetMapping("/rules") | @GetMapping("/rules") | ||||
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app, | |||||
public Result<List<FlowRuleEntity>> apiQueryMachineRules(HttpServletRequest request, | |||||
@RequestParam String app, | |||||
@RequestParam String ip, | @RequestParam String ip, | ||||
@RequestParam Integer port) { | @RequestParam Integer port) { | ||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.READ_RULE); | |||||
if (StringUtil.isEmpty(app)) { | if (StringUtil.isEmpty(app)) { | ||||
return Result.ofFail(-1, "app can't be null or empty"); | return Result.ofFail(-1, "app can't be null or empty"); | ||||
} | } | ||||
@@ -126,7 +138,10 @@ public class FlowControllerV1 { | |||||
} | } | ||||
@PostMapping("/rule") | @PostMapping("/rule") | ||||
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) { | |||||
public Result<FlowRuleEntity> apiAddFlowRule(HttpServletRequest request, @RequestBody FlowRuleEntity entity) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE); | |||||
Result<FlowRuleEntity> checkResult = checkEntityInternal(entity); | Result<FlowRuleEntity> checkResult = checkEntityInternal(entity); | ||||
if (checkResult != null) { | if (checkResult != null) { | ||||
return checkResult; | return checkResult; | ||||
@@ -150,10 +165,14 @@ public class FlowControllerV1 { | |||||
} | } | ||||
@PutMapping("/save.json") | @PutMapping("/save.json") | ||||
public Result<FlowRuleEntity> updateIfNotNull(Long id, String app, | |||||
String limitApp, String resource, Integer grade, | |||||
Double count, Integer strategy, String refResource, | |||||
Integer controlBehavior, Integer warmUpPeriodSec, Integer maxQueueingTimeMs) { | |||||
public Result<FlowRuleEntity> updateIfNotNull(HttpServletRequest request, Long id, String app, | |||||
String limitApp, String resource, Integer grade, | |||||
Double count, Integer strategy, String refResource, | |||||
Integer controlBehavior, Integer warmUpPeriodSec, | |||||
Integer maxQueueingTimeMs) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.WRITE_RULE); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id can't be null"); | return Result.ofFail(-1, "id can't be null"); | ||||
} | } | ||||
@@ -227,7 +246,8 @@ public class FlowControllerV1 { | |||||
} | } | ||||
@DeleteMapping("/delete.json") | @DeleteMapping("/delete.json") | ||||
public Result<Long> delete(Long id) { | |||||
public Result<Long> delete(HttpServletRequest request, Long id) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id can't be null"); | return Result.ofFail(-1, "id can't be null"); | ||||
} | } | ||||
@@ -235,6 +255,7 @@ public class FlowControllerV1 { | |||||
if (oldEntity == null) { | if (oldEntity == null) { | ||||
return Result.ofSuccess(null); | return Result.ofSuccess(null); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE); | |||||
try { | try { | ||||
repository.delete(id); | repository.delete(id); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
@@ -21,10 +21,15 @@ import java.util.Optional; | |||||
import java.util.concurrent.CompletableFuture; | import java.util.concurrent.CompletableFuture; | ||||
import java.util.concurrent.ExecutionException; | import java.util.concurrent.ExecutionException; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException; | import com.alibaba.csp.sentinel.dashboard.client.CommandNotFoundException; | ||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | ||||
import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement; | import com.alibaba.csp.sentinel.dashboard.discovery.AppManagement; | ||||
import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | ||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.AuthUser; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.PrivilegeType; | |||||
import com.alibaba.csp.sentinel.slots.block.RuleConstant; | import com.alibaba.csp.sentinel.slots.block.RuleConstant; | ||||
import com.alibaba.csp.sentinel.util.StringUtil; | import com.alibaba.csp.sentinel.util.StringUtil; | ||||
@@ -33,6 +38,7 @@ import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.ParamFlowRuleEn | |||||
import com.alibaba.csp.sentinel.dashboard.domain.Result; | import com.alibaba.csp.sentinel.dashboard.domain.Result; | ||||
import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | import com.alibaba.csp.sentinel.dashboard.repository.rule.RuleRepository; | ||||
import com.alibaba.csp.sentinel.dashboard.util.VersionUtils; | import com.alibaba.csp.sentinel.dashboard.util.VersionUtils; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -63,6 +69,9 @@ public class ParamFlowRuleController { | |||||
@Autowired | @Autowired | ||||
private RuleRepository<ParamFlowRuleEntity, Long> repository; | private RuleRepository<ParamFlowRuleEntity, Long> repository; | ||||
@Autowired | |||||
private AuthService<HttpServletRequest> authService; | |||||
private boolean checkIfSupported(String app, String ip, int port) { | private boolean checkIfSupported(String app, String ip, int port) { | ||||
try { | try { | ||||
return Optional.ofNullable(appManagement.getDetailApp(app)) | return Optional.ofNullable(appManagement.getDetailApp(app)) | ||||
@@ -77,9 +86,12 @@ public class ParamFlowRuleController { | |||||
} | } | ||||
@GetMapping("/rules") | @GetMapping("/rules") | ||||
public Result<List<ParamFlowRuleEntity>> apiQueryAllRulesForMachine(@RequestParam String app, | |||||
public Result<List<ParamFlowRuleEntity>> apiQueryAllRulesForMachine(HttpServletRequest request, | |||||
@RequestParam String app, | |||||
@RequestParam String ip, | @RequestParam String ip, | ||||
@RequestParam Integer port) { | @RequestParam Integer port) { | ||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.READ_RULE); | |||||
if (StringUtil.isEmpty(app)) { | if (StringUtil.isEmpty(app)) { | ||||
return Result.ofFail(-1, "app cannot be null or empty"); | return Result.ofFail(-1, "app cannot be null or empty"); | ||||
} | } | ||||
@@ -115,7 +127,10 @@ public class ParamFlowRuleController { | |||||
} | } | ||||
@PostMapping("/rule") | @PostMapping("/rule") | ||||
public Result<ParamFlowRuleEntity> apiAddParamFlowRule(@RequestBody ParamFlowRuleEntity entity) { | |||||
public Result<ParamFlowRuleEntity> apiAddParamFlowRule(HttpServletRequest request, | |||||
@RequestBody ParamFlowRuleEntity entity) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE); | |||||
Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); | Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); | ||||
if (checkResult != null) { | if (checkResult != null) { | ||||
return checkResult; | return checkResult; | ||||
@@ -177,7 +192,10 @@ public class ParamFlowRuleController { | |||||
} | } | ||||
@PutMapping("/rule/{id}") | @PutMapping("/rule/{id}") | ||||
public Result<ParamFlowRuleEntity> apiUpdateParamFlowRule(@PathVariable("id") Long id, @RequestBody ParamFlowRuleEntity entity) { | |||||
public Result<ParamFlowRuleEntity> apiUpdateParamFlowRule(HttpServletRequest request, | |||||
@PathVariable("id") Long id, | |||||
@RequestBody ParamFlowRuleEntity entity) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null || id <= 0) { | if (id == null || id <= 0) { | ||||
return Result.ofFail(-1, "Invalid id"); | return Result.ofFail(-1, "Invalid id"); | ||||
} | } | ||||
@@ -185,6 +203,7 @@ public class ParamFlowRuleController { | |||||
if (oldEntity == null) { | if (oldEntity == null) { | ||||
return Result.ofFail(-1, "id " + id + " does not exist"); | return Result.ofFail(-1, "id " + id + " does not exist"); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.WRITE_RULE); | |||||
Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); | Result<ParamFlowRuleEntity> checkResult = checkEntityInternal(entity); | ||||
if (checkResult != null) { | if (checkResult != null) { | ||||
return checkResult; | return checkResult; | ||||
@@ -214,7 +233,8 @@ public class ParamFlowRuleController { | |||||
} | } | ||||
@DeleteMapping("/rule/{id}") | @DeleteMapping("/rule/{id}") | ||||
public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { | |||||
public Result<Long> apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id cannot be null"); | return Result.ofFail(-1, "id cannot be null"); | ||||
} | } | ||||
@@ -222,6 +242,7 @@ public class ParamFlowRuleController { | |||||
if (oldEntity == null) { | if (oldEntity == null) { | ||||
return Result.ofSuccess(null); | return Result.ofSuccess(null); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE); | |||||
try { | try { | ||||
repository.delete(id); | repository.delete(id); | ||||
publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(); | publishRules(oldEntity.getApp(), oldEntity.getIp(), oldEntity.getPort()).get(); | ||||
@@ -245,7 +266,8 @@ public class ParamFlowRuleController { | |||||
} | } | ||||
private <R> Result<R> unsupportedVersion() { | private <R> Result<R> unsupportedVersion() { | ||||
return Result.ofFail(4041, "Sentinel client not supported for parameter flow control (unsupported version or dependency absent)"); | |||||
return Result.ofFail(4041, | |||||
"Sentinel client not supported for parameter flow control (unsupported version or dependency absent)"); | |||||
} | } | ||||
private final SentinelVersion version020 = new SentinelVersion().setMinorVersion(2); | private final SentinelVersion version020 = new SentinelVersion().setMinorVersion(2); | ||||
@@ -18,6 +18,11 @@ package com.alibaba.csp.sentinel.dashboard.controller; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.AuthUser; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.PrivilegeType; | |||||
import com.alibaba.csp.sentinel.util.StringUtil; | import com.alibaba.csp.sentinel.util.StringUtil; | ||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; | import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.SystemRuleEntity; | ||||
@@ -25,6 +30,7 @@ import com.alibaba.csp.sentinel.dashboard.discovery.MachineInfo; | |||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | ||||
import com.alibaba.csp.sentinel.dashboard.domain.Result; | import com.alibaba.csp.sentinel.dashboard.domain.Result; | ||||
import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemSystemRuleStore; | import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemSystemRuleStore; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -45,10 +51,14 @@ public class SystemController { | |||||
private InMemSystemRuleStore repository; | private InMemSystemRuleStore repository; | ||||
@Autowired | @Autowired | ||||
private SentinelApiClient sentinelApiClient; | private SentinelApiClient sentinelApiClient; | ||||
@Autowired | |||||
private AuthService<HttpServletRequest> authService; | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/rules.json") | @RequestMapping("/rules.json") | ||||
Result<List<SystemRuleEntity>> queryMachineRules(String app, String ip, Integer port) { | |||||
Result<List<SystemRuleEntity>> queryMachineRules(HttpServletRequest request, String app, String ip, Integer port) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.READ_RULE); | |||||
if (StringUtil.isEmpty(app)) { | if (StringUtil.isEmpty(app)) { | ||||
return Result.ofFail(-1, "app can't be null or empty"); | return Result.ofFail(-1, "app can't be null or empty"); | ||||
} | } | ||||
@@ -80,7 +90,10 @@ public class SystemController { | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/new.json") | @RequestMapping("/new.json") | ||||
Result<?> add(String app, String ip, Integer port, Double avgLoad, Long avgRt, Long maxThread, Double qps) { | |||||
Result<?> add(HttpServletRequest request, | |||||
String app, String ip, Integer port, Double avgLoad, Long avgRt, Long maxThread, Double qps) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.WRITE_RULE); | |||||
if (StringUtil.isBlank(app)) { | if (StringUtil.isBlank(app)) { | ||||
return Result.ofFail(-1, "app can't be null or empty"); | return Result.ofFail(-1, "app can't be null or empty"); | ||||
} | } | ||||
@@ -137,7 +150,9 @@ public class SystemController { | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/save.json") | @RequestMapping("/save.json") | ||||
Result<?> updateIfNotNull(Long id, String app, Double avgLoad, Long avgRt, Long maxThread, Double qps) { | |||||
Result<?> updateIfNotNull(HttpServletRequest request, | |||||
Long id, String app, Double avgLoad, Long avgRt, Long maxThread, Double qps) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id can't be null"); | return Result.ofFail(-1, "id can't be null"); | ||||
} | } | ||||
@@ -145,6 +160,7 @@ public class SystemController { | |||||
if (entity == null) { | if (entity == null) { | ||||
return Result.ofFail(-1, "id " + id + " dose not exist"); | return Result.ofFail(-1, "id " + id + " dose not exist"); | ||||
} | } | ||||
authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE); | |||||
if (StringUtil.isNotBlank(app)) { | if (StringUtil.isNotBlank(app)) { | ||||
entity.setApp(app.trim()); | entity.setApp(app.trim()); | ||||
} | } | ||||
@@ -188,7 +204,8 @@ public class SystemController { | |||||
@ResponseBody | @ResponseBody | ||||
@RequestMapping("/delete.json") | @RequestMapping("/delete.json") | ||||
Result<?> delete(Long id) { | |||||
Result<?> delete(HttpServletRequest request, Long id) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null) { | if (id == null) { | ||||
return Result.ofFail(-1, "id can't be null"); | return Result.ofFail(-1, "id can't be null"); | ||||
} | } | ||||
@@ -196,6 +213,7 @@ public class SystemController { | |||||
if (oldEntity == null) { | if (oldEntity == null) { | ||||
return Result.ofSuccess(null); | return Result.ofSuccess(null); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE); | |||||
try { | try { | ||||
repository.delete(id); | repository.delete(id); | ||||
} catch (Throwable throwable) { | } catch (Throwable throwable) { | ||||
@@ -18,6 +18,11 @@ package com.alibaba.csp.sentinel.dashboard.controller.v2; | |||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import javax.servlet.http.HttpServletRequest; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.AuthUser; | |||||
import com.alibaba.csp.sentinel.dashboard.service.AuthService.PrivilegeType; | |||||
import com.alibaba.csp.sentinel.util.StringUtil; | import com.alibaba.csp.sentinel.util.StringUtil; | ||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; | import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; | ||||
@@ -25,6 +30,7 @@ import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepository | |||||
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; | ||||
import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; | ||||
import com.alibaba.csp.sentinel.dashboard.domain.Result; | import com.alibaba.csp.sentinel.dashboard.domain.Result; | ||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -61,8 +67,14 @@ public class FlowControllerV2 { | |||||
@Qualifier("flowRuleDefaultPublisher") | @Qualifier("flowRuleDefaultPublisher") | ||||
private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher; | private DynamicRulePublisher<List<FlowRuleEntity>> rulePublisher; | ||||
@Autowired | |||||
private AuthService<HttpServletRequest> authService; | |||||
@GetMapping("/rules") | @GetMapping("/rules") | ||||
public Result<List<FlowRuleEntity>> apiQueryMachineRules(@RequestParam String app) { | |||||
public Result<List<FlowRuleEntity>> apiQueryMachineRules(HttpServletRequest request, @RequestParam String app) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(app, PrivilegeType.READ_RULE); | |||||
if (StringUtil.isEmpty(app)) { | if (StringUtil.isEmpty(app)) { | ||||
return Result.ofFail(-1, "app can't be null or empty"); | return Result.ofFail(-1, "app can't be null or empty"); | ||||
} | } | ||||
@@ -129,7 +141,10 @@ public class FlowControllerV2 { | |||||
} | } | ||||
@PostMapping("/rule") | @PostMapping("/rule") | ||||
public Result<FlowRuleEntity> apiAddFlowRule(@RequestBody FlowRuleEntity entity) { | |||||
public Result<FlowRuleEntity> apiAddFlowRule(HttpServletRequest request, @RequestBody FlowRuleEntity entity) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
authUser.authTarget(entity.getApp(), PrivilegeType.WRITE_RULE); | |||||
Result<FlowRuleEntity> checkResult = checkEntityInternal(entity); | Result<FlowRuleEntity> checkResult = checkEntityInternal(entity); | ||||
if (checkResult != null) { | if (checkResult != null) { | ||||
return checkResult; | return checkResult; | ||||
@@ -151,7 +166,10 @@ public class FlowControllerV2 { | |||||
} | } | ||||
@PutMapping("/rule/{id}") | @PutMapping("/rule/{id}") | ||||
public Result<FlowRuleEntity> apiUpdateFlowRule(@PathVariable("id") Long id, @RequestBody FlowRuleEntity entity) { | |||||
public Result<FlowRuleEntity> apiUpdateFlowRule(HttpServletRequest request, | |||||
@PathVariable("id") Long id, | |||||
@RequestBody FlowRuleEntity entity) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null || id <= 0) { | if (id == null || id <= 0) { | ||||
return Result.ofFail(-1, "Invalid id"); | return Result.ofFail(-1, "Invalid id"); | ||||
} | } | ||||
@@ -162,6 +180,8 @@ public class FlowControllerV2 { | |||||
if (entity == null) { | if (entity == null) { | ||||
return Result.ofFail(-1, "invalid body"); | return Result.ofFail(-1, "invalid body"); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.WRITE_RULE); | |||||
entity.setApp(oldEntity.getApp()); | entity.setApp(oldEntity.getApp()); | ||||
entity.setIp(oldEntity.getIp()); | entity.setIp(oldEntity.getIp()); | ||||
entity.setPort(oldEntity.getPort()); | entity.setPort(oldEntity.getPort()); | ||||
@@ -188,7 +208,8 @@ public class FlowControllerV2 { | |||||
} | } | ||||
@DeleteMapping("/rule/{id}") | @DeleteMapping("/rule/{id}") | ||||
public Result<Long> apiDeleteRule(@PathVariable("id") Long id) { | |||||
public Result<Long> apiDeleteRule(HttpServletRequest request, @PathVariable("id") Long id) { | |||||
AuthUser authUser = authService.getAuthUser(request); | |||||
if (id == null || id <= 0) { | if (id == null || id <= 0) { | ||||
return Result.ofFail(-1, "Invalid id"); | return Result.ofFail(-1, "Invalid id"); | ||||
} | } | ||||
@@ -196,6 +217,7 @@ public class FlowControllerV2 { | |||||
if (oldEntity == null) { | if (oldEntity == null) { | ||||
return Result.ofSuccess(null); | return Result.ofSuccess(null); | ||||
} | } | ||||
authUser.authTarget(oldEntity.getApp(), PrivilegeType.DELETE_RULE); | |||||
try { | try { | ||||
repository.delete(id); | repository.delete(id); | ||||
publishRules(oldEntity.getApp()); | publishRules(oldEntity.getApp()); | ||||
@@ -0,0 +1,111 @@ | |||||
/* | |||||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.dashboard.service; | |||||
/** | |||||
* Interface about authentication and authorization | |||||
* | |||||
* @author Carpenter Lee | |||||
*/ | |||||
public interface AuthService<R> { | |||||
/** | |||||
* Get the authentication user. | |||||
* | |||||
* @param request the request contains the user information | |||||
* @return the auth user represent the current user, when the user is illegal, a null value will return. | |||||
*/ | |||||
AuthUser getAuthUser(R request); | |||||
/** | |||||
* privilege type. | |||||
*/ | |||||
enum PrivilegeType { | |||||
/** | |||||
* read rule | |||||
*/ | |||||
READ_RULE, | |||||
/** | |||||
* create or modify rule | |||||
*/ | |||||
WRITE_RULE, | |||||
/** | |||||
* delete rule | |||||
*/ | |||||
DELETE_RULE, | |||||
/** | |||||
* read metrics | |||||
*/ | |||||
READ_METRIC, | |||||
/** | |||||
* add machine | |||||
*/ | |||||
ADD_MACHINE, | |||||
/** | |||||
* equals all privileges above | |||||
*/ | |||||
ALL | |||||
} | |||||
/** | |||||
* entity represents the current user | |||||
*/ | |||||
interface AuthUser { | |||||
/** | |||||
* query whether current user has the specific privilege to the target, the target | |||||
* may be an app name or an ip address, or other destination. | |||||
* <p> | |||||
* This method will use return value to represent whether user has the specific | |||||
* privileges to the target, but to throw a RuntimeException to represent no auth | |||||
* is also a good way. | |||||
* </p> | |||||
* | |||||
* @param target the target to check | |||||
* @param privilegeType the privilege type to check | |||||
* @return if current user has the specific privileges to the target, return true, | |||||
* otherwise return false. | |||||
*/ | |||||
boolean authTarget(String target, PrivilegeType privilegeType); | |||||
/** | |||||
* check whether current user is super user | |||||
* | |||||
* @return if current user is super user return true, else return false. | |||||
*/ | |||||
boolean isSuperUser(); | |||||
/** | |||||
* get current user's nick name. | |||||
* | |||||
* @return current user's nick name. | |||||
*/ | |||||
String getNickName(); | |||||
/** | |||||
* get current user's login name. | |||||
* | |||||
* @return current user's login name. | |||||
*/ | |||||
String getLoginName(); | |||||
/** | |||||
* get current user's employ id. | |||||
* | |||||
* @return current user's employ id. | |||||
*/ | |||||
String getEmpId(); | |||||
} | |||||
} |
@@ -0,0 +1,64 @@ | |||||
/* | |||||
* Copyright 1999-2018 Alibaba Group Holding Ltd. | |||||
* | |||||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||||
* you may not use this file except in compliance with the License. | |||||
* You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
*/ | |||||
package com.alibaba.csp.sentinel.dashboard.service; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* A fake AuthService implementation, which will pass all user auth checking. | |||||
* | |||||
* @author Carpenter Lee | |||||
*/ | |||||
@Component | |||||
public class FakeAuthServiceImpl implements AuthService<HttpServletRequest> { | |||||
@Override | |||||
public AuthUser getAuthUser(HttpServletRequest request) { | |||||
return new AuthUserImpl(); | |||||
} | |||||
static final class AuthUserImpl implements AuthUser { | |||||
@Override | |||||
public boolean authTarget(String target, PrivilegeType privilegeType) { | |||||
// fake implementation, always return true | |||||
return true; | |||||
} | |||||
@Override | |||||
public boolean isSuperUser() { | |||||
// fake implementation, always return true | |||||
return true; | |||||
} | |||||
@Override | |||||
public String getNickName() { | |||||
return "FAKE_NICK_NAME"; | |||||
} | |||||
@Override | |||||
public String getLoginName() { | |||||
return "FAKE_LOGIN_NAME"; | |||||
} | |||||
@Override | |||||
public String getEmpId() { | |||||
return "FAKE_EMP_ID"; | |||||
} | |||||
} | |||||
} |