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

来源:互联网 发布:java去掉字母和数字 编辑:程序博客网 时间:2024/06/05 17:58
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));        }    }}


0 0