Sentinel Architecture - Source Access Control

Source access control (black and white lists)

concept

Sentinel provides the function of black and white lists to restrict the passage of resources. If a whitelist is configured, only requests corresponding to request sources in the whitelist can pass; if a blacklist is configured, requests corresponding to request sources in the blacklist cannot pass.

Actual operation

insert image description here

In the configuration management/configuration list of the Nacos console, create the following configuration in the public namespace:

dataId:spring-cloud-demo-provider-sentinel-authority

group:DEFAULT_GROUP

The configuration content is as follows:

[
    {
    
    
        "resource": "/hello",
        "limitApp": "white-origin",
        "strategy": 0
    },
    {
    
    
        "resource": "/hello/say",
        "limitApp": "black-origin",
        "strategy": 1
    }
]

If strategy is 0, it means white list; if it is 1, it means black list.

limitApp If there are multiple request sources, separate them with commas.


The corresponding client configuration file is as follows:

spring:
    application:
        name: spring-cloud-demo-provider
    cloud:
        nacos:
            discovery:
                server-addr: 10.211.55.11:8848,10.211.55.12:8848,10.211.55.13:8848
                enabled: true
        sentinel:
            transport:
                dashboard: 127.0.0.1:9000
            eager: true
            web-context-unify: false
            datasource:
                authority-nacos-datasource:
                    nacos:
                        server-addr: 10.211.55.11:8848,10.211.55.12:8848,10.211.55.13:8848
                        group-id: DEFAULT_GROUP
                        namespace: public
                        data-id: ${
    
    spring.application.name}-sentinel-authority
                        data-type: json
                        rule-type: authority
                        username: nacos
                        password: nacos

Then register a Bean of type RequestOriginParser.

@Component
public class MyRequestOriginParser implements RequestOriginParser {
    
    
    @Override
    public String parseOrigin(HttpServletRequest httpServletRequest) {
    
    
        String origin = httpServletRequest.getHeader("origin");
        if (StringUtils.isBlank(origin)) {
    
    
            origin = "default";
        }
        return origin;
    }
}

When requesting, add a pair of origin, whiteOrigin or origin, blackOrigin to the request header to see the restriction effect of the black and white lists on specific resources.

In actual operation, I personally found that if restricted by the black and white list, the program will not throw an exception, but output Blocked by Sentinel (flow limiting) in the response.

AuthoritySlot

Responsible for verifying the authorization rules of the request source.

@Spi(order = Constants.ORDER_AUTHORITY_SLOT)
public class AuthoritySlot extends AbstractLinkedProcessorSlot<DefaultNode> {
    
    

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, boolean prioritized, Object... args)
        throws Throwable {
    
    
      	// 校验请求来源的授权规则
        checkBlackWhiteAuthority(resourceWrapper, context);
      	// 交给下一个ProcessorSlot继续处理
        fireEntry(context, resourceWrapper, node, count, prioritized, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
    
    
      	// 交给下一个ProcessorSlot继续处理
        fireExit(context, resourceWrapper, count, args);
    }

    void checkBlackWhiteAuthority(ResourceWrapper resource, Context context) throws AuthorityException {
    
    
      	// 加载所有资源的授权规则
        Map<String, Set<AuthorityRule>> authorityRules = AuthorityRuleManager.getAuthorityRules();
		// 如果授权规则列表为空,则直接返回
        if (authorityRules == null) {
    
    
            return;
        }

      	// 获取指定资源的授权规则列表
        Set<AuthorityRule> rules = authorityRules.get(resource.getName());
      	// 如果对应的授权规则列表为空,则直接返回
        if (rules == null) {
    
    
            return;
        }
      
		// 遍历授权规则列表
        for (AuthorityRule rule : rules) {
    
    
          	// 如果有一个授权规则没有校验通过,则抛出异常
            if (!AuthorityRuleChecker.passCheck(rule, context)) {
    
    
                throw new AuthorityException(context.getOrigin(), rule);
            }
        }
    }
}

Next, look at the internal logic of the passCheck method of AuthorityRuleChecker.

static boolean passCheck(AuthorityRule rule, Context context) {
    
    
  	// 获取上下文记录的请求来源
    String requester = context.getOrigin();

    // 如果请求来源为空或者授权规则的limitApp为空,则返回true,表示校验通过
    if (StringUtil.isEmpty(requester) || StringUtil.isEmpty(rule.getLimitApp())) {
    
    
        return true;
    }

    // 判断授权规则的limitApp中是否存在指定的请求来源
    int pos = rule.getLimitApp().indexOf(requester);
    boolean contain = pos > -1;

    if (contain) {
    
    
        boolean exactlyMatch = false;
      	// 用逗号分隔
        String[] appArray = rule.getLimitApp().split(",");
      	// 判断授权规则中是否对指定的请求来源进行了限制
        for (String app : appArray) {
    
    
            if (requester.equals(app)) {
    
    
                exactlyMatch = true;
                break;
            }
        }

        contain = exactlyMatch;
    }

    int strategy = rule.getStrategy();
  	// 如果设置了黑名单,并且授权规则中包含指定的请求来源,则返回false,表示校验不通过
    if (strategy == RuleConstant.AUTHORITY_BLACK && contain) {
    
    
        return false;
    }
	// 如果设置了白名单,并且授权规则中不包含指定的请求来源,则返回false,表示校验不通过
    if (strategy == RuleConstant.AUTHORITY_WHITE && !contain) {
    
    
        return false;
    }
	// 其余请求,返回true,表示校验通过
    return true;
}

Guess you like

Origin blog.csdn.net/qq_34561892/article/details/129410134