使用SpringAOP进行签名校验

使用SpringAOP进行签名校验


前言

最近接触到尚医通这个项目,其实这个项目确实有一些让人诟病的部分,所以我在看课程学习项目的同时也对自己感觉可以优化的部分进行优化,后面也会出一些关于这个项目的问题解决以及自己的解决方案,本篇博客仅是对签名校验的实现进行自己的思路重构,欢迎读者指正~

问题提出

原本的项目代码真的可以说是很冗余了,在每一个接口方法前面都需要经过签名校验,即业务逻辑代码200行,校验就单独做了100行,那么如何避免这种尴尬的情况呢?我不禁想到AOP(面向切面编程)就可以解决此类问题

原代码

@RestController
@RequestMapping("/api/hosp")
public class ApiController {
    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private HospitalSetService hospitalSetService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private ScheduleService scheduleService;

    //上传医院接口
    @PostMapping("saveHospital")
    public Result saveHosp(HttpServletRequest request){
        //获取医院传递过来的信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        //为避免后面遍历,将map中的String[]转换成Object
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
        //核验签名是否一致
            //1.获取医院系统传递过来的签名
        String hospSign = (String) parampMap.get("sign");
            //2.根据传递过来的医院编码,查询数据库,查询签名
        String hoscode = (String) parampMap.get("hoscode");
        String signKey = hospitalSetService.getSignKey(hoscode);
            //3.把查询出来的签名进行MD5加密
        String signKeyMD5 = MD5.encrypt(signKey);
            //4.判断签名是否一致
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }

        //图片数据采取base64工具类传输,在传输过程中“+”转换为了“ ”,因此我们要转换回来
        String logoData = (String) parampMap.get("logoData");
        logoData = logoData.replace(" ","+");
        parampMap.put("logoData",logoData);

        //调用service的方法
        hospitalService.save(parampMap);
        return Result.ok();
    }

    //查询医院接口
    @PostMapping("hospital/show")
    public Result getHospital(HttpServletRequest request){
        //获取医院传递过来的信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        //为避免后面遍历,将map中的String[]转换成Object
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
        //获取传递过来的医院编号
        String hoscode = (String) parampMap.get("hoscode");
        //签名校验
        String hospSign = (String) parampMap.get("sign");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }
        //调用service方法
        Hospital hospital = hospitalService.getByHoscode(hoscode);
        return Result.ok(hospital);
    }

    //上传科室接口
    @PostMapping("saveDepartment")
    public Result saveDepartment(HttpServletRequest request){
        //获取传递过来的科室信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
        //核验签名是否一致
        String hospSign = (String) parampMap.get("sign");
        String hoscode = (String) parampMap.get("hoscode");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }
        //调用service方法
        departmentService.save(parampMap);
        return Result.ok();
    }

    //科室查询接口
    @PostMapping("department/list")
    public Result findDepartment(HttpServletRequest request){
        //获取传递过来的科室信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
        //医院编号
        String hoscode = (String) parampMap.get("hoscode");
        //当前页
        int page = Integer.parseInt((String) parampMap.get("page"));
        if(StringUtils.isEmpty(page)){
            page = 1;
        }
        //每页显示记录数
        int limit = Integer.parseInt((String) parampMap.get("limit"));
        if(StringUtils.isEmpty(limit)){
            limit = 1;
        }
        //签名校验
        String hospSign = (String) parampMap.get("sign");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }
        //调用service查询
            //查询条件的值封装到departmentQueryVo中
        DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
        departmentQueryVo.setHoscode(hoscode);
        Page<Department> pageModel = departmentService.finPageDepartment(page,limit,departmentQueryVo);
        return Result.ok(pageModel);
    }

    //删除科室接口
    @PostMapping("department/remove")
    public Result removeDepartment(HttpServletRequest request){
        //获取传递过来的科室信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
        //获取医院编号和科室编号
        String hoscode = (String) parampMap.get("hoscode");
        String depcode = (String) parampMap.get("depcode");
        //签名校验
        String hospSign = (String) parampMap.get("sign");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }
        departmentService.remove(hoscode,depcode);
        return Result.ok();
    }

    //上传排班
    @PostMapping("saveSchedule")
    public Result saveSchedule(HttpServletRequest request){
        //获取传递过来的科室信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);

        //签名校验
        String hospSign = (String) parampMap.get("sign");
        String hoscode = (String) parampMap.get("hoscode");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }

        //调用service方法
        scheduleService.save(parampMap);
        return Result.ok();
    }

    //查询排班
    @PostMapping("schedule/list")
    public Result findSchedule(HttpServletRequest request) {
        //获取传递过来的科室信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
        //医院编号
        String hoscode = (String) parampMap.get("hoscode");
        //科室编号
        String depcode = (String) parampMap.get("depcode");

        //当前页
        int page = Integer.parseInt((String) parampMap.get("page"));
        if (StringUtils.isEmpty(page)) {
            page = 1;
        }
        //每页显示记录数
        int limit = Integer.parseInt((String) parampMap.get("limit"));
        if (StringUtils.isEmpty(limit)) {
            limit = 1;
        }
        //签名校验
        String hospSign = (String) parampMap.get("sign");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if (!hospSign.equals(signKeyMD5)) {
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }
        //调用service查询
            //查询条件的值封装到departmentQueryVo中
        ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
        scheduleQueryVo.setHoscode(hoscode);
        scheduleQueryVo.setDepcode(depcode);
        Page<Schedule> pageModel = scheduleService.finPageSchedule(page, limit, scheduleQueryVo);
        return Result.ok(pageModel);
    }

    //删除排班
    @PostMapping("schedule/remove")
    public Result remove(HttpServletRequest request){
        //获取传递过来的科室信息
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
        //获取医院编号和排班编号
        String hoscode = (String) parampMap.get("hoscode");
        String hosScheduleId = (String) parampMap.get("hosScheduleId");
        //签名校验
        String hospSign = (String) parampMap.get("sign");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }
        scheduleService.remove(hoscode,hosScheduleId);
        return Result.ok();
    }
}

