func onHttpRequestHeaders()

in plugins/wasm-go/extensions/basic-auth/main.go [191:293]


func onHttpRequestHeaders(ctx wrapper.HttpContext, config BasicAuthConfig, log wrapper.Log) types.Action {
	var (
		noAllow            = len(config.allow) == 0 // 未配置 allow 列表,表示插件在该 domain/route 未生效
		globalAuthNoSet    = config.globalAuth == nil
		globalAuthSetTrue  = !globalAuthNoSet && *config.globalAuth
		globalAuthSetFalse = !globalAuthNoSet && !*config.globalAuth
	)
	// log.Debugf("global auth set: %t", !globalAuthNoSet)
	// log.Debugf("rule set: %t", ruleSet)
	// log.Debugf("config: %+v", config)

	// 不需要认证而直接放行的情况:
	// - global_auth == false 且 当前 domain/route 未配置该插件
	// - global_auth 未设置 且 有至少一个 domain/route 配置该插件 且 当前 domain/route 未配置该插件
	if globalAuthSetFalse || (globalAuthNoSet && ruleSet) {
		if noAllow {
			log.Info("authorization is not required")
			return types.ActionContinue
		}
	}

	// 以下为需要认证的情况:
	auth, err := proxywasm.GetHttpRequestHeader("Authorization")
	if err != nil {
		log.Warnf("failed to get authorization: %v", err)
		return deniedNoBasicAuthData()
	}
	if auth == "" {
		log.Warnf("authorization is empty")
		return deniedNoBasicAuthData()
	}
	if !strings.HasPrefix(auth, "Basic ") {
		log.Warnf("authorization has no prefix 'Basic '")
		return deniedNoBasicAuthData()
	}

	encodedCredential := strings.TrimPrefix(auth, "Basic ")
	credentialByte, err := base64.StdEncoding.DecodeString(encodedCredential)
	if err != nil {
		log.Warnf("failed to decode authorization %q: %v", string(credentialByte), err)
		return deniedInvalidCredentials()
	}

	credential := string(credentialByte)
	userAndPasswd := strings.Split(credential, ":")
	if len(userAndPasswd) != 2 {
		log.Warnf("invalid credential format: %s", credential)
		return deniedInvalidCredentials()
	}

	user, passwd := userAndPasswd[0], userAndPasswd[1]
	if correctPasswd, ok := config.username2Passwd[user]; !ok {
		log.Warnf("credential username %q is not configured", user)
		return deniedInvalidCredentials()
	} else {
		if passwd != correctPasswd {
			log.Warnf("credential password is not correct for username %q", user)
			return deniedInvalidCredentials()
		}
	}

	// 以下为 username 和 password 正确的情况:
	name, ok := config.credential2Name[credential]
	if !ok { // 理论上该分支永远不可达,因为 username 和 password 都是从 credential 中获取的
		log.Warnf("credential %q is not configured", credential)
		return deniedUnauthorizedConsumer()
	}

	// 全局生效:
	// - global_auth == true 且 当前 domain/route 未配置该插件
	// - global_auth 未设置 且 没有任何一个 domain/route 配置该插件
	if (globalAuthSetTrue && noAllow) || (globalAuthNoSet && !ruleSet) {
		// log.Debug("authenticated case 1")
		log.Infof("consumer %q authenticated", name)
		return authenticated(name)
	}

	// 全局生效,但当前 domain/route 配置了 allow 列表
	if globalAuthSetTrue && !noAllow {
		if !contains(config.allow, name) {
			log.Warnf("consumer %q is not allowed", name)
			return deniedUnauthorizedConsumer()
		}
		// log.Debug("authenticated case 2")
		log.Infof("consumer %q authenticated", name)
		return authenticated(name)
	}

	// 非全局生效
	if globalAuthSetFalse || (globalAuthNoSet && ruleSet) {
		if !noAllow { // 配置了 allow 列表
			if !contains(config.allow, name) {
				log.Warnf("consumer %q is not allowed", name)
				return deniedUnauthorizedConsumer()
			}
			// log.Debug("authenticated case 3")
			log.Infof("consumer %q authenticated", name)
			return authenticated(name)
		}
	}

	return types.ActionContinue
}