亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

annuaire recherche
閱讀前篇 簡介 Yii 是什么 從 Yii 1.1 升級 入門 安裝 Yii 運行應(yīng)用 第一次問候 使用Forms 數(shù)據(jù)庫應(yīng)用 使用 Gii 生成代碼 進階 應(yīng)用結(jié)構(gòu) 概述 入口腳本 應(yīng)用(Applications) 應(yīng)用組件(Application Components) 控制器(Controllers) 模型(Models) 視圖(views) 模塊(Modules) 過濾器(Filters) 小部件(Widgets) 前端資源(Assets) 擴展(Extensions) 請求處理 運行概述 啟動引導(dǎo)(Bootstrapping) 路由和創(chuàng)建URL 請求(Requests) 響應(yīng)(Responses) Sessions 和 Cookies 錯誤處理(Handling Errors) 日志(Logging) 關(guān)鍵概念 組件(Component) 屬性(Property) 事件(Events) 行為(Behaviors) 配置(Configurations) 別名(Aliases) 類自動加載(Autoloading) 服務(wù)定位器(Service Locator) 依賴注入容器(Dependency Injection Container) 配合數(shù)據(jù)庫工作 數(shù)據(jù)庫訪問 (Data Access Objects) 查詢生成器(Query Builder) 活動記錄(Active Record) 數(shù)據(jù)庫遷移(Migrations) Sphinx Redis MongoDB Elasticsearch 接收用戶數(shù)據(jù) 創(chuàng)建表單(Creating Forms) 輸入驗證(Validating Input) 文件上傳(Uploading Files) 收集列表輸入(Collecting Tabular Input) 多模型的復(fù)合表單(Getting Data for Multiple Models) 顯示數(shù)據(jù) 格式化輸出數(shù)據(jù)(Data Formatting) 分頁(Pagination) 排序(Sorting) 數(shù)據(jù)提供器(Data Providers) 數(shù)據(jù)小部件(Data Widgets) 客戶端腳本使用(Working with Client Scripts) 主題(Theming) 安全 認(rèn)證(Authentication) 授權(quán)(Authorization) 處理密碼(Working with Passwords) 客戶端認(rèn)證(Auth Clients) 最佳安全實踐(Best Practices) 緩存 概述 數(shù)據(jù)緩存 片段緩存 頁面緩存 HTTP 緩存 RESTfull Web服務(wù) 快速入門(Quick Start) 資源(Resources) 控制器(Controllers) 路由(Routing) 格式化響應(yīng)(Response Formatting) 授權(quán)認(rèn)證(Authentication) 速率限制(Rate Limiting) 版本(Versioning) 錯誤處理(Error Handling) 開發(fā)工具 調(diào)試工具欄和調(diào)試器 使用Gii生成代碼 生成API文檔 測試 概述(Overview) 配置測試環(huán)境(Testing environment setup) 單元測試(Unit Tests) 功能測試(Function Tests) 驗收測試(Acceptance Tests) 測試夾具(Fixtures) 高級專題 高級應(yīng)用模板 創(chuàng)建自定義應(yīng)用程序結(jié)構(gòu) 控制臺命令 核心驗證器(Core Validators) 國際化 收發(fā)郵件 性能優(yōu)化 共享主機環(huán)境 模板引擎 集成第三方代碼 小部件 Bootstrap 小部件 Jquery UI 助手類 概述 Array 助手(ArrayHelper) Html 助手(Html) Url 助手(Url)
personnages

授權(quán)

授權(quán)

授權(quán)是指驗證用戶是否允許做某件事的過程。Yii提供兩種授權(quán)方法: 存取控制過濾器(ACF)和基于角色的存取控制(RBAC)。

存取控制過濾器

存取控制過濾器(ACF)是一種通過 yii\filters\AccessControl 類來實現(xiàn)的簡單授權(quán)方法, 非常適用于僅需要簡單的存取控制的應(yīng)用。正如其名稱所指,ACF 是一個種行動(action)過濾器?filter,可在控制器或者模塊中使用。當(dāng)一個用戶請求一個 action 時, ACF會檢查 yii\filters\AccessControl::rules 列表,判斷該用戶是否允許執(zhí) 行所請求的action。(譯者注:?action?在本文中視情況翻譯為行動、操作、方法等)

