【发布时间】:2015-03-01 07:07:31
【问题描述】:
我正在尝试为特权/权限编写一个类。
我正在尝试在 C# 中使用二进制基本权限系统。
我在我认为它应该工作的地方得到了它。但是,它没有按预期工作。
之后,我逐步检查了我的代码,我可以在名为 _mapPermissions 的方法中看到一个问题,if (dic.ContainsKey(vv)) 行每次都返回 false。
键是具有 2 个值的类的实例(即secionName、KeyIndex)
这是我的整个班级
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using MySql.Data.MySqlClient;
namespace POS
{
class Roles
{
private Dictionary<PermissionsKey, int> systemPermissions = new Dictionary<PermissionsKey, int>();
private Dictionary<PermissionsKey, int> userPermissions = new Dictionary<PermissionsKey, int>();
public Roles()
{
this._getSystemPrivleges();
this._getUserPrivleges();
this._display(systemPermissions);
this._display(userPermissions);
}
public bool hasAccess(string sectionName, string[] keys)
{
if ( this.systemPermissions.Count == 0
|| this.userPermissions.Count == 0
|| keys.Count() == 0
|| String.IsNullOrEmpty(sectionName)
)
{
return false;
}
int systemReq = this._mapPermissions(sectionName, keys, systemPermissions); ;
int userPerm = this._mapPermissions(sectionName, keys, userPermissions);
int check = systemReq & userPerm;
Common.Alert("System Value" + systemReq + Environment.NewLine +"User Value " + userPerm + Environment.NewLine + "AND Results " + check);
if (check == 0)
{
return false;
}
return true;
}
private int _mapPermissions(string secName, string[] keys, Dictionary<PermissionsKey, int> dic)
{
int newKey = 0;
var vv = new PermissionsKey();
foreach (string k in keys)
{
vv.sectionName = secName;
vv.KeyIndex = k;
if (dic.ContainsKey(vv))
{
newKey |= dic[vv] ;
}
}
return newKey;
}
private void _getSystemPrivleges()
{
var db = new dbConnetion();
string sql = " SELECT SQL_CACHE "
+ " KeyIndex, Value, sectionName "
+ " FROM role_keys "
+ " WHERE status = 'active' ";
foreach (var i in db.getData(sql, null, r => new SystemPermissions()
{
pIndex = r["KeyIndex"].ToString()
, pSec = r["sectionName"].ToString()
, pValue = r["Value"].ToString()
}
)
)
{
var vv = new PermissionsKey();
vv.sectionName = i.pSec;
vv.KeyIndex = i.pIndex;
systemPermissions.Add(vv, Convert.ToInt32(i.pValue));
}
}
private void _getUserPrivleges()
{
var db = new dbConnetion();
string sql = " SELECT SQL_CACHE k.sectionName, k.KeyIndex, k.value "
+" FROM users AS su "
+" INNER JOIN role_relation AS r ON r.roleID = su.roleID "
+" INNER JOIN role_keys AS k ON k.KeyID = r.KeyID "
+" WHERE su.status = 'active' AND su.userID = @userid ";
var parms = new List<MySqlParameter>();
parms.Add(new MySqlParameter("@userid", UserInfo.UserID));
foreach (var i in db.getData(sql, parms , r => new SystemPermissions()
{
pIndex = r["KeyIndex"].ToString()
, pSec = r["sectionName"].ToString()
, pValue = r["Value"].ToString()
}
)
)
{
var vv = new PermissionsKey();
vv.sectionName = i.pSec;
vv.KeyIndex = i.pIndex;
userPermissions.Add(vv, Convert.ToInt32(i.pValue));
}
}
private void _display(Dictionary<PermissionsKey, int> dic)
{
string str = "";
foreach (KeyValuePair<PermissionsKey, int> d in dic)
{
var vv = new PermissionsKey();
var c = d.Key;
str += c.sectionName + "_" + c.KeyIndex + " => " + d.Value.ToString() + Environment.NewLine;
}
Common.Alert(str);
}
private int _BinToInt(string str)
{
Regex binary = new Regex("^[01]{1,32}$", RegexOptions.Compiled);
int val = -1;
if (binary.IsMatch(str))
{
val = Convert.ToInt32(str, 2);
}
return val;
}
private string _IntToBin(int number)
{
return Convert.ToString(number, 2);
}
}
class SystemPermissions{
public string pIndex;
public string pSec;
public string pValue;
}
class PermissionsKey
{
public string sectionName;
public string KeyIndex;
}
}
我就是这样使用这个类的
var role = new Roles();
string[] aa = { "view", "use" };
if (role.hasAccess("system", aa))
{
Common.Alert("Welcome");
}
else
{
Common.Alert("NOP!");
}
注意Common.Alert() 方法只是显示一条消息(即MessageBox)
以上代码运行时显示如下
1) systemPermissions 字典的内容按以下顺序排列 PermissionsKey.sectionName_PermissionsKey.KeyIndex => 值 (ie. 1 , 2, 4, 8, 16, 32, 64 .....)
system_do = > 1
系统使用 => 2
系统视图 => 4
测试使用 => 1
test_view => 2
2)usePermissions字典的内容
system_do = > 1
test_use => 1
问题是systemReq 和userPerm 这两个变量每次都返回0。我不知道为什么
int systemReq = this._mapPermissions(sectionName, keys, systemPermissions); ;
int userPerm = this._mapPermissions(sectionName, keys, userPermissions);
【问题讨论】:
-
你可能需要在你的 PermissionKey 类型上定义 gethashcode 和 equals,否则字典不知道什么时候两个东西是等价的。
-
你能告诉我你所说的 gethashcode 是什么意思吗?
-
散列基本上是通过将项目分割成桶来工作的。例如,如果您有 100 个项目和 10 个存储桶,那么您只需确定项目属于哪个存储桶(通过使用 GetHashCode),然后在该存储桶中进行搜索。这将搜索从 100 项减少到仅搜索 10 项(这就是字典如此快的原因)。也就是说,要让它知道某物进入哪个存储桶,您需要定义一个散列函数。
-
C#/Java 中的散列函数基本上通过重新调整数字 (
Int32) 来工作。数字是多少并不重要,只要您始终为相同的“类型”获得相同的数字(无论这在您的实现中意味着什么)。所以两个相等的东西也应该有相同的哈希码(这样它们就可以进入同一个桶——字典只会测试同一个桶中两个项目的相等性!)。例如,一个简单的解决方案就是返回(KeyIndex+sectionName).getHashCode()。这是原始的,但我认为它会在你的场景中工作。 -
提示:考虑在 Google/Bing 上搜索您的问题的标题。 (所以搜索引擎有时不会带来最佳匹配)以验证您是否真的是第一个遇到问题的人......我怀疑有些人已经尝试使用自定义对象作为字典中的键,并且确实根据这个搜索@ 987654321@有些人已经遇到过类似的问题。
标签: c# authentication dictionary permissions user-permissions