統(tǒng)一驗簽器

切面編程-自定義注解-統(tǒng)一異常攔截-反射

很多有安全要求笑旺,或是系統(tǒng)對接的接口都需要進行簽名驗簽文留。一般我們都是寫個工具類好唯,哪個接口需要自己調,把簽名字段組織好扔進去燥翅。
閑著蛋疼骑篙,寫了個接口層的驗簽注解,包裝了json返回格式权旷,可以自定義替蛉。

1.先定義兩個注解
//標識簽名接口方法
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Signature {
    //入?yún)⒅幸粋€來源標識,綁定了對應的秘鑰鹽值登配置
    String configKey() default "source";
    //入?yún)⒅械暮灻侄蚊袈龋勺远x
    String signKey() default "sign";
    //簽名算法
    String algorithm() default "MD5";
}

//標識簽名字段
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface SignField {
}
2.切面及通知定義
@Aspect
@Component
@Slf4j
public class SignAspect {

    // 簽名開關
    private Boolean signSwitch;

    // 配置 dao
    private ConfigMapper configMapper;

    public SignAspect(Boolean signSwitch, ConfigMapper configMapper) {
        this.signSwitch = signSwitch;
        this.configMapper = configMapper;
    }

    @Pointcut("@annotation(com.***.signature.Signature)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        //簽名開關
        if (Boolean.FALSE.equals(signSwitch)) return pjp.proceed();
        // 取body參數(shù) @SignField
        Object[] params = pjp.getArgs();
        if (params == null || params.length == 0){
            log.error("signAspect doAround params null");
            throw new KKXExeception("驗簽異常,參數(shù)為空!");
        }
        Object param = params[0];
        Map<String,Field> fieldMap = getAllFields(param.getClass());
        MethodSignature methodSignature = ((MethodSignature)pjp.getSignature());
        Method method = methodSignature.getMethod();
        Signature signature = method.getAnnotation(Signature.class);
        Field signKey = fieldMap.get(signature.signKey());
        signKey.setAccessible(true);
        String sign = (String) signKey.get(param);
        if (StringUtil.isEmpty(sign)) throw new KKXExeception("驗簽異常,參數(shù)sign為空躲查!");
        // 查詢配置
        Field configKey = fieldMap.get(signature.configKey());
        configKey.setAccessible(true);
        String source = (String) configKey.get(param);
        if (StringUtil.isEmpty(source)) throw new KKXExeception("驗簽異常,配置參數(shù)為空!");
        String salt = configMapper.querySignKey(source);
        if (StringUtil.isEmpty(salt)) throw new KKXExeception("驗簽異常,未加載到簽名配置译柏!");
        StringBuilder sb = getSignStr(param,fieldMap);
        String actualSign = SignatureUtil.sign(sb,salt);
        if (sign.equals(actualSign)){
            return pjp.proceed();
        }
        throw new KKXExeception("98","簽名驗證失敗");
    }

    private StringBuilder getSignStr(Object param,Map<String,Field> fieldMap) throws Throwable {
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (Field field : fieldMap.values()) {
            SignField annotation = field.getAnnotation(SignField.class);
            if (annotation == null) {
                continue;
            }
            String name = field.getName();
            field.setAccessible(true);
            Object val = field.get(param);
            if (i++ > 0) sb.append("&");
            sb.append(name).append("=").append(val);
        }
        return sb;
    }


    @AfterThrowing(value = "pointCut()", throwing="e")
    public void afterThrowing(Throwable e) {
        log.error("signAspect afterThrowing ",e);
        if(e instanceof KKXExeception) {
            throw (KKXExeception)e;
        }
        throw new KKXExeception("","驗簽異常");
    }

    /**
     * 獲取本類及其父類的屬性的方法
     * @param clazz 當前類對象
     * @return 字段數(shù)組
     */
    private static Map<String,Field> getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null){
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Map<String,Field> fieldMap = new HashMap<>();
        for (Field e : fieldList) {
            fieldMap.put(e.getName(), e);
        }
        return fieldMap;
    }
}
3.統(tǒng)一異常攔截

...略

4.bean注冊

因為需要裝配到具體的項目中镣煮,需要進行spring裝配。
這個有很多方式.

  • 引用jar封裝成springboot-starter @bean + springboot spi定義自動裝配
  • 主項目直接定義@componentscan 掃描到引入jar中的@component
  • 主項目中@bean 注冊(暫采用)
@Bean
public SignAspect signAspect(@Value("${app.signSwitch:true}") Boolean signSwitch, ConfigMapper configMapper){
    return new SignAspect(signSwitch,configMapper);
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末鄙麦,一起剝皮案震驚了整個濱河市典唇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胯府,老刑警劉巖介衔,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異骂因,居然都是意外死亡炎咖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乘盼,“玉大人升熊,你說我怎么就攤上這事〕裾ぃ” “怎么了级野?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粹胯。 經常有香客問我蓖柔,道長,這世上最難降的妖魔是什么风纠? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任渊抽,我火速辦了婚禮,結果婚禮上议忽,老公的妹妹穿的比我還像新娘。我一直安慰自己十减,他們只是感情好栈幸,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著帮辟,像睡著了一般速址。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上由驹,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天芍锚,我揣著相機與錄音,去河邊找鬼蔓榄。 笑死并炮,一個胖子當著我的面吹牛,可吹牛的內容都是我干的甥郑。 我是一名探鬼主播逃魄,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼澜搅!你這毒婦竟也來了伍俘?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤勉躺,失蹤者是張志新(化名)和其女友劉穎癌瘾,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饵溅,經...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡妨退,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碧注。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡嚣伐,死狀恐怖,靈堂內的尸體忽然破棺而出萍丐,到底是詐尸還是另有隱情轩端,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布逝变,位于F島的核電站基茵,受9級特大地震影響,放射性物質發(fā)生泄漏壳影。R本人自食惡果不足惜拱层,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宴咧。 院中可真熱鬧根灯,春花似錦、人聲如沸掺栅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氧卧。三九已至桃笙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沙绝,已是汗流浹背搏明。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留闪檬,地道東北人星著。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像粗悯,于是被迫代替她去往敵國和親强饮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內容