下述代碼展示如何在?site?控制器中使用 ACF:

use yii\web\Controller;
use yii\filters\AccessControl;

class SiteController extends Controller{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['login', 'logout', 'signup'],
                'rules' => [
                    [
                        'allow' => true,
                        'actions' => ['login', 'signup'],
                        'roles' => ['?'],
                    ],
                    [
                        'allow' => true,
                        'actions' => ['logout'],
                        'roles' => ['@'],
                    ],
                ],
            ],
        ];
    }
    // ...
}

上面的代碼中 ACF 以行為 (behavior) 的形式附加到?site?控制器。 這就是很典型的使用行動過濾器的方法。?only?選項指明 ACF 應(yīng)當(dāng)只 對?login,?logout?和?signup?方法起作用。所有其它的?site?控制器中的方法不受存取控制的限制。?rules?選項列出了 yii\filters\AccessRule,解讀如下:

  • 允許所有訪客(還未經(jīng)認(rèn)證的用戶)執(zhí)行?login?和?signup?操作。?roles?選項包含的問號???是一個特殊的標(biāo)識,代表”訪客用戶”。
  • 允許已認(rèn)證用戶執(zhí)行?logout?操作。@是另一個特殊標(biāo)識, 代表”已認(rèn)證用戶”。

ACF 自頂向下逐一檢查存取規(guī)則,直到找到一個與當(dāng)前 欲執(zhí)行的操作相符的規(guī)則。 然后該匹配規(guī)則中的?allow?選項的值用于判定該用戶是否獲得授權(quán)。如果沒有找到匹配的規(guī)則, 意味著該用戶沒有獲得授權(quán)。(譯者注:?only?中沒有列出的操作,將無條件獲得授權(quán))

當(dāng) ACF 判定一個用戶沒有獲得執(zhí)行當(dāng)前操作的授權(quán)時,它的默認(rèn)處理是:

  • 如果該用戶是訪客,將調(diào)用 yii\web\User::loginRequired() 將用戶的瀏覽器重定向到登錄頁面。
  • 如果該用戶是已認(rèn)證用戶,將拋出一個 yii\web\ForbiddenHttpException 異常。

你可以通過配置 yii\filters\AccessControl::denyCallback 屬性定制該行為:

[
    'class' => AccessControl::className(),
    ...
    'denyCallback' => function ($rule, $action) {
        throw new \Exception('You are not allowed to access this page');
    }
]

yii\filters\AccessRule 支持很多的選項。下列是所支持選項的總覽。 你可以派生 yii\filters\AccessRule 來創(chuàng)建自定義的存取規(guī)則類。

  • yii\filters\AccessRule::allow: 指定該規(guī)則是 "允許" 還是 "拒絕" 。(譯者注:true是允許,false是拒絕)

  • yii\filters\AccessRule::actions:指定該規(guī)則用于匹配哪些操作。 它的值應(yīng)該是操作方法的ID數(shù)組。匹配比較是大小寫敏感的。如果該選項為空,或者不使用該選項, 意味著當(dāng)前規(guī)則適用于所有的操作。

  • yii\filters\AccessRule::controllers:指定該規(guī)則用于匹配哪些控制器。 它的值應(yīng)為控制器ID數(shù)組。匹配比較是大小寫敏感的。如果該選項為空,或者不使用該選項, 則意味著當(dāng)前規(guī)則適用于所有的操作。(譯者注:這個選項一般是在控制器的自定義父類中使用才有意義)

  • yii\filters\AccessRule::roles:指定該規(guī)則用于匹配哪些用戶角色。 系統(tǒng)自帶兩個特殊的角色,通過 yii\web\User::isGuest 來判斷:

    • ?: 用于匹配訪客用戶 (未經(jīng)認(rèn)證)
    • @: 用于匹配已認(rèn)證用戶
  • 使用其他角色名時,將觸發(fā)調(diào)用 yii\web\User::can(),這時要求 RBAC 的支持 (在下一節(jié)中闡述)。 如果該選項為空或者不使用該選項,意味著該規(guī)則適用于所有角色。

  • yii\filters\AccessRule::ips:指定該規(guī)則用于匹配哪些 yii\web\Request::userIP 。 IP 地址可在其末尾包含通配符?*?以匹配一批前綴相同的IP地址。 例如,192.168.*?匹配所有?192.168.?段的IP地址。 如果該選項為空或者不使用該選項,意味著該規(guī)則適用于所有角色。

  • yii\filters\AccessRule::verbs:指定該規(guī)則用于匹配哪種請求方法(例如GET,POST)。 這里的匹配大小寫不敏感。

  • yii\filters\AccessRule::matchCallback:指定一個PHP回調(diào)函數(shù)用于 判定該規(guī)則是否滿足條件。(譯者注:此處的回調(diào)函數(shù)是匿名函數(shù))

  • yii\filters\AccessRule::denyCallback: 指定一個PHP回調(diào)函數(shù), 當(dāng)這個規(guī)則不滿足條件時該函數(shù)會被調(diào)用。(譯者注:此處的回調(diào)函數(shù)是匿名函數(shù))

