エレガントなカットとコメントの権限は検証を達成するために使用する方法

背景

私たちのシステムのアクセス許可の検証は、ビジネスロジックは何の関係もありませんが、それはビジネス機能に密接に関連しています。
我々は、システムのメンバーをカスタマイズするために、中小企業のためのビジョンを開発しました。システムは、企業A、Bおよびその他の企業のためのサービスを提供することができます。データベースのテーブル構造(以下は単なるデモで、フィールド内の実際の状況はますます複雑になります)ので、多くの場合、次のとおりです。

ID memberCardCode userNameに card_status ビジネス
1 a564456578 zhangsan 0 ビジネス-A
2 b678688643 溶解 1 businsss-B
3 a775445667 wangwu 0 businsss-A
4 b943578978 zhaoliu 1 businsss-B
5 c657688799 sunqi 1 businsss-C

:上記の表に基づいて、我々は、ID = 1人のメンバーは、多くの場合、この操作(物理的に削除されると仮定)を除去
コントローラ層。

@RestController("/member")
public class MemberController {
    @PostMapping("/delete")
    public void deleteById(int id) {
        // 此处省略删除代码
    }
}
复制代码

このようなコントローラの最後の呼び出しでSQL文:

delete from member where id = 1;
复制代码

一見すると、どんな問題を抱えているために、このような単純なSQL文ですか?実際には、もっと簡単な質問には、より手放すことはできません。
テーブルによって、我々は1がビジネスに属し=会員情報IDを参照してください。あなたが= 1会員情報IDを削除することができ、ビジネス・アカウントであることを想定しています。1へのidパラメータは、その後、ビジネス-Bがあるでしょうビジネス-bの削除メンバーならば、その時点ではビジネスのメンバーを削除しました。このとき、ビジネス・気分のクラッシュ。

だから、許可を検証する必要があります。その権威は、それを行う方法を確認しますか?

無粋:侵襲的なビジネスコード体系

コントローラ層に論理判断を添加した:彼らは、その後削除された場合、現在のアカウントIDを削除するかどうかを決定するために、そうでなければ直接返します。コードは以下の通りであります:

@RestController("/member")
public class MemberController {
    @PostMapping("/delete")
    public void deleteById(int id) {
        // 第一步:权限验证
        Integer id = selectByIdAndBusiness(id, "business-a");
        if (id == null) {
            // 说明id不属于business-a不能删除
            return;
        }
        // 第二步:调用删除逻辑
    }
}
复制代码

上記のコードは、越権の問題を解決しないが、いくつかのビジネスは私たちのビジネス・ロジックを侵略するために、コードに依存しない、このロジックは、優雅さを達成することはほとんどありません。その後、我々は完全な権限を確認するために、よりエレガントな方法を選択してください。

エレガント:プログラムの+ノートセクション

idとビジネス:まず、情報の懸念のフィールドをクリアする必要があります。どこで事業をしてThreadLocalのフィルタに保存することができますので、我々は単にフィールドIDに焦点を当てる必要があります。
ステップ1:カスタム注釈を作成します(メソッド演技法)

@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.METHOD)  
public @interface Auth {
    // 方法的参数名称,以防参数名称不是id,所以提供paramName
    String paramName() default "id";
}
复制代码

ステップ2:メソッドに注釈を使用します

package com.demo.controller;
@RestController("/member")
public class MemberController {
    @PostMapping("/delete")
    @Auth(paramId = "deleteId")
    public void deleteById(int deleteId) {
        // 调用删除逻辑
    }
}
复制代码

第三段階:態様を実装

// 通过注解可以看到,我们该方法切的是controller层带有Auth注解的方法
@Before(value = "execution(public * com.demo.controller..*.*(..))"
      + " && @annotation(auth)", argNames = "pjp, auth")
public void before4Auth(JoinPoint pjp, Auth auth) {
    // 1、通过ThreadLocal获取business
    String business = context.get();
    // 2、通过注解解析id
    // 2.1 获取参数值
    Object[] args = pjp.getArgs();
    // 2.2 获取参数名
    MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
    String[] parameterNames = methodSignature.getParameterNames();
    // 2.3 获取注解中paramName的下标
    int index = ArrayUtils.indexOf(parameterNames, auth.paramName());
    // 2.4 根据下标获取id对应的值
    int val = (int) args[index];
    // 2.5 鉴权逻辑
    Integer id = selectByIdAndBusiness(val, business);
    if (id == null) {
        // 抛异常提示越权
    }
    // 否则的正常执行下面的业务逻辑
}
复制代码

このように、我々は、単にメソッドレイヤコントローラを加えた@Auth注釈ができます。立ち入り禁止非ビジネスコード、実装はエレガントと考えることができません。
あなたはよりエレガントな解決策を持っている場合は、アイデアを歓迎します。

おすすめ

転載: juejin.im/post/5d79f66f6fb9a06af13d96d0