二进制妙用——实现权限控制(JAVA)

前言

本文章是对我之前一篇有关Linux操作系统通过二进制实现用户权限控制原理的java代码实现上扩充。
一是为了巩固知识点,另一方面是想让那一篇的理论知识落到实处。项目源码会在文章中放出。
注意:实现并不是完全按照Linux的模型进行实现,主要是让大家明白二进制的运算在本例的作用。

一、模拟环境及需求

1. 开发环境

  • IDEA 2019.1.4
  • JDK1.8
  • maven
    pom.xml的jar包依赖(没有给出指定版本)
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
    

2. 功能需求

二、实现步骤

1.创建实体

// user实体
@AllArgsConstructor
@Setter
@Getter
public class User {

    private String name;

    /**
     * 默认权限全空
     */
    private Integer auth = 0B000;

    @Override
    public String toString() {
        return name + "拥有" + AuthTools.authTools.pintf(this.auth);
    }
}

// file实体
@AllArgsConstructor
@Setter
@Getter
public class File {

    private String name;

    /**
     * 默认权限全空
     */
    private Integer auth = 0B000;

    @Override
    public String toString() {
        return name+"拥有"+ AuthTools.authTools.pintf(this.auth);
    }
}

// 操作枚举
@AllArgsConstructor
@Getter
public enum Authority {

    /**
     * 读权限 0B100 = 4
     */
    READABLE(0B100, "可读"),
    /**
     * 读权限 0B010 = 2
     */
    WRITABLE(0B010, "可写"),
    /**
     * 读权限 0B001 = 1
     */
    RUNNABLE(0B001, "可运行");


    private Integer value;
    private String name;

}

2.编写逻辑

public class AuthTools {

    public static AuthTools authTools = new AuthTools();

    /**
     * Description:
     * 给user 添加 authoritys 的权限
     *
     * @param user:
     * @param authoritys:
     * @date 2020/12/13 10:11
     **/
    public void addUserAuth(User user, Authority... authoritys) {
        user.setAuth(this.addAuth(user.getAuth(), authoritys));
    }

    /**
     * Description:
     * 给user 删除 authoritys 的权限
     *
     * @param user:
     * @param authoritys:
     * @date 2020/12/13 10:11
     **/
    public void delUserAuth(User user, Authority... authoritys) {
        user.setAuth(this.delAuth(user.getAuth(), authoritys));
    }

    /**
     * Description:
     * 给file 添加 authoritys 的权限
     *
     * @param file:
     * @param authoritys:
     * @date 2020/12/13 10:11
     **/
    public void addFileAuth(File file, Authority... authoritys) {
        file.setAuth(this.addAuth(file.getAuth(), authoritys));
    }

    /**
     * Description:
     * 给file 删除 authoritys 的权限
     *
     * @param file:
     * @param authoritys:
     * @date 2020/12/13 10:11
     **/
    public void delFileAuth(File file, Authority... authoritys) {
        file.setAuth(this.delAuth(file.getAuth(), authoritys));
    }

    /**
     * Description:
     * user对file执行operation操作
     *
     * @param user:
     * @param file:
     * @param operation:
     * @date 2020/12/13 10:11
     **/
    public void execOpera(User user, File file, Authority operation) {
        // 执行操作主程序

        // 执行判断逻辑,只有user和file都有operation的权限的时候才可以执行
        // 比如 user:0B101 file:0B110 operation:0B100 就可以
        // 比如 user:0B001 file:0B110 operation:0B100 不可以 user用户本身就没有读权限
        // 细粒度分析:只要对应位置的二进制都是1就为true,否则为false
        if (this.judgeOperation(user.getAuth(), operation) &&
                this.judgeOperation(file.getAuth(), operation)) {
            System.out.println(user.getName() + "进行" + operation.getName() + "操作成功");
        } else {
            System.out.println(user.getName() + "进行" + operation.getName() + "操作失败");
        }

    }

    private Integer addAuth(Integer integer, Authority... authorities) {
        // 添加权限主程序

        // 获取本次操作的实际权限集合
        Integer mergeAuth = mergeAuth(authorities);
        // 返回二者的合并即可
        return integer | mergeAuth;
    }

    private Integer delAuth(Integer integer, Authority... authorities) {
        // 删除权限主程序

        // 获取本次操作的实际权限集合
        Integer mergeAuth = mergeAuth(authorities);

        // 返回二者的差
        // 例子:user的权限0B110(读写权限)删除0B011(执行与写权限),结果为0B100(读权限)
        // 细粒度分析:0+0= 0,1+0 = 1, 0+1=0,1+1=0 (+代表位运算符号可能是| 也可能是 & 也可能是组合的)
        integer = ~(~integer | mergeAuth);
        return integer;
    }

    /**
     * Description:
     * 用于计算出本次操作总权限是什么
     *
     * @param authorities: 权限集合
     * @return java.lang.Integer: 合并总权限
     * @date 2020/12/13 10:27
     **/
    private Integer mergeAuth(Authority... authorities) {
        Integer auth = 0B000;
        for (Authority authority : authorities) {
            // 二进制位与操作
            // 解析:此处是合并操作,说明是要从 0 -> 1的变化
            // 例子:0B000(空权限) + 0B100(读权限) = 0B100(读权限)
            // 位运算细粒度分析: 0+1=1、0+0=0、1+0=1,1+1=1。(+代表位运算符号可能是| 也可能是 & 也可能是组合的)
            auth = auth | authority.getValue();
        }
        return auth;
    }

