SqlRoleProvider.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. //
  2. // System.Web.Security.SqlRoleProvider
  3. //
  4. // Authors:
  5. // Ben Maurer ([email protected])
  6. // Chris Toshok ([email protected])
  7. //
  8. // (C) 2003 Ben Maurer
  9. // Copyright (c) 2005,2006 Novell, Inc (http://www.novell.com)
  10. //
  11. // Permission is hereby granted, free of charge, to any person obtaining
  12. // a copy of this software and associated documentation files (the
  13. // "Software"), to deal in the Software without restriction, including
  14. // without limitation the rights to use, copy, modify, merge, publish,
  15. // distribute, sublicense, and/or sell copies of the Software, and to
  16. // permit persons to whom the Software is furnished to do so, subject to
  17. // the following conditions:
  18. //
  19. // The above copyright notice and this permission notice shall be
  20. // included in all copies or substantial portions of the Software.
  21. //
  22. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  23. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  24. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. //
  30. #if NET_2_0
  31. using System.Collections;
  32. using System.Collections.Specialized;
  33. using System.Data;
  34. using System.Data.Common;
  35. using System.Configuration;
  36. using System.Configuration.Provider;
  37. using System.Web.Configuration;
  38. namespace System.Web.Security {
  39. public class SqlRoleProvider: RoleProvider {
  40. string applicationName;
  41. int commandTimeout;
  42. string providerName;
  43. ConnectionStringSettings connectionString;
  44. DbProviderFactory factory;
  45. DbConnection CreateConnection ()
  46. {
  47. DbConnection connection = factory.CreateConnection ();
  48. connection.ConnectionString = connectionString.ConnectionString;
  49. connection.Open ();
  50. return connection;
  51. }
  52. void AddParameter (DbCommand command, string parameterName, string parameterValue)
  53. {
  54. DbParameter dbp = command.CreateParameter ();
  55. dbp.ParameterName = parameterName;
  56. dbp.Value = parameterValue;
  57. dbp.Direction = ParameterDirection.Input;
  58. command.Parameters.Add (dbp);
  59. }
  60. public override void AddUsersToRoles (string [] usernames, string [] rolenames)
  61. {
  62. string commandText = @"
  63. INSERT INTO dbo.aspnet_UsersInRoles (UserId, RoleId)
  64. SELECT dbo.aspnet_Users.UserId, dbo.aspnet_Roles.RoleId
  65. FROM dbo.aspnet_Users, dbo.aspnet_Roles, dbo.aspnet_Applications
  66. WHERE dbo.aspnet_Users.ApplicationId = dbo.aspnet_Applications.ApplicationId
  67. AND dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  68. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  69. AND dbo.aspnet_Users.LoweredUserName = LOWER(@UserName)
  70. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)
  71. ";
  72. Hashtable h;
  73. h = new Hashtable();
  74. foreach (string u in usernames) {
  75. if (u == null)
  76. throw new ArgumentNullException ("null element in usernames array");
  77. if (h.ContainsKey (u))
  78. throw new ArgumentException ("duplicate element in usernames array");
  79. if (u.Length == 0 || u.Length > 256 || u.IndexOf (",") != -1)
  80. throw new ArgumentException ("element in usernames array in illegal format");
  81. h.Add (u, u);
  82. }
  83. h = new Hashtable();
  84. foreach (string r in usernames) {
  85. if (r == null)
  86. throw new ArgumentNullException ("null element in usernames array");
  87. if (h.ContainsKey (r))
  88. throw new ArgumentException ("duplicate element in usernames array");
  89. if (r.Length == 0 || r.Length > 256 || r.IndexOf (",") != -1)
  90. throw new ArgumentException ("element in usernames array in illegal format");
  91. h.Add (r, r);
  92. }
  93. using(DbConnection connection = CreateConnection ()) {
  94. DbTransaction trans = connection.BeginTransaction ();
  95. try {
  96. foreach (string username in usernames) {
  97. foreach (string rolename in rolenames) {
  98. /* add the user/role combination to dbo.aspnet_UsersInRoles */
  99. DbCommand command = factory.CreateCommand ();
  100. command.Transaction = trans;
  101. command.CommandText = commandText;
  102. command.Connection = connection;
  103. command.CommandType = CommandType.Text;
  104. AddParameter (command, "RoleName", rolename);
  105. AddParameter (command, "UserName", username);
  106. AddParameter (command, "ApplicationName", ApplicationName);
  107. if (command.ExecuteNonQuery() != 1)
  108. throw new ProviderException ("failed to create new user/role association.");
  109. }
  110. }
  111. trans.Commit ();
  112. }
  113. catch (Exception e) {
  114. trans.Rollback ();
  115. if (e is ProviderException)
  116. throw e;
  117. else
  118. throw new ProviderException ("", e);
  119. }
  120. }
  121. }
  122. public override void CreateRole (string rolename)
  123. {
  124. string commandText = @"
  125. INSERT INTO dbo.aspnet_Roles
  126. (ApplicationId, RoleName, LoweredRoleName)
  127. VALUES ((SELECT ApplicationId FROM dbo.aspnet_Applications WHERE LoweredApplicationName = LOWER(@ApplicationName)), @RoleName, LOWER(@RoleName))
  128. ";
  129. if (rolename == null)
  130. throw new ArgumentNullException ("rolename");
  131. if (rolename.Length == 0 || rolename.Length > 256 || rolename.IndexOf (",") != -1)
  132. throw new ArgumentException ("rolename is in invalid format");
  133. using (DbConnection connection = CreateConnection ()) {
  134. DbCommand command = factory.CreateCommand ();
  135. command.CommandText = commandText;
  136. command.Connection = connection;
  137. command.CommandType = CommandType.Text;
  138. AddParameter (command, "ApplicationName", ApplicationName);
  139. AddParameter (command, "RoleName", rolename);
  140. if (command.ExecuteNonQuery() != 1)
  141. throw new ProviderException ("failed to create new role.");
  142. }
  143. }
  144. [MonoTODO]
  145. public override bool DeleteRole (string rolename, bool throwOnPopulatedRole)
  146. {
  147. if (rolename == null)
  148. throw new ArgumentNullException ("rolename");
  149. if (rolename.Length == 0 || rolename.Length > 256 || rolename.IndexOf (",") != -1)
  150. throw new ArgumentException ("rolename is in invalid format");
  151. using(DbConnection connection = CreateConnection ()) {
  152. DbCommand command;
  153. if (throwOnPopulatedRole) {
  154. command = factory.CreateCommand ();
  155. command.CommandText = @"
  156. SELECT COUNT(*)
  157. FROM dbo.aspnet_UsersInRoles, dbo.aspnet_Roles, dbo.aspnet_Users, dbo.aspnet_Applications
  158. WHERE dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  159. AND dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId
  160. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  161. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)";
  162. command.Connection = connection;
  163. command.CommandType = CommandType.Text;
  164. AddParameter (command, "ApplicationName", ApplicationName);
  165. AddParameter (command, "RoleName", rolename);
  166. int count = (int)command.ExecuteScalar ();
  167. if (count != 0)
  168. throw new ProviderException (String.Format ("The role '{0}' has users in it and can't be deleted", rolename));
  169. }
  170. else {
  171. /* XXX are we really supposed to delete all the user/role associations in this case? */
  172. command = factory.CreateCommand ();
  173. command.CommandText = @"
  174. DELETE dbo.aspnet_UsersInRoles FROM dbo.aspnet_UsersInRoles, dbo.aspnet_Roles, dbo.aspnet_Applications
  175. WHERE dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId
  176. AND dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  177. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)
  178. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)";
  179. command.Connection = connection;
  180. command.CommandType = CommandType.Text;
  181. AddParameter (command, "RoleName", rolename);
  182. AddParameter (command, "ApplicationName", ApplicationName);
  183. command.ExecuteNonQuery ();
  184. }
  185. command = factory.CreateCommand ();
  186. command.CommandText = @"
  187. DELETE dbo.aspnet_Roles FROM dbo.aspnet_Roles, dbo.aspnet_Applications
  188. WHERE dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  189. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  190. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)";
  191. command.Connection = connection;
  192. command.CommandType = CommandType.Text;
  193. AddParameter (command, "ApplicationName", ApplicationName);
  194. AddParameter (command, "RoleName", rolename);
  195. bool rv = command.ExecuteNonQuery() == 1;
  196. return rv;
  197. }
  198. }
  199. public override string[] FindUsersInRole (string roleName, string usernameToMatch)
  200. {
  201. string commandTextFormat = @"
  202. SELECT dbo.aspnet_Users.UserName
  203. FROM dbo.aspnet_Users, dbo.aspnet_Roles, dbo.aspnet_UsersInRoles, dbo.aspnet_Applications
  204. WHERE dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  205. AND dbo.aspnet_Users.ApplicationId = dbo.aspnet_Applications.ApplicationId
  206. AND dbo.aspnet_UsersInRoles.UserId = dbo.aspnet_Users.UserId
  207. AND dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId
  208. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)
  209. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  210. AND dbo.aspnet_Users.UserName {0} @UsernameToMatch
  211. ";
  212. if (roleName == null)
  213. throw new ArgumentNullException ("roleName");
  214. if (usernameToMatch == null)
  215. throw new ArgumentNullException ("usernameToMatch");
  216. if (roleName.Length == 0 || roleName.Length > 256 || roleName.IndexOf (",") != -1)
  217. throw new ArgumentException ("roleName is in invalid format");
  218. if (usernameToMatch.Length == 0 || usernameToMatch.Length > 256)
  219. throw new ArgumentException ("usernameToMatch is in invalid format");
  220. using(DbConnection connection = CreateConnection ()) {
  221. bool useLike = usernameToMatch.IndexOf ("%") != -1;
  222. DbCommand command = factory.CreateCommand ();
  223. command.CommandText = String.Format(commandTextFormat, useLike ? "LIKE" : "=");
  224. command.Connection = connection;
  225. command.CommandType = CommandType.Text;
  226. AddParameter (command, "ApplicationName", ApplicationName);
  227. AddParameter (command, "RoleName", roleName);
  228. AddParameter (command, "UsernameToMatch", usernameToMatch);
  229. DbDataReader reader = command.ExecuteReader ();
  230. ArrayList userList = new ArrayList();
  231. while (reader.Read())
  232. userList.Add (reader.GetString(0));
  233. reader.Close();
  234. return (string[])userList.ToArray(typeof (string));
  235. }
  236. }
  237. public override string [] GetAllRoles ()
  238. {
  239. string commandText = @"
  240. SELECT dbo.aspnet_Roles.RoleName
  241. FROM dbo.aspnet_Roles, dbo.aspnet_Applications
  242. WHERE dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  243. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  244. ";
  245. using(DbConnection connection = CreateConnection ()) {
  246. DbCommand command = factory.CreateCommand ();
  247. command.CommandText = commandText;
  248. command.Connection = connection;
  249. command.CommandType = CommandType.Text;
  250. AddParameter (command, "ApplicationName", ApplicationName);
  251. DbDataReader reader = command.ExecuteReader ();
  252. ArrayList roleList = new ArrayList();
  253. while (reader.Read())
  254. roleList.Add (reader.GetString(0));
  255. reader.Close();
  256. return (string[])roleList.ToArray(typeof (string));
  257. }
  258. }
  259. public override string [] GetRolesForUser (string username)
  260. {
  261. string commandText = @"
  262. SELECT dbo.aspnet_Roles.RoleName
  263. FROM dbo.aspnet_Roles, dbo.aspnet_UsersInRoles, dbo.aspnet_Users, dbo.aspnet_Applications
  264. WHERE dbo.aspnet_Roles.RoleId = dbo.aspnet_UsersInRoles.RoleId
  265. AND dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  266. AND dbo.aspnet_UsersInRoles.UserId = dbo.aspnet_Users.UserId
  267. AND dbo.aspnet_Users.LoweredUserName = LOWER(@UserName)
  268. AND dbo.aspnet_Users.ApplicationId = dbo.aspnet_Applications.ApplicationId
  269. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  270. ";
  271. using(DbConnection connection = CreateConnection ()) {
  272. DbCommand command = factory.CreateCommand ();
  273. command.CommandText = commandText;
  274. command.Connection = connection;
  275. command.CommandType = CommandType.Text;
  276. AddParameter (command, "UserName", username);
  277. AddParameter (command, "ApplicationName", ApplicationName);
  278. DbDataReader reader = command.ExecuteReader ();
  279. ArrayList roleList = new ArrayList();
  280. while (reader.Read())
  281. roleList.Add (reader.GetString(0));
  282. reader.Close();
  283. return (string[])roleList.ToArray(typeof (string));
  284. }
  285. }
  286. public override string [] GetUsersInRole (string rolename)
  287. {
  288. string commandText = @"
  289. SELECT dbo.aspnet_Users.UserName
  290. FROM dbo.aspnet_Roles, dbo.aspnet_UsersInRoles, dbo.aspnet_Users, dbo.aspnet_Applications
  291. WHERE dbo.aspnet_Roles.RoleId = dbo.aspnet_UsersInRoles.RoleId
  292. AND dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  293. AND dbo.aspnet_UsersInRoles.UserId = dbo.aspnet_Users.UserId
  294. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)
  295. AND dbo.aspnet_Users.ApplicationId = dbo.aspnet_Applications.ApplicationId
  296. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  297. ";
  298. using(DbConnection connection = CreateConnection ()) {
  299. DbCommand command = factory.CreateCommand ();
  300. command.CommandText = commandText;
  301. command.Connection = connection;
  302. command.CommandType = CommandType.Text;
  303. AddParameter (command, "RoleName", rolename);
  304. AddParameter (command, "ApplicationName", ApplicationName);
  305. DbDataReader reader = command.ExecuteReader ();
  306. ArrayList userList = new ArrayList();
  307. while (reader.Read())
  308. userList.Add (reader.GetString(0));
  309. reader.Close();
  310. return (string[])userList.ToArray(typeof (string));
  311. }
  312. }
  313. [MonoTODO]
  314. public override void Initialize (string name, NameValueCollection config)
  315. {
  316. if (config == null)
  317. throw new ArgumentNullException ("config");
  318. base.Initialize (name, config);
  319. #if false
  320. ApplicationName = config["applicationName"];
  321. #else
  322. ApplicationName = "/";
  323. #endif
  324. string connectionStringName = config["connectionStringName"];
  325. string commandTimeout = config["commandTimeout"];
  326. if (applicationName.Length > 256)
  327. throw new ProviderException ("The ApplicationName attribute must be 256 characters long or less.");
  328. if (connectionStringName == null || connectionStringName.Length == 0)
  329. throw new ProviderException ("The ConnectionStringName attribute must be present and non-zero length.");
  330. // XXX check connectionStringName and commandTimeout
  331. connectionString = WebConfigurationManager.ConnectionStrings[connectionStringName];
  332. factory = ProvidersHelper.GetDbProviderFactory (connectionString.ProviderName);
  333. }
  334. public override bool IsUserInRole (string username, string rolename)
  335. {
  336. string commandText = @"
  337. SELECT COUNT(*)
  338. FROM dbo.aspnet_Users, dbo.aspnet_UsersInRoles, dbo.aspnet_Roles, dbo.aspnet_Applications
  339. WHERE dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  340. AND dbo.aspnet_Users.ApplicationId = dbo.aspnet_Applications.ApplicationId
  341. AND dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId
  342. AND dbo.aspnet_UsersInRoles.UserId = dbo.aspnet_Users.UserId
  343. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  344. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)
  345. AND dbo.aspnet_Users.LoweredUserName = LOWER(@UserName)
  346. ";
  347. using(DbConnection connection = CreateConnection ()) {
  348. DbCommand command = factory.CreateCommand ();
  349. command.CommandText = commandText;
  350. command.Connection = connection;
  351. command.CommandType = CommandType.Text;
  352. AddParameter (command, "RoleName", rolename);
  353. AddParameter (command, "UserName", username);
  354. AddParameter (command, "ApplicationName", ApplicationName);
  355. bool rv = ((int)command.ExecuteScalar ()) != 0;
  356. return rv;
  357. }
  358. }
  359. public override void RemoveUsersFromRoles (string [] usernames, string [] rolenames)
  360. {
  361. string commandText = @"
  362. DELETE dbo.aspnet_UsersInRoles
  363. FROM dbo.aspnet_UsersInRoles, dbo.aspnet_Users, dbo.aspnet_Roles, dbo.aspnet_Applications
  364. WHERE dbo.aspnet_UsersInRoles.UserId = dbo.aspnet_Users.UserId
  365. AND dbo.aspnet_UsersInRoles.RoleId = dbo.aspnet_Roles.RoleId
  366. AND dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  367. AND dbo.aspnet_Users.ApplicationId = dbo.aspnet_Applications.ApplicationId
  368. AND dbo.aspnet_Users.LoweredUserName = LOWER(@UserName)
  369. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)
  370. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)";
  371. Hashtable h;
  372. h = new Hashtable();
  373. foreach (string u in usernames) {
  374. if (u == null)
  375. throw new ArgumentNullException ("null element in usernames array");
  376. if (h.ContainsKey (u))
  377. throw new ArgumentException ("duplicate element in usernames array");
  378. if (u.Length == 0 || u.Length > 256 || u.IndexOf (",") != -1)
  379. throw new ArgumentException ("element in usernames array in illegal format");
  380. h.Add (u, u);
  381. }
  382. h = new Hashtable();
  383. foreach (string r in usernames) {
  384. if (r == null)
  385. throw new ArgumentNullException ("null element in usernames array");
  386. if (h.ContainsKey (r))
  387. throw new ArgumentException ("duplicate element in usernames array");
  388. if (r.Length == 0 || r.Length > 256 || r.IndexOf (",") != -1)
  389. throw new ArgumentException ("element in usernames array in illegal format");
  390. h.Add (r, r);
  391. }
  392. using(DbConnection connection = CreateConnection ()) {
  393. DbTransaction trans = connection.BeginTransaction ();
  394. try {
  395. foreach (string username in usernames) {
  396. foreach (string rolename in rolenames) {
  397. DbCommand command = factory.CreateCommand ();
  398. command.Transaction = trans;
  399. command.CommandText = commandText;
  400. command.Connection = connection;
  401. command.CommandType = CommandType.Text;
  402. AddParameter (command, "UserName", username);
  403. AddParameter (command, "RoleName", rolename);
  404. AddParameter (command, "ApplicationName", ApplicationName);
  405. if (command.ExecuteNonQuery() != 1)
  406. throw new ProviderException (String.Format ("failed to remove users from role '{0}'.", rolename));
  407. }
  408. }
  409. trans.Commit ();
  410. }
  411. catch (Exception e) {
  412. trans.Rollback ();
  413. if (e is ProviderException)
  414. throw e;
  415. else
  416. throw new ProviderException ("", e);
  417. }
  418. }
  419. }
  420. public override bool RoleExists (string rolename)
  421. {
  422. string commandText = @"
  423. SELECT COUNT(*)
  424. FROM dbo.aspnet_Roles, dbo.aspnet_Applications
  425. WHERE dbo.aspnet_Roles.ApplicationId = dbo.aspnet_Applications.ApplicationId
  426. AND dbo.aspnet_Applications.LoweredApplicationName = LOWER(@ApplicationName)
  427. AND dbo.aspnet_Roles.LoweredRoleName = LOWER(@RoleName)
  428. ";
  429. using (DbConnection connection = CreateConnection ()) {
  430. DbCommand command = factory.CreateCommand ();
  431. command.CommandText = commandText;
  432. command.Connection = connection;
  433. command.CommandType = CommandType.Text;
  434. AddParameter (command, "ApplicationName", ApplicationName);
  435. AddParameter (command, "RoleName", rolename);
  436. bool rv = ((int) command.ExecuteScalar ()) != 0;
  437. return rv;
  438. }
  439. }
  440. [MonoTODO]
  441. public override string ApplicationName {
  442. get { return applicationName; }
  443. set {
  444. applicationName = value;
  445. }
  446. }
  447. }
  448. }
  449. #endif