防止跨站脚本攻击--不同的系统之间为了访问安全可以验证key,和sign

 

key和sign的校验可以采用类似日志的切面方式(一个切点可以织入多种通知,例如即织入日志通知,又织入key校验通知)

切面基本思路是定义切点(截点),在切点(截点)处织入通知(前置通知,环绕通知,后置通知)

 

请求系统在业务数据之后加上key,sign,到达目标系统之后,目标系统用切面拦截(前置通知),校验key(和本地存的是否一致)和sign(加密方式,参数是否一致),通过之后remove掉key,sign留下业务数据(参数操作基于对象引用

,所以后传有效)自动从截点方法继续执行,不通过抛异常(环绕通知需要在通知处手动调用截点方法)

 

 

前置通知://不需要手动调用截点,自动运行

 

截点:

    /**

     * 所有controller

     */

    @Pointcut("execution(* com.houbank.bank.*.controller..*.*(..))")

    private void allController() {

    }

 

 

通知

 

  @Before(value = "allController()" +

            "&&!callbackController()" +

            "&&!taskController()" +

            "&&!webController()" +

            "&&!baseController()" + 

            "&&!nosignController()")

    public void req(JoinPoint joinPoint) throws Throwable {

    if(joinPoint.getArgs().length > 0){

    Object jsonObject = (Object) joinPoint.getArgs()[0];

            Map bodyMap = MapUtil.beansToMap(jsonObject);

            String key = (String) bodyMap.get("key");

            String sign = (String) bodyMap.get("sign");

            if (StringUtils.isBlank(key) || StringUtils.isBlank(sign)) {

                throw new ParamException("请检查参数key,sign");

            }

            String secret = null;

            String[] split = appKey.split(";");

            for (String str : split) {

                if (str.split(",")[0].trim().equals(key)) {

                    secret = str.split(",")[1].trim();

                    if (logger.isDebugEnabled()) {

                        logger.debug("对方key=" + key + ",获取的秘钥secret=" + secret);

                    }

                }

            }

            if (StringUtils.isBlank(secret)) {

                logger.error("秘钥为空,对方key=" + key + ",我方appKey集合=" + appKey);

                throw new ParamException("key不匹配");

            } else {

                bodyMap.remove("sign");

                bodyMap.remove("key");

                if (!SignUtils.signOuter(bodyMap, secret,sign)) {

                    throw new ParamException(CodeEnum.CODE_9998.getMsg());

                }

            }

    }

    }

 

 

 

环绕通知://环绕通知需要手动调用截点

 

 

 

 

 /**

     * 执行controller时调用

     */

    @Pointcut("execution(* com.houbank.bank.*.controller..*.*(..))")

    private void executeController() {

    }

 

 

    @Around("executeController()")

    public Object notifyCreditAccountStatusFail(ProceedingJoinPoint joinPoint) throws Throwable {

    if(joinPoint.getArgs().length > 0){

    Object jsonObject = (Object) joinPoint.getArgs()[0];

            Map map = MapUtil.beansToMap(jsonObject);

            String applyNo = null;

            if (!map.isEmpty()) {

                applyNo = (String) map.get("applyNo");

                MDC.put(ApiLogConst.REQUESTIP, request.getServerName());

                MDC.put(ApiLogConst.REQUESTPORT, String.valueOf(request.getServerPort()));

                MDC.put(ApiLogConst.REQUESTURI, request.getRequestURI());

                MDC.put(ApiLogConst.REQUESTTYPE, request.getMethod());

                MDC.put(ApiLogConst.APPLYNO, applyNo);

            }

            LogFactory.setTxId(String.format("applyNo:%s",applyNo));

    }

        try {

            Object obj = super.logMethodArgsReturn(joinPoint);   //环绕通知需要手动调用截点

            return obj;

        } finally {

            MDC.remove(ApiLogConst.REQUESTIP);

            MDC.remove(ApiLogConst.REQUESTPORT);

            MDC.remove(ApiLogConst.REQUESTURI);

            MDC.remove(ApiLogConst.REQUESTTYPE);

            MDC.remove(ApiLogConst.APPLYNO);

            LogFactory.destory();

        }

    }

 

 

 

 

 

 

 

 

 

 

 

 

发起方:

    @Test

    public void updateStatus() throws Exception {

        String url="http://localhost:8080/bank-gateway/approval/update";

        JSONObject jsonObj = new JSONObject();

        jsonObj.put("id", "1");

        jsonObj.put("status", "0");

        Map map=JSONObject.parseObject(jsonObj.toJSONString());

        jsonObj.put("key", "bankApi");  //相当于盐值

        jsonObj.put("sign",SignUtils.signOuter(map,"a6e237fc-5a53-4e29-a961-813de44a9929"));  //相当于加密密码

        String resultStr = HttpClientUtil.httpJsonPost(url, jsonObj.toString());

        System.out.println(resultStr);

    }

 

 

 

 

接收方:(用上面的前置通知对比key,sign)

 

 /**

     * 更新

     * @param

     * @return

     */

    @RequestMapping("update")

    public ApiResponse update(@Valid @RequestBody ApprovalRule appRule, Errors errors) throws Exception {

        try {

            if (approvalRuleMapper.updateByPrimaryKeySelective(appRule)<1){

                LOGGER.error(CodeEnum.CODE_9997.getMsg()+"参数:"+appRule.toString());

                return ApiResponse.error(CodeEnum.CODE_0001);

            }

            return ApiResponse.error(CodeEnum.CODE_0000);

        } catch (Exception e) {

            LOGGER.error("更新rule异常,参数:"+appRule.toString());

            return ApiResponse.error(CodeEnum.CODE_9999);

        }

    }

 

 

 

你可能感兴趣的:(其他)