    private Boolean judgeOperation(Integer auth, Authority authority) {
        // 细粒度分析 0+0=0, 0+1=0, 1+0=0, 1+1=1
        return (auth & authority.getValue()) == authority.getValue();
    }

    /**
     * Description:
     * 打印interger所拥有的权限
     *
     * @param integer:
     * @return java.lang.String
     * @date 2020/12/13 11:20
     **/
    public String pintf(Integer integer) {
        String str = "【";
        if (this.judgeOperation(integer, Authority.READABLE)) {
            str += Authority.READABLE.getName();
        }
        if (this.judgeOperation(integer, Authority.WRITABLE)) {
            str += "、" + Authority.WRITABLE.getName();
        }
        if (this.judgeOperation(integer, Authority.RUNNABLE)) {
            str += "、" + Authority.RUNNABLE.getName();
        }
        return str + "】";
    }

}

3.编写测试环境

public class Run {

    /*
        默认创建一个文件和两个用户,并且将他们的权限默认为全空
     */

    private File file = new File("系统文件.txt", 0B000);
    private User user1 = new User("用户一", 0B000);
    private User user2 = new User("用户二", 0B000);

    private AuthTools authTools = AuthTools.authTools;

    /**
     * 给user1赋予Read权限
     */
    @Test
    public void addUser1Read() {
        System.out.println("赋值前:" + user1);
        authTools.addUserAuth(user1, Authority.READABLE);
        System.out.println("赋值后:" + user1);

    }

    /**
     * 给user2赋予Write和Runnable权限
     */
    @Test
    public void addUser2Write() {
        System.out.println("赋值前:" + user2);
        authTools.addUserAuth(user2, Authority.WRITABLE, Authority.RUNNABLE);
        System.out.println("赋值后:" + user2);
    }

    /**
     * 删除use1的可运行权限
     */
    @Test
    public void delUser1Write() {
        // 先给予全部权限
        authTools.addUserAuth(user1, Authority.READABLE, Authority.WRITABLE, Authority.RUNNABLE);
        System.out.println("user1:" + user1);
        authTools.delUserAuth(user1, Authority.RUNNABLE);
        System.out.println("删除可运行权限后user1:" + user1);
    }

    /**
     * 测试file的运行的情况
     */
    @Test
    public void execFileByUser() {
        authTools.addFileAuth(file, Authority.RUNNABLE, Authority.READABLE);
        System.out.println("file:" + file);
        authTools.addUserAuth(user1, Authority.READABLE);
        System.out.println("user1:"+user1);
        System.out.println("user2:"+user2);
        authTools.execOpera(user1, file, Authority.READABLE);
        authTools.execOpera(user1, file, Authority.RUNNABLE);
        authTools.execOpera(user2, file, Authority.READABLE);
    }
}

4.代码结构

--com
	-- binary
		--entity
			-- enum Authority (操作枚举)
			-- class File (文件)
			-- class User (用户)
		--test
			-- class Run (测试类)
		--tool
			-- class AuthTools (权限控制类)

总结

通过本次代码测验主要是回归二进制的用法之一。
经过本测验,我们其实在个人的学习上使用这种方式去进行动态的业务属性增添,比如说权限、电影与种类的对应。在经过统一和确定的情况下,这种方式不失为一种快捷方式,还减少了存储空间。
当然其弊端也是很大的,所以大家也可以将此文章作为二进制运算的练习。
通过明白二进制的各种运算,我们的思维会更加贴合计算机本身,更好地巩固我们的内功。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 Java 实现,用于计算给定二进制数据的 CRC 校验码: ```java public class CRC { /** * 计算给定数据的 CRC 校验码 * @param data 输入数据的二进制表示 * @param divisor CRC 校验码生成多项式的二进制表示 * @return 计算出的 CRC 校验码 */ public static String calculateCRC(String data, String divisor) { int dataLen = data.length(); int divLen = divisor.length(); // 将数据和多项式补齐到相同的长度 StringBuilder paddedData = new StringBuilder(data); for (int i = 0; i < divLen - 1; i++) { paddedData.append('0'); } StringBuilder remainder = new StringBuilder(divisor); for (int i = 0; i < divLen - 1; i++) { remainder.append('0'); } // 用长除法计算 CRC 校验码 for (int i = 0; i < dataLen; i++) { char currentChar = paddedData.charAt(i); remainder.append(currentChar); if (remainder.charAt(0) == '1') { remainder = xor(remainder, divisor); } remainder.deleteCharAt(0); } return remainder.toString(); } /** * 对两个二进制串进行异或操作 * @param a 第一个二进制串 * @param b 第二个二进制串 * @return 异或后的结果 */ private static StringBuilder xor(StringBuilder a, String b) { StringBuilder result = new StringBuilder(); int len = Math.min(a.length(), b.length()); for (int i = 0; i < len; i++) { result.append(a.charAt(i) ^ b.charAt(i)); } return result; } public static void main(String[] args) { String data = "1101011011"; String divisor = "10011"; String crc = calculateCRC(data, divisor); System.out.println("CRC 校验码为:" + crc); } } ``` 在 `calculateCRC` 方法中,我们将输入数据和多项式分别补齐到相同的长度,并使用长除法计算 CRC 校验码。`xor` 方法则用于对两个二进制串进行异或操作。 在 `main` 方法中,我们演示了如何使用 `calculateCRC` 方法计算给定数据的 CRC 校验码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值