目次
hiroのカスタムアノテーションをベースにした拡張
ロジックを介してページとAPIインターフェースを関連付ける方法
Shiro の自己アノテーションの使用法
カスタムアノテーションの書き方
ホームページ Java &#&チュートリアル hiroをベースにしたカスタムアノテーションの拡張 - 画像とテキストで詳しく解説

hiroをベースにしたカスタムアノテーションの拡張 - 画像とテキストで詳しく解説

Aug 09, 2018 pm 05:19 PM
java spring

hiroのカスタムアノテーションをベースにした拡張

ここでは主にhiroのカスタムアノテーションソリューションを採用します。この記事では主に以下の問題を解決します。

  1. ロジックを通じてページを API インターフェースに関連付ける方法。

  2. Shiro の自己アノテーションの使用法。

  3. カスタム注釈の書き方。

ロジックを介してページとAPIインターフェースを関連付ける方法

テーブル間の構造的関係において、ページとインターフェースのテーブルは最終的に権限テーブルに関連付けられます(詳しくは、以前の記事「権限」設計の話」を参照してください) 。
hiroをベースにしたカスタムアノテーションの拡張 - 画像とテキストで詳しく解説今後は、ある程度の権限制御を考慮しながら、別のソリューションに置き換えて低コストを実現したいと考えています。ここでは 2 つの概念を紹介します。 ビジネスモジュール操作タイプ

  • ビジネスモジュール

    • コンセプト: システム内のビジネスモジュールを一種のデータに抽象化します。これは文字列の形式で表現できます。たとえば、ロール管理は role-manage に対応します。ユーザー管理は user-manage などに対応します。システム内に存在する業務モジュールを「最小権限の原則」に基づいて分割し、最終的に分散可能なデータの塊を形成します。

    • 使用原則: API インターフェース、ページ、関数は本質的にビジネス モジュールに論理的に関連しているため、API インターフェースとページ (および関数ポイント) を論理的に照合して、ページが一致しているかどうかを判断できます。ビジネスモジュールの関係。

  • 操作タイプ

    • コンセプト: システム内のすべての操作タイプを一種のデータに抽象化することもできます。たとえば、新しい追加は追加と割り当てに対応します。対応するのはallotなどです。システム内のあらゆる操作を業務モジュールごとの「データライセンス」で分割し、最終的に分散可能なデータの塊を形成します。

    • 使用原則: ページは表示であり、関数ポイントはアクションであり、インターフェイスは最終アクションのためのリソースの提供です。呼び出されるリソースは「ビジネス モジュール」によって決定され、リソースの使用量は「操作タイプ」によって決定されます。この 2 つにより、ページのファンクション ポイントによってトリガーされたインターフェイスが認証内にあるかどうかを大まかかつ正確に判断できます。

さて、この 2 つの概念が提案されたところで、実際の最終的な用途は何でしょうか。まずは以下の観点から考えてみましょう。

  1. データベース内のページテーブルまたはAPIインターフェーステーブルのデータは本物で有効ですか?

  2. ページまたはインターフェイスの実際の使用は、関数の存在またはデータベース テーブル内のデータの存在に基づいています。

  3. 権限構造において、「制御オブジェクト」を保存する唯一の方法はデータベースですか?

これらの質問を結論から見てみましょう。まず、「コントロール オブジェクト」の保存先はデータベース、コード、または設定ファイルにあります。必ずしもデータベースにある必要はありません。 ; 次に 2 番目の質問に答えます。 問題は、インターフェイス情報がデータベースに存在するが、サーバーがこのインターフェイスを開発していない場合、データベース情報自体に問題があるか、データベース内の新しいインターフェイスが次のインターフェイスである必要があることです。有効になるためにサーバーにデプロイされているかどうか、最初の疑問は、データベース内の「コントロール オブジェクト」テーブルのデータが必ずしも真実で有効であるとは限らないということです。そこで、次のような解決策を考え出すことができます

  1. インターフェース上で アノテーション を使用して、「ビジネスモジュール」と「操作タイプ」のデータ情報を補うことができます。どちらのタイプの情報も定数クラスに格納できます。

  2. データベースにページテーブル構造とページ関数テーブル構造を作成するときに、「ビジネスモジュール」フィールドと「操作タイプ」フィールドを追加します。

  3. 「業務モジュール」と「操作タイプ」の情報をデータベースのディクショナリテーブルに格納できます。

  4. モジュールや操作の追加は必然的にインターフェースの追加をもたらし、これによりシステム導入作業が発生します。この操作と保守のコストは削減できず、テーブル構造によっても削減できません。