以下例子展示了如何使用?matchCallback?選項, 可使你設(shè)計任意的訪問權(quán)限檢查邏輯:

use yii\filters\AccessControl;

class SiteController extends Controller{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['special-callback'],
                'rules' => [
                    [
                        'actions' => ['special-callback'],
                        'allow' => true,
                        'matchCallback' => function ($rule, $action) {
                            return date('d-m') === '31-10';
                        }
                    ],
                ],
            ],
        ];
    }

    // 匹配的回調(diào)函數(shù)被調(diào)用了!這個頁面只有每年的10月31號能訪問(譯者注:原文在這里說該方法是回調(diào)函數(shù)不確切,讀者不要和 `matchCallback` 的值即匿名的回調(diào)函數(shù)混淆理解)。
    public function actionSpecialCallback()
    {
        return $this->render('happy-halloween');
    }
}

基于角色的存取控制 (RBAC)

基于角色的存取控制 (RBAC) 提供了一個簡單而強大的集中式存取控制機制。 詳細的關(guān)于 RBAC 和諸多傳統(tǒng)的存取控制方案對比的詳情,請參閱?Wikipedia。

Yii 實現(xiàn)了通用的分層的 RBAC,遵循的模型是?NIST RBAC model. 它通過 yii\rbac\ManagerInterface?application component?提供 RBAC 功能。

使用 RBAC 涉及到兩部分工作。第一部分是建立授權(quán)數(shù)據(jù), 而第二部分是使用這些授權(quán)數(shù)據(jù)在需要的地方執(zhí)行檢查。

為方便后面的講述,這里先介紹一些 RBAC 的基本概念。

基本概念

角色是?權(quán)限?的集合 (例如:建貼、改貼)。一個角色 可以指派給一個或者多個用戶。要檢查某用戶是否有一個特定的權(quán)限, 系統(tǒng)會檢查該包含該權(quán)限的角色是否指派給了該用戶。

可以用一個規(guī)則?rule?與一個角色或者權(quán)限關(guān)聯(lián)。一個規(guī)則用一段代碼代表, 規(guī)則的執(zhí)行是在檢查一個用戶是否滿足這個角色或者權(quán)限時進行的。例如,"改帖" 的權(quán)限 可以使用一個檢查該用戶是否是帖子的創(chuàng)建者的規(guī)則。權(quán)限檢查中,如果該用戶 不是帖子創(chuàng)建者,那么他(她)將被認(rèn)為不具有 "改帖"的權(quán)限。

角色和權(quán)限都可以按層次組織。特定情況下,一個角色可能由其他角色或權(quán)限構(gòu)成, 而權(quán)限又由其他的權(quán)限構(gòu)成。Yii 實現(xiàn)了所謂的?局部順序?的層次結(jié)構(gòu),包含更多的特定的??的層次。 一個角色可以包含一個權(quán)限,反之則不行。(譯者注:可理解為角色在上方,權(quán)限在下方,從上到下如果碰到權(quán)限那么再往下不能出現(xiàn)角色)

配置 RBAC

