C# 使用二进制 逻辑(与、或、非)位移运算 控制系统权限

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Grass.Authorize
{
    /// <summary>
    /// 二进制授权帮助类,最多支持 62 种不同权限,鉴权值最大为2的62次方(即:4611686018427387904)
    /// </summary>
    public class BinAuth
    {
        /// <summary>
        /// 验证非负正整数是否为2的幂级
        /// </summary>
        /// <remarks></remarks>
        /// <param name="n"></param>
        /// <returns></returns>
        public static bool IsBinPower(long n)
        {
            /*             
        判断是2的幂,1个数乘以2就是将该数左移1位,而2的0次幂为1, 
         所以2的n次幂(就是2的0次幂n次乘以2)就是将1左移n位,
          这样我们知道如果一个数n是2的幂,则其只有首位为1,
         其后若干个0,必然有n & (n - 1)为0。(在求1个数的二进制表示中1的个数的时候说过
         ,n&(n-1)去掉n的最后一个1)。因此,判断一个数n是否为2的幂,只需要判断n&(n-1)是否为0即可。
             */
            return (n & (n - 1)) == 0;
        }
        /// <summary>
        /// 获取2 的 x 次方值
        /// </summary>
        /// <param name="x">x 次方值</param>
        /// <returns></returns>
        public static long GetBinPower(int x)
        {
            return (long)System.Math.Pow(2, x);
        }
        /// <summary>
        /// 将数值转为等值2进制数
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static string GetBin(long n)
        {
            return Convert.ToString(n, 2);
        }

        /// <summary>
        /// 生成鉴权码
        /// </summary>
        /// <param name="arr">权限值(2的幂级)</param>
        /// <remarks>每个鉴权值执行或操作(code = code | n)</remarks>
        /// <returns></returns>
        public static long GenAuthCode(params long[] arr)
        {
            if (arr == null)
                throw new Exception("权限值数组不允许为空,Grass.BinAuth.GenAuthCode()");
            long code = 0;
            arr.ToList().ForEach(x =>
            {
                if (!IsBinPower(x))
                    throw new Exception(string.Format("值 {0} 为无效的鉴权码不是2的幂级", x));
                if (x< 0 ||x > 4611686018427387904)
                    throw new Exception(string.Format("鉴权值 {0} 应大于 0 小于 4611686018427387904", x));
                code = code | x;
            });
            return code;
        }
        /// <summary>
        /// 添加权限
        /// </summary>
        /// <param name="authCode">鉴权码</param>
        /// <param name="auth">权限值(2的幂级)</param>
        /// <remarks>code = authCode | auth</remarks>
        /// <returns></returns>
        public static long AddAuth(long authCode,long auth)
        {
            if (!IsBinPower(auth))
                throw new Exception(string.Format("值 {0} 为无效的鉴权码不是2的幂级", auth));

            if (auth < 0 || auth > 4611686018427387904)
                throw new Exception(string.Format("鉴权值 {0} 应大于 0 小于 4611686018427387904", auth));

            long code = authCode | auth;
            return code;
        }
        /// <summary>
        /// 移除权限
        /// </summary>
        /// <param name="authCode">鉴权码</param>
        /// <param name="auth">权限值(2的幂级)</param>
        /// <remarks>code = authCode & (~auth)</remarks>
        /// <returns></returns>
        public static long RemoveAuth(long authCode, long auth)
        {
            if (!IsBinPower(auth))
                throw new Exception(string.Format("值 {0} 为无效的鉴权码不是2的幂级", auth));

            if (auth < 0 || auth > 4611686018427387904)
                throw new Exception(string.Format("鉴权值 {0} 应大于 0 小于 4611686018427387904", auth));

            long code = authCode & (~auth);
            return code;
        }

        /// <summary>
        /// 验证权限
        /// </summary>
        /// <param name="authCode">鉴权码</param>
        /// <param name="auth">权限值(2的幂级)</param>
        /// <remarks>auth == (authCode & auth)</remarks>
        /// <returns></returns>
        public static bool IsHasAuth(long authCode, long auth)
        {
            if (!IsBinPower(auth))
                throw new Exception(string.Format("值 {0} 为无效的鉴权码不是2的幂级", auth));

            if (authCode <= 0 || auth<=0)
                return false;

            return auth == (authCode & auth);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Grass.Authorize;
using Microsoft.VisualStudio.TestTools.UnitTesting;


namespace TestGrass
{
    [TestClass]
    public class TestBinAuth
    {
        /// <summary>
        /// 验证非负正整数是否为 2 的幂级
        /// </summary>
        /// <remarks>
        /// 判断是2的幂,1个数乘以2就是将该数左移1位,而2的0次幂为1, 所以2的n次幂(就是2的0次幂n次乘以2)就是将1左移n位, 这样我们知道如果一个数n是2的幂,则其只有首位为1,其后若干个0,必然有n & (n - 1)为0。(在求1个数的二进制表示中1的个数的时候说过,n&(n-1)去掉n的最后一个1)。因此,判断一个数n是否为2的幂,只需要判断n&(n-1)是否为0即可。
        /// </remarks>
        /// <returns></returns>
        [TestMethod]
        public void TestIsBinPower()
        {
            string str = "";
            for (int i = 0; i < 64; i++)
            {
                long n = BinAuth.GetBinPower(i);
                str = BinAuth.GetBin(n);
                if (!BinAuth.IsBinPower(n))
                    Assert.IsTrue(false);
            }
            Assert.IsTrue(true);
        }


        /// <summary>
        /// 获取2 的 x 次方值
        /// </summary>
        /// <returns></returns>
        [TestMethod]
        public void TestGetBinPower()
        {
            long n = (long)Math.Pow(2, 50);
            string ns = BinAuth.GetBin(n);


            long m = BinAuth.GetBinPower(50);
            string ms = BinAuth.GetBin(m);
            Assert.IsTrue(n == m);
        }
        /// <summary>
        /// 将数值转为等值2进制数
        /// </summary>
        /// <returns></returns>
        [TestMethod]
        public void TestGetBin()
        {
            long n = (long)Math.Pow(2, 50);
            string s1 = BinAuth.GetBin(n);
            string s2 = Convert.ToString(n, 2);
            Assert.IsTrue(s1.Equals(s2));
        }


        /// <summary>
        /// 生成鉴权码
        /// </summary>
        /// <param name="arr">权限值(2的幂级)</param>
        /// <remarks>每个鉴权值执行或操作</remarks>
        /// <returns></returns>
        [TestMethod]
        public void TestGenAuthCode()
        {
            long authCode = 0;
            string binStr = "";
            List<long> codeList = new List<long>();
            for (int i = 1; i <= 62; i++)
            {
                codeList.Add((long)Math.Pow(2, i));
            }
            authCode = BinAuth.GenAuthCode(codeList.ToArray());
            binStr = BinAuth.GetBin(authCode); ;
            Assert.IsTrue(true);
        }
        /// <summary>
        /// 添加权限
        /// </summary>
        /// <remarks>code = authCode | auth</remarks>
        /// <returns></returns>
        [TestMethod]
        public void TestAddAuth()
        {
            long authCode = 0;
            string binStr = "";
            for (int i = 1; i <= 62; i++)
            {
                long x = BinAuth.GetBinPower(i);
                authCode = BinAuth.AddAuth(authCode, x);
                binStr = BinAuth.GetBin(authCode);
            }
            binStr = BinAuth.GetBin(authCode);
            Assert.IsTrue(true);
        }
        /// <summary>
        /// 移除权限
        /// </summary>
        /// <remarks>code = authCode & (~auth)</remarks>
        /// <returns></returns>
        [TestMethod]
        public void TestRemoveAuth()
        {
            long authCode = 9223372036854775806;//表示最大权限值
            string binStr = "";
            for (int i = 1; i <= 62; i++)
            {
                long x = BinAuth.GetBinPower(i);
                authCode = BinAuth.RemoveAuth(authCode, x);
                binStr = BinAuth.GetBin(authCode);
            }
            binStr = BinAuth.GetBin(authCode);
            Assert.IsTrue(true);


        }


        /// <summary>
        /// 验证权限
        /// </summary>
        /// <returns></returns>
        [TestMethod]
        public void TestIsHasAuth()
        {
            long[] arr = {1, 2, 4, 8, 16, 32, 64};
            long authCode = BinAuth.GenAuthCode(arr);
            Assert.IsTrue(BinAuth.IsHasAuth(authCode, 1));
            Assert.IsTrue(BinAuth.IsHasAuth(authCode, 2));
            Assert.IsTrue(BinAuth.IsHasAuth(authCode, 4));
            Assert.IsTrue(BinAuth.IsHasAuth(authCode, 8));
            Assert.IsTrue(BinAuth.IsHasAuth(authCode, 16));
            Assert.IsTrue(BinAuth.IsHasAuth(authCode, 32));
            Assert.IsTrue(BinAuth.IsHasAuth(authCode, 64));




            Assert.IsFalse(BinAuth.IsHasAuth(-1, 0));
            Assert.IsFalse(BinAuth.IsHasAuth(0, 0));
            Assert.IsFalse(BinAuth.IsHasAuth(authCode, 128));
            Assert.IsFalse(BinAuth.IsHasAuth(authCode, 256));
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值