hiroをベースにしたカスタムアノテーションの拡張 - 画像とテキストで詳しく解説

ただし、このソリューションは非強力なコントロール インターフェイス プロジェクトにのみ適しています。強力なコントロール インターフェイス プロジェクトでは、ページとインターフェイスをバインドする必要がありますが、これには莫大な運用コストとメンテナンス コストがかかります。さらに、/api/page/xxxx/ (ページのみに使用)、/api/mobile/xxxxx (モバイル端末のみに使用) などのインターフェイス ルーティング ルールによって分割して、のみ使用されるインターフェイスを分類することもできます。このクラス インターフェイスは認証のみを実行し、認可は実行しませんが、これによっても目的を達成できます。

Shiro の自己アノテーションの使用法

理論的なアイデアが承認された後、残りは技術的な実践に移されます。以下のシロの注釈を簡単に説明します。

アノテーション名 関数
@RequiresAuthentication は、クラス、メソッド、インスタンスに作用します。呼び出された場合、現在のサブジェクトは認証される必要があります。
@RequiresGuest は、クラス、メソッド、インスタンスに作用します。呼び出されたとき、サブジェクトはゲスト状態になることができます。
@RequiresPermissions は、クラス、メソッド、インスタンスに作用します。呼び出すときは、プロジェクトの現在のインターフェイスに Permission (権限情報) が含まれているかどうかを確認する必要があります。
@RequiresRoles は、クラス、メソッド、インスタンスに作用します。呼び出し時に、サブジェクトに現在のインターフェイスのロール (ロール情報) が含まれているかどうかを判断する必要があります。
@RequiresUser は、クラス、メソッド、インスタンスに作用します。呼び出し時には、対象者が現在アプリケーションを使用しているユーザーであるかどうかを判断する必要があります。
    /**
     * 1.当前接口需要经过"认证"过程
     * @return
     */
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    @RequiresAuthentication
    public String test(){
        return "恭喜你,拿到了参数信息";
    }
    
    /**
     * 2.1.当前接口需要经过权限校验(需包含 角色的查询 或 菜单的查询)
     * @return
     */
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    @RequiresPermissions(value={"role:search","menu":"search"},logical=Logical.OR)
    public String test(){
        return "恭喜你,拿到了参数信息";
    }
    
    /**
     * 2.2.当前接口需要经过权限校验(需包含 角色的查询 与 菜单的查询)
     * @return
     */
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    @RequiresPermissions(value={"role:search","menu":"search"},logical=Logical.OR)
    public String test(){
        return "恭喜你,拿到了参数信息";
    }
    
    /**
     * 3.1.当前接口需要经过角色校验(需包含admin的角色)
     * @return
     */
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    @RequiresRoles(value={"admin"})
    public String test(){
        return "恭喜你,拿到了参数信息";
    }
    
    /**
     * 3.2.当前接口需要经过角色与权限的校验(需包含admin的角色,以及角色的查询 或 菜单的查询)
     * @return
     */
    @RequestMapping(value = "/info",method = RequestMethod.GET)
    @RequiresRoles(value={"admin"})
    @RequiresPermissions(value={"role:search","menu":"search"},logical=Logical.OR)
    public String test(){
        return "恭喜你,拿到了参数信息";
    }
ログイン後にコピー

実際の使用プロセスでは、@RequiresPermissions と @RequiresAuthentication を使用するだけで十分です。 前のセクションの最後で、ビジネス モジュールとオペレーションの組み合わせを採用しました。ページとAPIインターフェースの関係を切り離す方法は、Apache Rokuの方法とまったく同じです。ただし、ロールの組み合わせが多すぎて、インターフェイス内でロール名を一意に表現できないため、 @RequiresRoles はできるだけ使用しないようにします (インターフェイスが特定のロールに属していることを指定するのは困難ですが、インターフェイスが特定のビジネス モジュールに属していることを明確に知ることができます) 一部の操作)

次に、操作プロセス全体を確認してみましょう。

hiroをベースにしたカスタムアノテーションの拡張 - 画像とテキストで詳しく解説

カスタムアノテーションの書き方

しかし、hiroにこれら5つのアノテーションがあるだけでは絶対に十分ではありません。実際の使用プロセスでは、必要に応じて、権限認証に独自のビジネス ロジックを追加し、便宜上、カスタム アノテーションを使用できます。この方法は、Apachehiro だけでなく、Hibernate Validator、SpringMVC などの他の多くのフレームワークにも適用でき、aop でアクセス許可を検証する検証システムを作成することもできますが、これは問題ありません。したがって、カスタム アノテーションには幅広い用途があります。ただし、ここでは hiro に基づいてそれに適したカスタム アノテーションのみを実装します。

  • アノテーションクラスの定義