在開始定義授權(quán)數(shù)據(jù)和執(zhí)行存取檢查之前,需要先配置應(yīng)用組件 yii\base\Application::authManager 。 Yii 提供了兩套授權(quán)管理器: yii\rbac\PhpManager 和 yii\rbac\DbManager。前者使用 PHP 腳本存放授權(quán)數(shù)據(jù), 而后者使用數(shù)據(jù)庫存放授權(quán)數(shù)據(jù)。 如果你的應(yīng)用不要求大量的動態(tài)角色和權(quán)限管理, 你可以考慮使用前者。

使用?PhpManager

以下代碼展示使用 yii\rbac\PhpManager 時如何在應(yīng)用配置文件中配置?authManager

return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\PhpManager',
        ],
        // ...
    ],
];

現(xiàn)在可以通過?\Yii::$app->authManager?訪問?authManager?。

yii\rbac\PhpManager 默認(rèn)將 RBAC 數(shù)據(jù)保存在?@app/rbac?目錄下的文件中。 如果權(quán)限層次數(shù)據(jù)在運行時會被修改,需確保WEB服務(wù)器進程對該目錄和其中的文件有寫權(quán)限。

使用?DbManager

以下代碼展示使用 yii\rbac\DbManager 時如何在應(yīng)用配置文件中配置?authManager

return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\DbManager',
        ],
        // ...
    ],
];

DbManager?使用4個數(shù)據(jù)庫表存放它的數(shù)據(jù):

  • yii\rbac\DbManager::$itemTable: 該表存放授權(quán)條目(譯者注:即角色和權(quán)限)。默認(rèn)表名為 "auth_item" 。
  • yii\rbac\DbManager::$itemChildTable: 該表存放授權(quán)條目的層次關(guān)系。默認(rèn)表名為 "auth_item_child"。
  • yii\rbac\DbManager::$assignmentTable: 該表存放授權(quán)條目對用戶的指派情況。默認(rèn)表名為 "auth_assignment"。
  • yii\rbac\DbManager::$ruleTable: 該表存放規(guī)則。默認(rèn)表名為 "auth_rule"。

繼續(xù)之前,你需要在數(shù)據(jù)庫中創(chuàng)建這些表。你可以使用存放在?@yii/rbac/migrations?目錄中的數(shù)據(jù)庫遷移文件來做這件事(譯者注:根據(jù)本人經(jīng)驗,最好是將授權(quán)數(shù)據(jù)初始化命令也寫到這個 RBAC 數(shù)據(jù)庫遷移文件中):

yii migrate --migrationPath=@yii/rbac/migrations

現(xiàn)在可以通過?\Yii::$app->authManager?訪問?authManager?。

建立授權(quán)數(shù)據(jù)

所有授權(quán)數(shù)據(jù)相關(guān)的任務(wù)如下:

  • 定義角色和權(quán)限;
  • 建立角色和權(quán)限的關(guān)系;
  • 定義規(guī)則;
  • 將規(guī)則與角色和權(quán)限作關(guān)聯(lián);
  • 指派角色給用戶。

根據(jù)授權(quán)的彈性需求,上述任務(wù)可用不同的方法完成。

如果你的權(quán)限層次結(jié)構(gòu)不會發(fā)生改變,而且你的用戶數(shù)是恒定的,你可以通過?authManager?提供的 API 創(chuàng)建一個?控制臺命令?一次性初始化授權(quán)數(shù)據(jù):

<?phpnamespace app\commands;

use Yii;
use yii\console\Controller;

class RbacController extends Controller{
    public function actionInit()
    {
        $auth = Yii::$app->authManager;

        // 添加 "createPost" 權(quán)限
        $createPost = $auth->createPermission('createPost');
        $createPost->description = 'Create a post';
        $auth->add($createPost);

        // 添加 "updatePost" 權(quán)限
        $updatePost = $auth->createPermission('updatePost');
        $updatePost->description = 'Update post';
        $auth->add($updatePost);

        // 添加 "author" 角色并賦予 "createPost" 權(quán)限
        $author = $auth->createRole('author');
        $auth->add($author);
        $auth->addChild($author, $createPost);

        // 添加 "admin" 角色并賦予 "updatePost" 
                // 和 "author" 權(quán)限
        $admin = $auth->createRole('admin');
        $auth->add($admin);
        $auth->addChild($admin, $updatePost);
        $auth->addChild($admin, $author);

        // 為用戶指派角色。其中 1 和 2 是由 IdentityInterface::getId() 返回的id (譯者注:user表的id)
        // 通常在你的 User 模型中實現(xiàn)這個函數(shù)。
        $auth->assign($author, 2);
        $auth->assign($admin, 1);
    }
}

