|
|
Posted on 2007-05-31 21:55 江南白衣 阅读(14749) 评论(15) 编辑 收藏 网摘 所属分类: Enterprise Library
大家都知道,微软企业库中的Security Application Block是把权限规则写在配置文件中的(app.config,web.config),并没有提供存在数据库的实现形式。我去年就向企业库项目组的人建议在SAB中加入这一实现形式,遗憾的是,直到现在的3.1版本,还是没有实现这一功能。 还好GotDotNet上有人提供了这一功能的扩展:Database Rules Provider ,不过这个扩展没有权限操作的功能(添加,删除,修改权限。。。),不方便大家的日常使用,所以我就对其作了一些修改,加入了权限操作功能。现在放出来与大家共享:) 项目下载:Database Authorization Provider.rar DbRulesManager.cs:
1 using System; 2 using System.Data; 3 using System.Data.Common; 4 using System.Data.SqlClient; 5 using System.Configuration; 6 using System.Collections.Generic; 7 using System.Security.Principal; 8 using System.Web.Security; 9 10 using Microsoft.Practices.ObjectBuilder; 11 using Microsoft.Practices.EnterpriseLibrary.Security; 12 //using Microsoft.Practices.EnterpriseLibrary.Security.Authorization; 13 using Microsoft.Practices.EnterpriseLibrary.Security.Configuration; 14 using Microsoft.Practices.EnterpriseLibrary.Data; 15 using Microsoft.Practices.EnterpriseLibrary.Configuration; 16 using System.Configuration.Provider; 17 18 namespace Kreeg.EnterpriseLibrary.Security.Database.Authorization 19  { 20 /**//// <summary> 21 /// Class for retrieving rules from the database 22 /// </summary> 23 public class DbRulesManager 24 { 25 26 private Microsoft.Practices.EnterpriseLibrary.Data.Database dbRules = null; 27 /**//// <summary> 28 /// Creates a Database Rules Manager instance 29 /// </summary> 30 /// <param name="databaseService">The Database Instance to use to query the data(要查询数据的数据库实例)</param> 31 /// <param name="config">The configuration context</param> 32 public DbRulesManager(string databaseService) 33 { 34 //DatabaseProviderFactory factory = new DatabaseProviderFactory(config); 35 dbRules = DatabaseFactory.CreateDatabase(databaseService); 36 } 37 38 39 /**//// <summary> 40 /// Retrieves a rule from the database 41 /// </summary> 42 /// <param name="Name">The name of the rule</param> 43 /// <returns>An AuthorizationRuleData object</returns> 44 public AuthorizationRuleData GetRule(string name) 45 { 46 47 AuthorizationRuleData rule = null; 48 49 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.GetRuleByName"); 50 dbRules.AddInParameter(cmd, "Name", DbType.String, name); 51 52 using(IDataReader reader = dbRules.ExecuteReader(cmd)) 53 { 54 if(reader.Read()) 55 { 56 rule = GetRuleFromReader(reader); 57 } 58 } 59 60 return rule; 61 } 62 63 private AuthorizationRuleData GetRuleFromReader(IDataReader reader) 64 { 65 AuthorizationRuleData rule = new AuthorizationRuleData(); 66 rule.Name = reader.GetString(reader.GetOrdinal("Name")); 67 rule.Expression = reader.GetString(reader.GetOrdinal("Expression")); 68 69 return rule; 70 } 71 72 73 /**////// <summary> 74 ///// Retrieves all rules in the database as a DataSet 75 ///// </summary> 76 ///// <returns>A DataSet containing all of the rules</returns> 77 //public DataSet GetAllRules() 78 //{ 79 // DbCommand cmd = dbRules.GetStoredProcCommand("dbo.GetAllRules"); 80 81 // using(DataSet ds = dbRules.ExecuteDataSet(cmd)) 82 // { 83 // return ds; 84 // } 85 //} 86 87 88 /**//// <summary> 89 /// Retrieves all rules in the database as a Collection 90 /// </summary> 91 /// <returns>An AuthorizationRuleDataCollection containing all of the rules</returns> 92 public List<AuthorizationRuleData> GetAllRulesAsCollection() 93 { 94 List<AuthorizationRuleData> rules = new List<AuthorizationRuleData>(); 95 96 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.GetAllRules"); 97 98 using(IDataReader reader = dbRules.ExecuteReader(cmd)) 99 { 100 while(reader.Read()) 101 { 102 AuthorizationRuleData rule = GetRuleFromReader(reader); 103 rules.Add(rule); 104 } 105 } 106 return rules; 107 } 108 109 /**//// <summary> 110 /// Inserts a rule into the database 111 /// </summary> 112 /// <param name="name">The name of the rule</param> 113 /// <param name="expression">The expression defining the rule</param> 114 public void InsertRule(string name, string expression,string description) 115 { 116 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.InsertRule"); 117 dbRules.AddInParameter(cmd, "Name", DbType.String, name); 118 dbRules.AddInParameter(cmd, "Expression", DbType.String, expression); 119 dbRules.AddInParameter(cmd, "Description",DbType.String, description); 120 121 dbRules.ExecuteNonQuery(cmd); 122 } 123 124 /**//// <summary> 125 /// Saves the rule to the database 126 /// </summary> 127 /// <param name="ruleId">The Rule Id</param> 128 /// <param name="name">The name of the rule</param> 129 /// <param name="expression">The expression</param> 130 public void UpdateRuleById(int ruleId, string name, string expression) 131 { 132 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.UpdateRuleById"); 133 dbRules.AddInParameter(cmd, "id", DbType.Int32, ruleId); 134 dbRules.AddInParameter(cmd, "Name", DbType.String, name); 135 dbRules.AddInParameter(cmd, "Expression", DbType.String, expression); 136 //dbRules.AddInParameter(cmd, "Description", DbType.String, description); 137 138 dbRules.ExecuteNonQuery(cmd); 139 } 140 141 /**//// <summary> 142 /// Removes a rule from the database 143 /// </summary> 144 /// <param name="ruleId">The ruleid to remove</param> 145 public void DeleteRuleById(int ruleId) 146 { 147 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.DeleteRuleById"); 148 dbRules.AddInParameter(cmd, "id", DbType.Int32, ruleId); 149 150 dbRules.ExecuteNonQuery(cmd); 151 } 152 153 154 /**//***************** Follow Function Created by levinknight 2006.06.07 *****************/ 155 156 GetAllRules#region GetAllRules 157 public string[] GetAllRules() 158 { 159 string rules = string.Empty; 160 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.GetAllRules"); 161 162 using (DataSet ds = dbRules.ExecuteDataSet(cmd)) 163 { 164 foreach (DataRow rule in ds.Tables[0].Rows) 165 { 166 rules += (string)rule["Name"] + ","; 167 } 168 169 if (rules.Length >0) 170 { 171 rules = rules.Substring(0,rules.Length -1); 172 return rules.Split(','); 173 } 174 175 return new string[0]; 176 } 177 } 178 #endregion 179 180 GetRulesForUser by IPrincipal#region GetRulesForUser by IPrincipal 181 public string[] GetRulesForUser(IPrincipal principal) 182 { 183 if (principal == null) 184 { 185 throw new ArgumentException("Principal cannot be null."); 186 } 187 188 return GetEffectiveRules(principal); 189 } 190 #endregion 191 192 GetRulesForuser by Username#region GetRulesForuser by Username 193 public string[] GetRulesForUser(string username) 194 { 195 string[] roles = Roles.GetRolesForUser(username); 196 IPrincipal principal = new GenericPrincipal(new GenericIdentity(username),roles); 197 198 return GetEffectiveRules(principal); 199 } 200 #endregion 201 202 GetRulesForRole by Role'Name#region GetRulesForRole by Role'Name 203 public string[] GetRulesForRole(string rolename) 204 { 205 string[] roles = new string[1] {rolename}; 206 IPrincipal principal = new GenericPrincipal(new GenericIdentity(""), roles); 207 208 return GetEffectiveRules(principal); 209 } 210 #endregion 211 212 GetEffectiveRules Service for GetRulesFor User or Role#region GetEffectiveRules Service for GetRulesFor User or Role 213 private string[] GetEffectiveRules(System.Security.Principal.IPrincipal principal) 214 { 215 string rules = ""; 216 List<AuthorizationRuleData> ruleCollection = GetAllRulesAsCollection(); 217 218 try 219 { 220 foreach (AuthorizationRuleData rule in ruleCollection) 221 { 222 if ( IsInRule(principal,rule.Expression) ) 223 { 224 rules += rule.Name + ","; 225 } 226 } 227 } 228 catch (SyntaxException) 229 { 230 throw new ProviderException("返回有效权限时发生了错误,权限表达式非法"); 231 } 232 233 if (rules.Length > 0) 234 { 235 //删除最末尾的逗号 236 rules = rules.Substring(0,rules.Length - 1); 237 return rules.Split(','); 238 } 239 240 return new string[0]; 241 } 242 #endregion 243 244 AddUserToRule#region AddUserToRule 245 246 public void AddUserToRule(string ruleName,string username) 247 { 248 if (ruleName.Length == 0 || username.Length == 0) 249 { 250 throw new ProviderException("权限名和用户名都不能为空"); 251 } 252 253 string[] roles = Roles.GetRolesForUser(username); 254 IPrincipal principal = new GenericPrincipal(new GenericIdentity(username), roles); 255 256 AuthorizationRuleData rule = GetRule(ruleName); 257 258 if (rule == null) 259 { 260 throw new ProviderException(string.Format("权限: '{0}'不在数据库中",ruleName)); 261 } 262 263 264 if ( IsInRule(principal,rule.Expression) ) 265 { 266 throw new ProviderException(string.Format("用户: '{0}'已经拥有权限: '{1}'",username,ruleName)); 267 } 268 269 string ruleExpression = string.Empty; 270 string tempExpression = string.Empty; 271 272 if (rule.Expression.Contains(string.Format(" AND (NOT I:{0})", username))) 273 { 274 tempExpression = ruleExpression = rule.Expression.Replace(string.Format(" AND (NOT I:{0})", username), ""); 275 if (IsInRule(principal, tempExpression)) 276 { 277 ruleExpression = rule.Expression.Replace(string.Format(" AND (NOT I:{0})", username), ""); 278 } 279 else 280 { 281 ruleExpression = rule.Expression.Replace(string.Format(" AND (NOT I:{0})", username), 282 string.Format(" OR (I:{0})", username) 283 ); 284 } 285 } 286 else if (rule.Expression.Contains(string.Format("(NOT I:{0})", username))) 287 { 288 ruleExpression = rule.Expression.Replace(string.Format("(NOT I:{0})", username), 289 string.Format("(I:{0})", username) 290 ); 291 } 292 else 293 { 294 ruleExpression = rule.Expression + string.Format(" OR (I:{0})", username); 295 } 296 297 try 298 { 299 new Parser().Parse(ruleExpression); 300 } 301 catch (SyntaxException) 302 { 303 throw; 304 } 305 306 UpdateRuleByName(rule.Name,ruleExpression); 307 } 308 309 #endregion 310 311 RemoveUserFromRule#region RemoveUserFromRule 312 public void RemoveUserFromRule(string ruleName, string username) 313 { 314 if (ruleName.Length == 0 || username.Length == 0) 315 { 316 throw new ProviderException("权限名和用户名都不能为空"); 317 } 318 319 string[] roles = Roles.GetRolesForUser(username); 320 IPrincipal principal = new GenericPrincipal(new GenericIdentity(username), roles); 321 322 Parser parser = new Parser(); 323 AuthorizationRuleData rule = GetRule(ruleName); 324 325 if ( !parser.Parse(rule.Expression).Evaluate(principal) ) 326 { 327 throw new ProviderException(string.Format("用户: '{0}'已经没有权限: '{1}'", username,ruleName)); 328 } 329 330 string ruleExpression; 331 332 //此用户已经拥有了此权限 333 if (rule.Expression.Contains(string.Format(" OR (I:{0})", username))) 334 { 335 ruleExpression = rule.Expression.Replace(string.Format(" OR (I:{0})", username), ""); 336 } 337 //后面有表达式 OR 338 else if (rule.Expression.Contains(string.Format("(I:{0}) OR ", username))) 339 { 340 ruleExpression = rule.Expression.Replace(string.Format("(I:{0}) OR ", username), ""); 341 342 } 343 //后面有表达式 AND 344 else if (rule.Expression.Contains(string.Format("(I:{0}) AND ", username))) 345 { 346 ruleExpression = rule.Expression.Replace(string.Format("(I:{0}) AND ", username), ""); 347 } 348 //只有此用户拥有此权限 349 else if (rule.Expression.Contains(string.Format("(I:{0})", username))) 350 { 351 //ruleExpression = rule.Expression.Replace(string.Format("(I:{0})", username), ""); 352 throw new ProviderException("权限必须属于至少一个角色或用户!!!"); 353 } 354 //只是此用户所属的角色拥有此权限 355 else 356 { 357 ruleExpression = rule.Expression + string.Format(" AND (NOT I:{0})", username); 358 } 359 360 UpdateRuleByName(ruleName,ruleExpression); 361 } 362 #endregion 363 364 AddRoleToRule#region AddRoleToRule 365 public void AddRoleToRule(string ruleName,string roleName) 366 { 367 if (ruleName.Length == 0 || roleName.Length ==0) 368 { 369 throw new ProviderException("权限名和角色名都不能为空"); 370 } 371 372 string[] roles = new string[1] {roleName}; 373 IPrincipal principal = new GenericPrincipal( new GenericIdentity(""),roles ); 374 375 Parser parser = new Parser(); 376 AuthorizationRuleData rule = GetRule(ruleName); 377 BooleanExpression parsedExpression; 378 379 if (rule == null) 380 { 381 throw new ProviderException(string.Format("权限: '{0}'不在数据库中", ruleName)); 382 } 383 384 parsedExpression = parser.Parse(rule.Expression); 385 if (parsedExpression.Evaluate(principal)) 386 { 387 throw new ProviderException(string.Format("角色: '{0}'已经拥有权限: '{1}'", roleName, ruleName)); 388 } 389 390 string ruleExpression = string.Empty; 391 392 if (rule.Expression.Contains(string.Format(" AND (NOT R:{0})", roleName))) 393 { 394 ruleExpression = rule.Expression.Replace(string.Format(" AND (NOT R:{0})", roleName), 395 string.Format(" OR (R:{0})", roleName) 396 ); 397 } 398 else 399 { 400 ruleExpression = rule.Expression + string.Format(" OR (R:{0})", roleName); 401 } 402 403 ruleExpression = rule.Expression + string.Format(" OR (R:{0})", roleName); 404 405 try 406 { 407 parser.Parse(ruleExpression); 408 } 409 catch (SyntaxException)//权限表达式非法 410 { 411 throw new ApplicationException("权限表达式非法"); 412 } 413 414 UpdateRuleByName(rule.Name, ruleExpression); 415 416 } 417 #endregion 418 419 RemoveRoleFromRule#region RemoveRoleFromRule 420 public void RemoveRoleFromRule(string ruleName,string roleName) 421 { 422 string[] roles; 423 roles = new string[1] { roleName }; 424 425 if (ruleName.Length == 0 || roleName.Length == 0) 426 { 427 throw new ProviderException("权限名和角色名都不能为空"); 428 } 429 430 IPrincipal principal; 431 principal= new GenericPrincipal(new GenericIdentity(""), roles); 432 433 Parser parser = new Parser(); 434 AuthorizationRuleData rule = GetRule(ruleName); 435 436 if (!parser.Parse(rule.Expression).Evaluate(principal)) 437 { 438 throw new ProviderException(string.Format("角色: '{0}'已经没有权限: '{1}'", roleName, ruleName)); 439 } 440 441 string ruleExpression = string.Empty; 442 int i = 0; 443 444 //计算有几个角色拥有此权限 445 foreach (string role in Roles.GetAllRoles()) 446 { 447 roles[0] = role; 448 principal = new GenericPrincipal(new GenericIdentity(""),roles); 449 450 if (parser.Parse(rule.Expression).Evaluate(principal)) 451 { 452 i++; 453 } 454 } 455 456 if (i < 2) 457 { 458 throw new ProviderException("每个权限至少要属于一个角色!"); 459 } 460 461 462 //此角色已经拥有了此权限 463 if (rule.Expression.Contains(string.Format(" OR (R:{0})", roleName))) 464 { 465 ruleExpression = rule.Expression.Replace(string.Format(" OR (R:{0})", roleName), ""); 466 } 467 //后面有表达式 OR 468 else if (rule.Expression.Contains(string.Format("(R:{0}) OR ", roleName))) 469 { 470 ruleExpression = rule.Expression.Replace(string.Format("(R:{0}) OR ", roleName), ""); 471 472 } 473 //后面有表达式 AND 474 else if (rule.Expression.Contains(string.Format("(R:{0}) AND ", roleName))) 475 { 476 ruleExpression = rule.Expression.Replace(string.Format("(R:{0}) AND ", roleName), ""); 477 } 478 //只有此角色拥有此权限 479 //else if (rule.Expression.Contains(string.Format("(R:{0})", roleName))) 480 //{ 481 // //ruleExpression = rule.Expression.Replace(string.Format("(I:{0})", username), ""); 482 // throw new ProviderException("权限必须属于至少一个角色或用户!!!"); 483 //} 484 /**/////只是此角色拥有此权限 485 //else 486 //{ 487 // ruleExpression = rule.Expression + string.Format(" AND (NOT I:{0})", roleName); 488 //} 489 490 UpdateRuleByName(ruleName, ruleExpression); 491 } 492 #endregion 493 494 UpdateRuleByName#region UpdateRuleByName 495 private void UpdateRuleByName(string ruleName,string ruleExpression) 496 { 497 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.UpdateRuleByName"); 498 dbRules.AddInParameter(cmd, "Name", DbType.String, ruleName); 499 dbRules.AddInParameter(cmd, "Expression", DbType.String, ruleExpression); 500 501 dbRules.ExecuteNonQuery(cmd); 502 } 503 #endregion 504 505 DeleteRuleByName#region DeleteRuleByName 506 public void DeleteRuleByName(string ruleName) 507 { 508 if (ruleName.Length == 0) 509 { 510 throw new ProviderException("要删除的权限名不能为空"); 511 } 512 513 DbCommand cmd = dbRules.GetStoredProcCommand("dbo.DeleteRuleByName"); 514 dbRules.AddInParameter(cmd, "Name", DbType.String, ruleName); 515 516 dbRules.ExecuteNonQuery(cmd); 517 } 518 #endregion 519 520 CreateRule#region CreateRule 521 public void CreateRule(string ruleName,string description,string[] roles) 522 { 523 string ruleExpression; 524 string roleRules = string.Empty; 525 //string userRules = string.Empty; 526 527 if (ruleName == null) 528 { 529 throw new ArgumentException("权限名不能为空"); 530 } 531 532 if (roles.Length == 0) 533 { 534 throw new ProviderException("创建权限时必须指明权限的所属角色"); 535 } 536 537 if (roles.Length > 0) 538 { 539 foreach (string role in roles) 540 { 541 roleRules += string.Format("(R:{0}) OR ",role); 542 } 543 544 if (roles.Rank > 0) 545 { 546 roleRules = roleRules.Substring(0, roleRules.Length - 4); 547 } 548 } 549 550 ruleExpression = roleRules; 551 552 try 553 { 554 new Parser().Parse(ruleExpression); 555 } 556 catch (SyntaxErrorException) 557 { 558 throw; 559 } 560 561 InsertRule(ruleName,ruleExpression,description); 562 } 563 #endregion 564 565 IsInRule#region IsInRule 566 private bool IsInRule(IPrincipal principal,string ruleExpression) 567 { 568 Parser parser = new Parser(); 569 BooleanExpression parsedExpression; 570 571 try 572 { 573 parsedExpression = parser.Parse(ruleExpression); 574 } 575 catch (SyntaxException) 576 { 577 throw; 578 } 579 580 if (parsedExpression.Evaluate(principal)) 581 { 582 return true; 583 } 584 585 return false; 586 } 587 #endregion 588 } 589 } 590
Feedback
ms的Security Application Block好难用
2007-06-01 01:03 by volnet(可以叫我大V)
牛人
--------------------------------
汗,这是力气活啊,不敢当:)
2007-06-01 13:45 by 高海东
支持 不错 有使用的例子吗 对好有个demo
-----------------------------------------
这很容易使用,请下载代码,参考Readme里的说明
2007-06-01 14:25 by Justin
精神可嘉!
---------------
多谢鼓励:)
2008-04-20 15:01 by 程程 [未注册用户]
辛苦了,谢谢
=====================
不客气:)
写的好,理当嘉奖!
博客园对FireFox的支持有点问题哟。那个下载链接还非用IE来下才行。
|