/**
 * 用于认证的接口的注解,组合形式默认是“或”的关系
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
    /**
     * 业务模块
     * @return
     */
    String[] module();
    /**
     * 操作类型
     */
    String[] action();

}
ログイン後にコピー
  • アノテーション処理クラスの定義

/**
 * Auth注解的操作类
 */
public class AuthHandler extends AuthorizingAnnotationHandler {


    public AuthHandler() {
        //写入注解
        super(Auth.class);
    }

    @Override
    public void assertAuthorized(Annotation a) throws AuthorizationException {
        if (a instanceof Auth) {
            Auth annotation = (Auth) a;
            String[] module = annotation.module();
            String[] action = annotation.action();
            //1.获取当前主题
            Subject subject = this.getSubject();
            //2.验证是否包含当前接口的权限有一个通过则通过
            boolean hasAtLeastOnePermission = false;
            for(String m:module){
                for(String ac:action){
                    //使用hutool的字符串工具类
                    String permission = StrFormatter.format("{}:{}",m,ac);
                    if(subject.isPermitted(permission)){
                        hasAtLeastOnePermission=true;
                        break;
                    }
                }
            }
            if(!hasAtLeastOnePermission){
                throw new AuthorizationException("没有访问此接口的权限");
            }

        }
    }
}
ログイン後にコピー
  • hiroインターセプト処理クラスの定義

/**
 * 拦截器
 */
public class AuthMethodInterceptor extends AuthorizingAnnotationMethodInterceptor {


    public AuthMethodInterceptor() {
        super(new AuthHandler());
    }

    public AuthMethodInterceptor(AnnotationResolver resolver) {
        super(new AuthHandler(), resolver);
    }

    @Override
    public void assertAuthorized(MethodInvocation mi) throws AuthorizationException {
        // 验证权限
        try {
            ((AuthHandler) this.getHandler()).assertAuthorized(getAnnotation(mi));
        } catch (AuthorizationException ae) {
            if (ae.getCause() == null) {
                ae.initCause(new AuthorizationException("当前的方法没有通过鉴权: " + mi.getMethod()));
            }
            throw ae;
        }
    }
}
ログイン後にコピー
  • hiroのAOPアスペクトクラス

/**
 * shiro的aop切面
 */
public class AuthAopInterceptor extends AopAllianceAnnotationsAuthorizingMethodInterceptor {
    public AuthAopInterceptor() {
        super();
        // 添加自定义的注解拦截器
        this.methodInterceptors.add(new AuthMethodInterceptor(new SpringAnnotationResolver()));
    }
}
ログイン後にコピー
  • 定義hiro のカスタム アノテーション スタートアップ クラス

/**
 * 启动自定义注解
 */
public class ShiroAdvisor extends AuthorizationAttributeSourceAdvisor {

    public ShiroAdvisor() {
        // 这里可以添加多个
        setAdvice(new AuthAopInterceptor());
    }

    @SuppressWarnings({"unchecked"})
    @Override
    public boolean matches(Method method, Class targetClass) {
        Method m = method;
        if (targetClass != null) {
            try {
                m = targetClass.getMethod(m.getName(), m.getParameterTypes());
                return this.isFrameAnnotation(m);
            } catch (NoSuchMethodException ignored) {

            }
        }
        return super.matches(method, targetClass);
    }

    private boolean isFrameAnnotation(Method method) {
        return null != AnnotationUtils.findAnnotation(method, Auth.class);
    }
}
ログイン後にコピー
全体的な考え方: アノテーション クラス を定義 (ビジネスで使用できる変数を定義) -> アノテーション処理クラス を定義 (アノテーション内の変数を使用してビジネス ロジックを実行)処理中) -> アノテーション インターセプタを定義 - > aop のアスペクト クラスを定義 - > 最後に hiro のカスタム アノテーション有効化クラスを定義します。他のカスタム アノテーションの書き方のアイデアはこれと似ています。

関連する推奨事項:

カスタムアノテーションマッピング thinkPHP21カスタムタグライブラリのインポート方法の詳細説明

Javaでのカスタムアノテーションの詳細な紹介

Shiro認可実装の詳細説明

以上がhiroをベースにしたカスタムアノテーションの拡張 - 画像とテキストで詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

See all articles