具体实现

通过看上面的代码可以说是非常冗余了,于是我通过注解切面的形式做了一个小优化

实现步骤也非常简单:

  1. 定义签名校验注解
  2. 定义切面,并且做切入点的系统服务
  3. 在需要校验的方法上添加注解即可
  • 自定义注解
//自定义注解:签名校验
@Target({ElementType.PARAMETER,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)     //运行时生效
public @interface SignatureValidation {
}
  • 定义切面
@Aspect
@Component
public class SignatureValidation {
    @Autowired
    private HospitalSetService hospitalSetService;

    //切入点
    @Pointcut("@annotation(com.hang.aspectj.annotation.SignatureValidation)")
    public void signPointcut(){

    }

    //签名校验
    @Before("signPointcut()")
    public void doBefore(){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();

        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());

        //必须参数校验
        String hoscode = (String) paramMap.get("hoscode");
        if(StringUtils.isEmpty(hoscode)) {
            throw new YyghException(ResultCodeEnum.PARAM_ERROR);
        }

        //进行签名校验
        String signKey = hospitalSetService.getSignKey(hoscode);

        //对数据库中取出的签名进行加密
        String signKeyMd5 = MD5.encrypt(signKey);

        String hosSign=(String) paramMap.get("sign");

        //判断签名是否一致
        if(!hosSign.equals(signKeyMd5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }
    }
}
  • 添加注解实现(实现后的代码)
@RestController
@RequestMapping("/api/hosp")
public class ApiController {
    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private HospitalSetService hospitalSetService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private ScheduleService scheduleService;

    //上传医院接口
    @PostMapping("saveHospital")
    public Result saveHospital(HttpServletRequest request){
        //首先获取传递过来的信息
        //将传递的String[]信息转为Object
        Map<String, Object> parameterMap = HttpRequestHelper.switchMap(request.getParameterMap());

        //图片数据采取base64工具类传输,在传输过程中"+"转换为了" ",因此我们要转换回来
        String logoData = (String) parameterMap.get("logoData");
        logoData = logoData.replace(" ","+");
        parameterMap.put("logoData",logoData);

        //调用service方法进行保存
        hospitalService.save(parameterMap);

        //返回结果
        return Result.ok();
    }

    @PostMapping("hospital/show")
    @SignatureValidation
    public Result hospital(HttpServletRequest request) {
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
        //将request过来的参数进行解析获取
        return Result.ok(hospitalService.getByHoscode((String)paramMap.get("hoscode")));
    }


    //上传科室接口
    @PostMapping("saveDepartment")
    @SignatureValidation
    public Result saveDepartment(HttpServletRequest request) {
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
        departmentService.save(paramMap);
        return Result.ok();
    }


    //查询科室接口
    @PostMapping("department/list")
    @SignatureValidation
    public Result department(HttpServletRequest request) {
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
        //必须参数校验
        String hoscode = (String)paramMap.get("hoscode");
        //非必填
        String depcode = (String)paramMap.get("depcode");
        int page = StringUtils.isEmpty(paramMap.get("page")) ? 1 : Integer.parseInt((String)paramMap.get("page"));
        int limit = StringUtils.isEmpty(paramMap.get("limit")) ? 10 : Integer.parseInt((String)paramMap.get("limit"));

        DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
        departmentQueryVo.setHoscode(hoscode);
        departmentQueryVo.setDepcode(depcode);

        Page<Department> pageModel = departmentService.selectPage(page, limit, departmentQueryVo);
        return Result.ok(pageModel);
    }


    //删除科室接口
    @PostMapping("department/remove")
    @SignatureValidation
    public Result removeDepartment(HttpServletRequest request) {
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
        //必须参数校验
        String hoscode = (String) paramMap.get("hoscode");
        //必填
        String depcode = (String) paramMap.get("depcode");
        departmentService.remove(hoscode, depcode);
        return Result.ok();
    }

    //上传排班信息
    @PostMapping("saveSchedule")
    @SignatureValidation
    public Result saveSchedule(HttpServletRequest request) {
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
        scheduleService.save(paramMap);
        return Result.ok();
    }

    //查询排版信息接口
    @PostMapping("schedule/list")
    @SignatureValidation
    public Result getSchedules(HttpServletRequest request){
        //查询参数
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
        String hoscode =  (String) paramMap.get("hoscode");
        //分页查询数据
        String depcode=(String) paramMap.get("depcode");

        //非必填数据
        int page = StringUtils.isEmpty(paramMap.get("page")) ? 1 : Integer.parseInt((String)paramMap.get("page"));
        int limit = StringUtils.isEmpty(paramMap.get("limit")) ? 10 : Integer.parseInt((String)paramMap.get("limit"));

        ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
        scheduleQueryVo.setHoscode(hoscode);
        scheduleQueryVo.setDepcode(depcode);

        Page<Schedule> pageModel = scheduleService.selectPage(page, limit, scheduleQueryVo);
        return Result.ok(pageModel);
    }

    //删除排班接口:由于排班号并不唯一,因此不需要进行额外的唯一校验,因此仅需要进行签名校验
    @PostMapping("schedule/remove")
    public Result removeSchedule(HttpServletRequest request) {
        Map<String, Object> paramMap = HttpRequestHelper.switchMap(request.getParameterMap());
        String hoscode = (String)paramMap.get("hoscode");
        //必填
        String hosScheduleId = (String)paramMap.get("hosScheduleId");

        //签名校验
        String hospSign = (String) paramMap.get("sign");
        String signKey = hospitalSetService.getSignKey(hoscode);
        String signKeyMD5 = MD5.encrypt(signKey);
        if(!hospSign.equals(signKeyMD5)){
            throw new YyghException(ResultCodeEnum.SIGN_ERROR);
        }

        scheduleService.remove(hoscode, hosScheduleId);
        return Result.ok();
    }
}

代码整体减少了50~100行,而且逻辑也清晰了许多

总结

在学习的过程中不断总结,不断进步,学会将知识进行活学活用,才能立足~

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Astronaut_001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值