在用?yii rbac/init?執(zhí)行了這個命令后,我們將得到下圖所示的層次結(jié)構(gòu):

Simple RBAC hierarchy

作者可創(chuàng)建新貼,管理員可編輯帖子以及所有作者可做的事情。

如果你的應(yīng)用允許用戶注冊,你需要在注冊時給新用戶指派一次角色。例如, 在高級項目模板中,要讓所有注冊用戶成為作者,你需要如下例所示修改?frontend\models\SignupForm::signup()?方法:

public function signup(){
    if ($this->validate()) {
        $user = new User();
        $user->username = $this->username;
        $user->email = $this->email;
        $user->setPassword($this->password);
        $user->generateAuthKey();
        $user->save(false);

        // 要添加以下三行代碼:
        $auth = Yii::$app->authManager;
        $authorRole = $auth->getRole('author');
        $auth->assign($authorRole, $user->getId());

        return $user;
    }

    return null;
}

對于有動態(tài)更改授權(quán)數(shù)據(jù)的復(fù)雜存取控制需求的,你可能需要使用?authManager?提供的 API 的開發(fā)用戶界面(例如:管理面板)。

使用規(guī)則 (Rules)

如前所述,規(guī)則給角色和權(quán)限增加額外的約束條件。規(guī)則是 yii\rbac\Rule 的派生類。 它需要實現(xiàn) yii\rbac\Rule::execute() 方法。在之前我們創(chuàng)建的層次結(jié)構(gòu)中,作者不能編輯自己的帖子,我們來修正這個問題。 首先我們需要一個規(guī)則來認(rèn)證當(dāng)前用戶是帖子的作者:

namespace app\rbac;

use yii\rbac\Rule;

class AuthorRule extends Rule{
    public $name = 'isAuthor';

    
    public function execute($user, $item, $params)
    {
        return isset($params['post']) ? $params['post']->createdBy == $user : false;
    }
}

上述規(guī)則檢查?post?是否是?$user?創(chuàng)建的。我們還要在之前的命令中 創(chuàng)建一個特別的權(quán)限?updateOwnPost?:

$auth = Yii::$app->authManager;

// 添加規(guī)則$rule = new \app\rbac\AuthorRule;
$auth->add($rule);

// 添加 "updateOwnPost" 權(quán)限并與規(guī)則關(guān)聯(lián)$updateOwnPost = $auth->createPermission('updateOwnPost');
$updateOwnPost->description = 'Update own post';
$updateOwnPost->ruleName = $rule->name;
$auth->add($updateOwnPost);

// "updateOwnPost" 權(quán)限將由 "updatePost" 權(quán)限使用$auth->addChild($updateOwnPost, $updatePost);

// 允許 "author" 更新自己的帖子$auth->addChild($author, $updateOwnPost);

現(xiàn)在我們得到如下層次結(jié)構(gòu):

RBAC hierarchy with a rule

存取檢查

授權(quán)數(shù)據(jù)準(zhǔn)備好后,存取檢查簡單到只需要一個方法調(diào)用 yii\rbac\ManagerInterface::checkAccess()。 因為大多數(shù)存取檢查都是針對當(dāng)前用戶而言,為方便起見, Yii 提供了一個快捷方法 yii\web\User::can(),可以如下例所示來使用:

if (\Yii::$app->user->can('createPost')) {
    // 建貼
}

如果當(dāng)前用戶是?ID=1?的 Jane ,我們從圖中的?createPost?開始,并試圖到達?Jane?。 (譯者注:參照圖中紅色路線所示的建貼授權(quán)流程)

Access check

為了檢查某用戶是否能更新帖子,我們需要傳遞一個額外的參數(shù),該參數(shù)是?AuthorRule?要用的:

if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
    // 更新帖子
}

