您的位置:首页 > 编程语言 > C#

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

2014-12-17 15:36 519 查看
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));
        }
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: