自定义注解 加密

问题描述

我们的项目更换了测试,变得严格的好多,然后我们加重了安全准入,加上之前写的可能不是那么安全,就被查了,然后我们根据问题提供对应的处理方法。
首先遇到的问题就是,水平越权以及垂直越权,其实就是这么看还是蛮抽象的,其实就是举个例子,我目前做的是一个资产明细(按月)查询功能。这个功能大概是角色分为三层,分别是地市,省份,集团,但是呢我们没有完全利用好系统中的性能,导致出现了这个问题。
介绍一下是什么叫做,水平越权以及垂直越权,水平越权的意思是,以我做的功能举例,例如省的角色,山东省的角色,理论上来说,山东省的角色可以看到整个省的数据,山西省的角色,可以看得到山西省的数据,水平越权的意思,就是说山东省的角色,可以通过直接修改省份id查到山西省的角色能够看的数据。垂直越权的问题,就是说山东济南的角色,地市济南这个角色的用户,可以在资产明细(按月)查询到济南的数据,但是查找不到全省的角色,但是通过修改参数,可以使济南的角色查询到山东省的角色能够看的数据。

查询处理

我们想要处理的就是,首先不同的应用增加不同的应用的密码,这个是为了避免垂直越权,不同的角色权限小角色不能够看到权限大角色的数据,然后同一个功能的话,因为是查询,基本上是列表了,然后使用查询条件的初始化的,实话说这块的没有增加额外的新的代码,就是在查询之前,调用页面初始化,判断入参到底是否和角色相关,我们代码这块主要是处理不同应用的密码。

查询加密
/**
     * 查询资产明细信息 期间查询
     * 地市查询
     * @param body
     * @return
     */
    @PostMapping("/queryViewListPeriodName")
    @ApiOperation(value = "明细信息", notes = "明细信息")
    @OperateLog("资产信息查询-明细信息")
    @RsaDecrypt(msg = "查询失败", isModuleSign = true, moduleName = "AssetDetailsQueryAllRequestBody")
    public JSONObject queryViewListPeriodName(@RequestBody AssetDetailsQueryLocalRequestBody body) {
}

注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Description
 * @Author pgq
 * @DATE 2024/8/23 16:52
 * @Version 1.0
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RsaDecrypt {

    String msg() default "无数据访问权限";

    boolean isDecrypt() default true;

    boolean isModuleSign() default false;

    String encryptProperty() default "id";

    String moduleName() default "";
}

import cn.chinaunicom.core.base.NowUser;
import cn.chinaunicom.core.utils.encode.RSACoderUtil;
import lombok.experimental.UtilityClass;
import org.apache.commons.codec.binary.Base64;

/**
 * @Description
 * @Author pgq
 * @DATE 2024/8/20 16:20
 * @Version 1.0
 */
@UtilityClass
public class RSACheckUtil {
	//私钥
    private static String privateKey = "privateKey";
	//公钥
    private static String publicKey = "publicKey";

    /**
     * 使用公钥对属性进行加密
     *
     * @param id
     * @param nowUser
     * @return
     */
    public static String encryptStr(String id, NowUser nowUser) {
        String str = nowUser.getStaffId() + "," + nowUser.getRoleId() + "," + id;
        byte[] encrypt = RSACoderUtil.encryptByPublicKey(str, publicKey);
        return Base64.encodeBase64String(encrypt);
    }

    /**
     * 使用公钥对属性进行加密
     *
     * @param id
     * @return
     */
    public static String encryptStr(String id){
        byte[] encrypt = RSACoderUtil.encryptByPublicKey(id, publicKey);
        return Base64.encodeBase64String(encrypt);
    }

    /**
     * 获取某加密字符串的内容
     * @param content
     * @return
     */
    public static String decryptStr(String content) {
        String str = "";
        byte[] decrypt = RSACoderUtil.decryptByPrivateKey(Base64.decodeBase64(content), privateKey);
        str = new String(decrypt);
        return str;
    }

    /**
     * 获取某加密字符串的内容
     * @param content
     * @return
     */
    public static String decryptStr(String content,NowUser nowUser) {
        String str = "";
        byte[] decrypt = RSACoderUtil.decryptByPrivateKey(Base64.decodeBase64(content), privateKey);
        str = new String(decrypt);
        String[] result = str.split(",");
        if (!result[0].equalsIgnoreCase(nowUser.getStaffId().toString())) {
            //校验用户 id
            return "";
        }
        if (!result[1].equalsIgnoreCase(nowUser.getRoleId().toString())) {
            //校验角色 id
            return "";
        }
        return result[2];
    }

    /**
     * 对当前登录用户的 staffid 和 roleid 、功能模块 生成数据签名
     * @param nowUser
     * @return
     */
    public static String encryptModuleStr(NowUser nowUser,String moduleName) {
        String str = nowUser.getStaffId() + "," + nowUser.getRoleId()+","+moduleName;
        byte[] encrypt = RSACoderUtil.encryptByPublicKey(str, publicKey);
        return Base64.encodeBase64String(encrypt);
    }

    /**
     * 获取加密字符串中的 id
     *
     * @param encryptStr
     * @return
     */
    public static String getEncryptStrAttr(String encryptStr, NowUser nowUser) {
        byte[] decrypt = RSACoderUtil.decryptByPrivateKey(Base64.decodeBase64(encryptStr), privateKey);
        String descryptStr = new String(decrypt);
        String[] result = descryptStr.split(",");
        if (!result[0].equalsIgnoreCase(nowUser.getStaffId().toString())) {
            //校验用户 id
            return "";
        }
        if (!result[1].equalsIgnoreCase(nowUser.getRoleId().toString())) {
            //校验角色 id
            return "";
        }
        return result[2];
    }

    /**
     * 校验操作数据的是否是当前登录用户
     *
     * @param encryptStr
     * @param nowUser
     * @param id
     * @return
     */
    public static boolean checkIsCurrentUser(String encryptStr, NowUser nowUser, String id) {
        byte[] decrypt = RSACoderUtil.decryptByPrivateKey(Base64.decodeBase64(encryptStr), privateKey);
        String descryptStr = new String(decrypt);
        String[] result = descryptStr.split(",");
        if (!result[0].equalsIgnoreCase(nowUser.getStaffId().toString())) {
            //校验用户 id
            return false;
        }
        if (!result[1].equalsIgnoreCase(nowUser.getRoleId().toString())) {
            //校验角色 id
            return false;
        }
        if (!result[2].equalsIgnoreCase(id)) {
            //校验逻辑主键
            return false;
        }
        return true;
    }

    /**
     * 检查是否是当前用户
     *
     * @param encryptStr
     * @param nowUser
     * @return
     */
    public static boolean checkIsCurrentModule(String encryptStr, NowUser nowUser,String moduleName) {
        byte[] decrypt = RSACoderUtil.decryptByPrivateKey(Base64.decodeBase64(encryptStr), privateKey);
        String descryptStr = new String(decrypt);
        String[] result = descryptStr.split(",");
        if (!result[0].equalsIgnoreCase(nowUser.getStaffId().toString())) {
            //校验用户 id
            return false;
        }
        if (!result[1].equalsIgnoreCase(nowUser.getRoleId().toString())) {
            //校验角色 id
            return false;
        }
        if (!result[2].equalsIgnoreCase(moduleName)) {
            //功能模块
            return false;
        }
        return true;
    }
    // 待阅已阅校验加密值后返回roleid
    public static String checkIsCurrentUserForRoleId(String encryptStr) {
        byte[] decrypt = RSACoderUtil.decryptByPrivateKey(Base64.decodeBase64(encryptStr), privateKey);
        String descryptStr = new String(decrypt);
        String[] result = descryptStr.split(",");
        //角色 id
        String roleId=result[1];
        return roleId;
    }
    public static void main(String[] args) {
        String str = "4";
        str = RSACheckUtil.encryptStr(str);
        System.out.println(str);
    }


}
注意问题

首先保证实体类里面一定要有一个,属性amsRemark,用来存储加密的串,还有就是如果是多个参数的形式,要求是把存放属性amsRemark的实体类放到第一个的参数里面,然后当入参是map的时候是不能够处理的,只能够通过方法处理checkIsCurrentUser()

增删改处理

    @PostMapping("/saveHeaderInfo")
    @ApiOperation(value = "台账-软件新增保存头信息", notes = "台账-软件新增保存头信息")
    @OperateLog("台账-软件新增保存头信息")
    public Result saveHeaderInfo(TzSoftwareAddEntity entity) {
        NowUser nowUser = WebUtil.getNowUser();
        boolean flag = RSACheckUtil.checkIsCurrentUser(entity.getAmsRemark(), nowUser, String.valueOf(entity.getSoftwareAddHeaderId()));
         if(!flag) {
            return failed("新增失败");
          }
        Map<String, Object> m = new HashMap<>(2);
        String billTitle ="";
        try{
            //解码
            billTitle = URLDecoder.decode(entity.getBillTitle(),"UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("exception's message:{}",e.getStackTrace());
        }
        entity.setBillTitle(billTitle);
        final Integer temp = service.saveHeaderInfo(entity);
        m.put("billNumber", entity.getBillNumber());
        return Result.success(m);
    }

类似的代码逻辑

        NowUser nowUser = WebUtil.getNowUser();
        boolean flag = RSACheckUtil.checkIsCurrentUser(entity.getAmsRemark(), nowUser, String.valueOf(entity.getSoftwareAddHeaderId()));
         if(!flag) {
            return failed("新增失败");
          }

这一块的解密的字符

    @Override
    public IPage<TzSoftwareAddEntity> queryViewList(TzSoftwareAddRequestBody requestBody){
        TzSoftwareAddEntity entity = new TzSoftwareAddEntity();
        BeanUtils.copyProperties(requestBody, entity);
        NowUser nowUser = WebUtil.getNowUser();
        //获取当前登录人的staffId和bgId
        entity.nowUserWithAuth(nowUser);

        IPage<TzSoftwareAddEntity> result = mapper.queryViewList(requestBody.getPage(), entity);

        String amsRemark = "";
        for (TzSoftwareAddEntity h : result.getRecords()) {
            amsRemark = RSACheckUtil.encryptStr(h.getSoftwareAddHeaderId() + "", nowUser);
            h.setAmsRemark(amsRemark);
        }
        //加密结束
        return result;
    }

这是对应的加密的代码块,

 amsRemark = RSACheckUtil.encryptStr(h.getSoftwareAddHeaderId() + "", nowUser);
            h.setAmsRemark(amsRemark);

这是具体的加密的方法

前段的加密的方法

/**
 * 校验数据签名
 * @param amsRemark
 * @param id
 * @returns {boolean}
 */
function checkDataSign(amsRemark,id) {
	let flag = false;
	$.ajax({
		async: false,
		type: "POST",
		url: top.server + "/valueSetController/checkDataSign",
		data: {
			amsRemark: amsRemark,
			id: id
		},
		dataType: "json",
		success: function (res) {
			console.log(res);
			if (res.status == 200) {
				flag = true;
			} else {
				alertModel(res.msg);
			}
		}
	});
	return flag;
}

后台的代码

    @PostMapping("/checkDataSign")
    public Result checkData(@RequestParam("amsRemark")String amsRemark, @RequestParam("id")String id) {
        NowUser nowUser = WebUtil.getNowUser();
        boolean flag = RSACheckUtil.checkIsCurrentUser(amsRemark, nowUser, id);
        if(flag){
            return success("成功");
        }
        return Result.failed(500, "无访问权限");
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

又是重名了

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

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

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

打赏作者

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

抵扣说明:

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

余额充值