官网:https://sentinelguard.io/zh-cn/docs/origin-authority-control.html
来源访问控制:黑白名单,根据调用方限制资源是否通过
白名单:位于白名单内的资源可通过,不在白名单范围内的不可通过
黑名单:位于黑名单内的资源不可通过,不在黑名单范围内的资源可通过
AuthorityRule
public class AuthorityRule extends AbstractRule {
private int strategy = 0; //黑白名单:白名单(AUTHORITY_WHITE,默认)、黑名单(AUTHORITY_BLACK)
public AuthorityRule() {
}
AbstractRule
public abstract class AbstractRule implements Rule {
private String resource; //资源名称
private String limitApp; //限制的来源,多个来源用逗号间隔
public AbstractRule() {
}
配置示例
private static void initWhiteRules() {
AuthorityRule rule = new AuthorityRule();
rule.setResource(RESOURCE_NAME);
rule.setStrategy(RuleConstant.AUTHORITY_WHITE); //白名单
rule.setLimitApp("appA,appE");
AuthorityRuleManager.loadRules(Collections.singletonList(rule));
}
private static void initBlackRules() {
AuthorityRule rule = new AuthorityRule();
rule.setResource(RESOURCE_NAME);
rule.setStrategy(RuleConstant.AUTHORITY_BLACK); //黑名单
rule.setLimitApp("appA,appB");
AuthorityRuleManager.loadRules(Collections.singletonList(rule));
}
AuthoritySlot:过滤黑白名单规则
@SpiOrder(-6000)
public class AuthoritySlot extends AbstractLinkedProcessorSlot {
public AuthoritySlot() {
}
public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args) throws Throwable {
this.checkBlackWhiteAuthority(resourceWrapper, context);
this.fireEntry(context, resourceWrapper, node, count, prioritized, args);
}
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
this.fireExit(context, resourceWrapper, count, args);
}
void checkBlackWhiteAuthority(ResourceWrapper resource, Context context) throws AuthorityException {
Map> authorityRules = AuthorityRuleManager.getAuthorityRules();
//加载所有黑白名单规则
if (authorityRules != null) {
Set rules = (Set)authorityRules.get(resource.getName());
//获取资源对应的黑白名单规则
if (rules != null) {
Iterator var5 = rules.iterator();
AuthorityRule rule;
do {
if (!var5.hasNext()) {
return;
}
rule = (AuthorityRule)var5.next();
} while(AuthorityRuleChecker.passCheck(rule, context));
//黑白名单规则检验
throw new AuthorityException(context.getOrigin(), rule);
//无法规则检验则抛出异常
}
}
}
}
AuthorityRuleChecker:检验黑白名单规则
final class AuthorityRuleChecker {
static boolean passCheck(AuthorityRule rule, Context context) {
String requester = context.getOrigin(); //获取请求来源
if (!StringUtil.isEmpty(requester) && !StringUtil.isEmpty(rule.getLimitApp())) { //规则检验
int pos = rule.getLimitApp().indexOf(requester);
boolean contain = pos > -1;
if (contain) {
boolean exactlyMatch = false;
String[] appArray = rule.getLimitApp().split(",");
String[] var7 = appArray;
int var8 = appArray.length;
for(int var9 = 0; var9 < var8; ++var9) {
String app = var7[var9];
if (requester.equals(app)) {
exactlyMatch = true;
break;
}
}
contain = exactlyMatch;
}
int strategy = rule.getStrategy();
if (strategy == 1 && contain) {
return false;
} else {
return strategy != 0 || contain;
}
} else {
return true; //如果origin为空,或者限制的来源为空,直接返回true
}
}
private AuthorityRuleChecker() {
}
}
application.yml
spring:
application:
name: hello-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8000
CustomAuthorityRule
public class CustomAuthorityRule implements InitFunc {
@Override
public void init() throws Exception {
AuthorityRule authorityRule = new AuthorityRule();
authorityRule.setResource("/hello").setLimitApp("127.0.0.1,0:0:0:0:0:0:0:1");
authorityRule.setStrategy(RuleConstant.AUTHORITY_BLACK);
//authorityRule.setStrategy(RuleConstant.AUTHORITY_WHITE);
AuthorityRuleManager.loadRules(Collections.singletonList(authorityRule));
}
}
CustomRequestOriginParser:解析请求来源
@Component
public class CustomRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
String origin = httpServletRequest.getParameter("origin");
if (!StringUtils.isEmpty(origin)){
return origin;
}
return httpServletRequest.getRemoteHost();
}
}
HelloController
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "success";
}
}
META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
com.example.demo.config.CustomAuthorityRule
*************
使用测试
localhost:8080/hello
请求被黑名单规则拦截
CustomAuthorityRule:黑名单规则修改为白名单
public class CustomAuthorityRule implements InitFunc {
@Override
public void init() throws Exception {
AuthorityRule authorityRule = new AuthorityRule();
authorityRule.setResource("/hello").setLimitApp("127.0.0.1,0:0:0:0:0:0:0:1");
//authorityRule.setStrategy(RuleConstant.AUTHORITY_BLACK);
authorityRule.setStrategy(RuleConstant.AUTHORITY_WHITE);
AuthorityRuleManager.loadRules(Collections.singletonList(authorityRule));
}
}
localhost:8080/hello
请求可以正常通过