sentinel 来源访问控制


sentinel 来源访问控制

           

官网: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() {
    }
}

           

                   

                                 

使用示例

  

                       sentinel 来源访问控制_第1张图片

         

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

           sentinel 来源访问控制_第2张图片

请求被黑名单规则拦截

               

 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

           sentinel 来源访问控制_第3张图片

 请求可以正常通过

       

         

你可能感兴趣的:(spring,cloud,alibaba,sentinel,sentinel)