下圖所示為當(dāng)前用戶是 John 時所發(fā)生的事情:

Access check

我們從圖中的?updatePost?開始,經(jīng)過?updateOwnPost。為通過檢查,Authorrule?規(guī)則的?execute()?方法應(yīng)當(dāng)返回?true?。該方法從can()?方法調(diào)用接收到?$params?參數(shù), 因此它的值是?['post' => $post]?。如果一切順利,我們會達到指派給 John 的?author?角色。

對于 Jane 來說則更簡單,因為她是管理員:

Access check

使用默認(rèn)角色

所謂默認(rèn)角色就是?隱式?地指派給?所有?用戶的角色。不需要調(diào)用 yii\rbac\ManagerInterface::assign() 方法做顯示指派,并且授權(quán)數(shù)據(jù)中不包含指派信息。

默認(rèn)角色通常與一個規(guī)則關(guān)聯(lián),用以檢查該角色是否符合被檢查的用戶。

默認(rèn)角色常常用于已經(jīng)確立了一些角色的指派關(guān)系的應(yīng)用(譯者注:指派關(guān)系指的是應(yīng)用業(yè)務(wù)邏輯層面, 并非指授權(quán)數(shù)據(jù)的結(jié)構(gòu))。比如,一個應(yīng)用的 user 表中有一個?group?字段,代表用戶屬于哪個特權(quán)組。 如果每個特權(quán)組可以映射到 RBAC 的角色,你就可以采用默認(rèn)角色自動地為每個用戶指派一個 RBAC 角色。 讓我們用一個例子展示如何做到這一點。

假設(shè)在 user 表中,你有一個?group?字段,用 1 代表管理員組,用 2 表示作者組。 你規(guī)劃兩個 RBAC 角色?admin?和?author?分別對應(yīng)這兩個組的權(quán)限。 你可以這樣設(shè)置 RBAC 數(shù)據(jù),

namespace app\rbac;

use Yii;
use yii\rbac\Rule;

class UserGroupRule extends Rule{
    public $name = 'userGroup';

    public function execute($user, $item, $params)
    {
        if (!Yii::$app->user->isGuest) {
            $group = Yii::$app->user->identity->group;
            if ($item->name === 'admin') {
                return $group == 1;
            } elseif ($item->name === 'author') {
                return $group == 1 || $group == 2;
            }
        }
        return false;
    }
}

$auth = Yii::$app->authManager;

$rule = new \app\rbac\UserGroupRule;
$auth->add($rule);

$author = $auth->createRole('author');
$author->ruleName = $rule->name;
$auth->add($author);
// ... 添加$author角色的子項部分代碼 ... (譯者注:省略部分參照之前的控制臺命令)

$admin = $auth->createRole('admin');
$admin->ruleName = $rule->name;
$auth->add($admin);
$auth->addChild($admin, $author);
// ... 添加$admin角色的子項部分代碼 ... (譯者注:省略部分參照之前的控制臺命令)

注意,在上述代碼中,因為 "author" 作為 "admin" 的子角色,當(dāng)你實現(xiàn)這個規(guī)則的?execute()?方法時, 你也需要遵從這個層次結(jié)構(gòu)。這就是為何當(dāng)角色名為 "author" 的情況下(譯者注:$item->name就是角色名),?execute()?方法在組為 1 或者 2 時均要返回 true (意思是用戶屬于 "admin" 或者 "author" 組 )。

接下來,在配置?authManager?時指定 yii\rbac\BaseManager::$defaultRoles 選項(譯者注:在應(yīng)用配置文件中的組件部分配置):

return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yii\rbac\PhpManager',
            'defaultRoles' => ['admin', 'author'],
        ],
        // ...
    ],
];
現(xiàn)在如果你執(zhí)行一個存取權(quán)限檢查, 判定該規(guī)則時,?admin?和?author?兩個角色都將會檢查。如果規(guī)則返回 true ,意思是角色符合當(dāng)前用戶?;谏鲜鲆?guī)則 的實現(xiàn),意味著如果某用戶的?group?值為 1 ,?admin?角色將賦予該用戶, 如果?group?值是 2 則將賦予?author角色。
Article précédent: Article suivant: