Professional ASP.NET 2.0 Security, Membership, and Role Management phần 8 ppsx

64 509 0
Professional ASP.NET 2.0 Security, Membership, and Role Management phần 8 ppsx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

gets installed) against the user instance. The end result of this work is that an .mdf file is created in the file location specified by the connection string. As the last part of this work, the provider infrastructure detaches the newly created .mdf file. 5. Within the new user instance, the database file specified by AttachDBFilename is attached to the instance and registered in the metadata tables in the user instance’s master database. If you are accustomed to working with databases as a named database in other versions of SQL Server, this might seem a bit strange. However, using the attach syntax in the connection string causes the SSE user instance to attach the database on your behalf. The connection string shown earlier exists in machine.config to allow developers that use Visual Studio to get up and running “auto-magically” with the application services. Rather than running aspnet_regsql.exe manually to install the database scripts into a specific database on a database server, you can write code against a feature like Membership, and the database will automatically be created for you. From an ease-of-use perspective, this is actually pretty powerful and makes features like Membership so straightforward to use that developers potentially don’t need to understand or muck around with databases. Of course, this rosy scenario actually has a few streaks on the window, as you will shortly see. The automatic database creation behavior was originally intended for client applications such as ClickOnce apps. In a client environment, a user instance makes a fair amount of sense because someone is actually running interactively on a machine with a well-established set of credentials. Furthermore, while running in a client environment there is likely to be sufficient processing power on the machine to handle the overhead of user instancing. Just running the named SSE instance plus a user instance with the ASP.NET database tables in them incurs up to about 45–75MB of memory overhead. That’s a pretty hefty wallop, but nonetheless manageable on a single desktop machine. When the user instancing capability was used for the ASP.NET application services, the main scenario was to support development in Visual Studio — in essence, this is another client application scenario, albeit in this case the client application is a development environment. However, the SSE story on a web server starts to break down because of a few constraints with user instancing. The most obvious one is that user instancing is tied to a specific user identity, which leads to the potential for multiple user instances floating around on a server. With around a 45MB overhead when the SQL providers auto-create the database, and around 25MB of overhead once the database exists, it wouldn’t take long for a shared web server to run out of memory space. If you set up 40 application pools on IIS6 with each application pool running as a different identity, you could slurp up 1GB of memory with SSE user instances in short order. The next issue with user instancing deals specifically with the operating system thread identity that is used when making the initial ADO.NET connection. As mentioned earlier, this identity is critical because SSE needs to ensure that cloned databases like the master database exist for these user accounts. Additionally, SSE needs the security token of the client to create a new child process running the SQL Server executable. It turns out though that for SSE to actually know where to create and look for the cloned versions of master and other databases, a Windows user profile needs to be loaded into memory. In the scenario with a client application, the dependency on the Windows user profile is a nonissue. The second you log on to a Windows machine with some credentials, your Windows user profile is loaded. Hence, any application that you choose to run, including Visual Studio will be able to find data that is stored in the Windows user profile. What happens though for a noninteractive scenario like IIS6 applica- 421 SqlMembershipProvider 14_596985 ch11.qxp 12/14/05 7:51 PM Page 421 tion pools? It turns out that when you run ASP.NET (any version of ASP.NET for that matter) on IIS6, the Windows user profile is never loaded for the account identity used for the application pool when the application pool uses an account other than NETWORK SERVICE. If you write an ASP.NET application that uses Membership with the default connection string, in some circumstances the application services database is automatically created for you. The reason this works is basically by accident. Because the default identity for IIS6 application pools is NETWORK SERVICE, and NETWORK SERVICE is commonly used for other services on a Windows Server 2003 machine, the Windows user profile for NETWORK SERVICE gets loaded as a side effect of the operating system start- ing up. As a result, when you use SSE with the default connection string using the default IIS6 applica- tion pool identity, the named SSE instance is able to query the Windows user profile for the location of the Local Settings folder for NETWORK SERVICE. However, if you attempt to use application impersonation or to change the application pool identity to a different account, any code you write that uses the default SSE connection string will fail. For all other application pool identities, there is no Windows user profile available. As a result, if you attempt to use SSE user instances, you will instead end up with the following exception: Failed to generate a user instance of SQL Server due to failure in retrieving the user’s local application data path. Please make sure the user has a local user profile on the computer. The connection will be closed. Other information is displayed along with this error, but if you see this error, you aren’t ever going to get SSE user instancing to work (ignoring any crazy hacks that forcibly load a Windows user profile using an NT service or schedule batch job). This behavior basically leaves you wondering when to use the default connection string and when to change it. If you perform most of your development using file-based, as opposed to IIS-based, websites on your own machine, then you can leave the SSE connection string as is. File-based webs use the Cassini web server instead of the IIS6 process model. Cassini runs with your logged-in credentials, so SSE will always be able to find your Windows user profile. This security model meshes well with SSE’s assumptions about user instancing. However, if you are developing websites with IIS6 (some of you probably run Windows Server 2003 for a development “desktop”), or if you are developing websites that will be deployed to IIS6, then you defi- nitely should consider changing the SSE style connection string. There are a few reasons for this sugges- tion: ❑ As noted earlier, unless your IIS6 application pool runs as NETWORK SERVICE, the SSE style connections are not going to work anyway. ❑ There is a somewhat nonobvious problem with handshaking between an IIS6 website and the development environment over who has control over the .mdf file (more on this in a bit). ❑ From a security perspective, you should not run with user instancing on any of your production machines if untrusted applications are deployed on them. The last point may not be something that many of you run into. Most companies have SQL Server instal- lations running on separate machines, in which case user instances would never come into the picture. (You can’t connect to an SSE user instance from across the network; only local connections are accepted 422 Chapter 11 14_596985 ch11.qxp 12/14/05 7:51 PM Page 422 against user instances.) If you happen to be in an environment where SSE is installed locally on your web servers as a sort of low-cost database, you still should be aware of the security implications of user instancing. Imagine a scenario where you have two different application pools on IIS6 both running as NETWORK SERVICE. If you put applications from two different untrusted clients into the two different application pools, you may think that you have enforced a reasonable degree of isolation between the two applica- tions. The idea is that the two clients don’t know or trust each other — perhaps for example this is an Internet facing shared hosting machine. Because their sites are in different application pools, the applica- tions can’t reach into each other’s memory spaces and carry out malicious tasks. If you are running in something like Medium trust, the applications can’t use file I/O to try to read each other’s application files. So, you might think you are reasonably safe at this point. However, if these applications use a connection string that specifies SSE user instances you will come to grief. Because both application pools run as NETWORK SERVICE, SSE will spin up one, and only one, instance of sqlservr.exe running as NETWORK SERVICE. Both applications will connect to this single user instance, and both applications as a result will be running with System Administrators privileges within this single user instance. The end result is that two untrusted applications have access to each other’s data. And, of course, attempting to switch the application pool identities to something else immediately breaks SSE user instancing! There is a scenario though where SSE user instancing is reasonable for IIS6 production machines. If you are running in a corporate environment (and this can be an intranet, an extranet, or the Internet) and all of the applications on the machine are from trusted sources, SSE user instancing can probably be left in place. Because all of the code authors are presumably from the same or trusted organizations, there probably are not any concerns with snooping each other’s data. Also, corporate developers running local SQL Server installations on their web servers probably aren’t storing confidential information in these databases. You may just be storing information such as Web Parts Personalization data — if the worst happens and someone walks away with everyone’s preferred background color for a web part on page two of your application, it is not the end of the world. A cautionary note for this scenario is still needed though. Even if all of the applications on a machine trust each other, I still wouldn’t store any security sensitive data in an SSE user-instanced database. For example, I would still recommend storing Membership and Role Manager data at a minimum inside of a regular SQL Server database that can be protected. And ideally such a database would be running on a remote machine, not locally on the web server. Note that although this section is discussing the user instance mode of SSE, you can install SSE on a machine just as you would normally install any other version of SQL Server. You can then have local and remote web servers connect to SSE using the more traditional database connection string syntax: “server=remoteserver\SQLEXPRESS;database=aspnetdb;Integrated Security=true” This connection string works the same way as connections to named instances of SQL Server 2000 work today. With this approach you need to manually enable remote network connections to SSE because by default even the named instance of SSE only allows local connections. Also, you can turn off user instancing on your machines that are running SSE at install time (There is an advanced option for turn- ing off support.) Alternatively, you can connect to the SSE named instance using credentials that have System Administrators privileges. Then using a command line tool like OSQL.exe or SQLCMD.exe you can run the following SQL commands: 423 SqlMembershipProvider 14_596985 ch11.qxp 12/14/05 7:51 PM Page 423 exec sp_configure ‘show advanced option’, ‘1’ go reconfigure with override go exec sp_configure ‘user instances enabled’, 0 go reconfigure with override go Unless you intend to support user instancing for development purposes or web servers where you trust all of the users and you aren’t storing sensitive data, you should turn off support for user instances. Especially in environments such as shared hosting servers that support multiple untrusted clients, you should always disable SSE user instancing. Sharing Issues with SSE If you work with an IIS based web application inside of Visual Studio, you will probably run into cases with lock contention over the .mdf file containing the application services database. An .mdf file cannot be opened by more than one instance of sqlservr.exe at a time. If you are developing with file-based webs you won’t run into this issue because the Visual Studio environment and the Cassini web server run under the same credentials—the interactive user. Whenever either environment attempts to manipulate an .mdf both processes are routed to the same SSE user instance, and hence there is no file contention. With an IIS-based web, you potentially have two different user accounts causing two different SSE user instances to be spawned. IIS will spawn a user instance running as NETWORK SERVICE, whereas the Visual Studio design environment will cause a user instance running as the interactive user to be spawned. You can run into a problem with this environment if you start debugging your application in IIS6, thus causing the user instance running as NETWORK SERVICE to own the application services .mdf file. Then if you go back into Visual Studio and try to run the Web Administration Tool (WAT), Visual Studio will start up a Cassini instance running as you. When you then surf around the WAT and access functionality that needs to access the .mdf, you may get error like the following: Unable to open the physical file “c:\inetpub\wwwroot\Chapter11\SSEUsingIIS\App_Data\aspnetdb.mdf”. Operating system error 32: “32(The process cannot access the file because it is being used by another process.)”. An attempt to attach an auto-named database for file c:\inetpub\wwwroot\Chapter11\SSEUsingIIS\App_Data\aspnetdb.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share. or Cannot open user default database. Login failed. Login failed for user ‘DOMAIN\user’. These errors can occur because the SSE user instance for IIS6 is still up and running, and thus the SSE user instance for WAT in Cassini cannot get open the same .mdf file. Technically, this type of issue is not supposed to occur in many cases because within Visual Studio there are certain click paths that create an app_offline.htm file in the root of the IIS6 website. Remember that Chapter 1 pointed out that placing a file called app_offline.htm in the root of a website immediately caused the app-domain to recycle. 424 Chapter 11 14_596985 ch11.qxp 12/14/05 7:51 PM Page 424 The idea behind Visual Studio placing a temporary app_offline.htm in the root of an IIS-based website is that when the app-domain recycles, all the ADO.NET connections to the SSE user instance drop. As a result, the SSE user instance should quickly detect that there are no active connections to the currently attached database, and therefore the SSE user instance should release any attached .mdf files. Unfortunately, the SSE auto-detach behavior and Visual Studio handshaking behavior has been flaky since day one, and therefore the extra work that Visual Studio does to force a detaching of the applica- tion services database sometimes does not work. If you end up in this situation, the quickest way to force an app-domain restart in the IIS application is to touch the web.config. Put a space in the file, or make some trivial edit, and then save the updated web.config. ASP.NET will detect that web.config has changed, and it will cycle the app-domain, which in turn will trigger the auto-detach behavior in SSE. If you have problems going in the other direction (that is, the data designer in Visual Studio or the WAT has grabbed access to the .mdf file), you have two options. You can rectify the problem by finding the sqlservr.exe instance in Task Manager that is running with your logged in identity and just kill the process. Or you can right-click on the appli- cation services database in the Visual Studio Solution Explorer and select Detach. When you then switch to your IIS6 application, the SSE user instance running as NETWORK SERVICE will be able to grab access to the .mdf file again. As you can see from this process of sharing the application services .mdf file between the design envi- ronment and IIS, this is yet another reason why using SSE for any of the ASP.NET application services is frequently more trouble than it is worth when developing against IIS6. In general, I would only use SSE when developing file-based webs where the entire hand-shaking issue never arises. Changing the SSE Connection String So, what happens if you don’t want to use SSE user instancing? Does this suddenly mean that you have to redefine every application provider just to switch over the connection string? Thankfully, the answer to this is no! All of the ASP.NET providers, regardless of whether they are defined in machine.config or the root web.config, reference the connection string named LocalSqlServer. Because the <connectionStrings /> configuration section is a standard add-remove-clear collection, you can just redefine the LocalSqlServer connection string to point at a different server and database: <connectionStrings> <remove name=”LocalSqlServer”/> <add name=”LocalSqlServer” connectionString=”data source=.\SQLEXPRESS; Integrated Security=SSPI;database=aspnetdb”/> </connectionStrings> This connection string redefines the common connection string shared by all SQL providers to point at the default local SSE named instance, but instead specifies connecting to a database called aspnetdb. This is the more traditional SQL Server connection string that you probably familiar with from SQL Server 2000. For other server locations, you can change the data source portion of the connection string to point at the correct server. With the connection string shown previously, you can use the aspnet_regsql tool to install all of the application services database schemas in a database called aspnetdb on the local SSE instance. The aspnet_regsql.exe tool is located in the Framework’s installation directory: aspnet_regsql -S .\SQLEXPRESS -E -A all -d aspnetdb 425 SqlMembershipProvider 14_596985 ch11.qxp 12/14/05 7:51 PM Page 425 For this to work with a remote SSE instance, you need to use the SQL Server Configuration Manager tool that comes with SSE and enable either the Named Pipes or TCP/IP protocol for the remote SSE instance. SSE by default disables these protocols to prevent connections made by remote servers. After you have installed the application services databases, you still need to grant the appropriate login rights and permissions in the application services database. These steps aren’t unique to SSE because you will have to do this for any variation of SQL Server other than user instanced SSE installations. The subject of database security is the topic for the next section. Database Security After the database schema is installed using aspnet_regsql, your applications still aren’t going to be able to use the database. You need to grant the appropriate account login rights to the SQL Server. And then you need to grant the appropriate rights in the application services database. The first question that needs to be answered is which account do the SQL-based providers use when connecting to SQL Server? Internally all of the SQL providers, including SqlMembershipProvider, will suspend client imperson- ation if it is in effect. This means that the identity used by the providers for communicating with SQL Server when using integrated security will be one of the following: ❑ The process identity of the IIS6 worker process. This is NETWORK SERVICE by default, but it can be different if you have changed the identity of the application pool. ❑ If you configured application impersonation for you application, then the provider connects using the explicit credentials specified in the <identity /> configuration element. If you have <identity impersonate=”true” /> and you are using Windows authentication, the providers always suspend client impersonation. From a security perspective, it’s not a good approach to grant login and database access to all potential Windows accounts on your website. If your connection string uses standard SQL security instead of integrated security, then the identity that connects to SQL Server is pretty easy to identify; it’s simply the standard SQL user account that is specified in the connec- tion string. After you have identified the specific identity that will be used when connecting to SQL Server, you need to first grant login rights on the server to this identity. You can use the graphical management tools supplied with SQL Server 2000 and the nonexpress SKUs of SQL Server 2005 to do this. If you need to grant access to the NETWORK SERVICE account without a graphical tool, you can type in “NT AUTHORITY\NETWORK SERVICE” for the NETWORK SERVICE account of a local machine. However, if you want to grant access to the NETWORK SERVICE account for a remote web server, you need to grant access to DOMAIN\MACHINENAME$. This special syntax references the machine account for a server in a domain. The MACHINENAME$ portion of this account actually references the NETWORK SER- VICE account for a remote machine. If your website uses some other kind of domain credentials, you would just type DOMAIN\USERNAME instead. If you want, you can also grant login rights using plain old TSQL to accomplish this: exec sp_grantlogin N’CORSAIR\DEMOTEST$’ 426 Chapter 11 14_596985 ch11.qxp 12/14/05 7:51 PM Page 426 You use a standard SQL Server login account instead of a domain style name if your connection string uses standard SQL credentials. If you choose to use a locally installed SSE database, for some strange reason there is no graphical management tool for this type of operation that is available out of the box with the SSE installation. Instead, you need to use command-line tools like OSQL.exe or SQLCMD.exe to run this command. There is nothing quite like forward progress that throws you a decade back in time! After login rights are granted on the SQL Server, you then need to grant permissions for that login account to access the application services database. Assuming that you want to grant login rights for a local NETWORK SERVICE account to a database called aspnetdb, the TSQL for this looks like: use aspnetdb go exec sp_grantdbaccess ‘NT AUTHORITY\NETWORK SERVICE’ go You just use a different value for the username passed to sp_grantdbaccess, depending on whether you are granting login rights to a different domain account or to a standard SQL account. Of course, if you are using any of the graphical management tools, you can also use them to grant access to the database. By this point, you have set things up in SQL Server so that the appropriate account can at least connect to SQL Server and reach the database. The last step is granting rights in the database to the account — this includes things like rights to query views and execute stored procedures. The ASP.NET schemas though are installed with a set of SQL Server roles that make this exercise substantially simpler. Although you could make the application pool identity a dbo in the application services database for example, this goes against the grain of granting least privilege. Furthermore, if you installed the ASP.NET schema in a preexisting database, you probably do not want the ASP.NET process identity (or whatever credentials are being used) to have such broad privileges. The ASP.NET schema includes a set of roles for each set of application services with the following suffixes: ❑ BasicAccess — Database rights granted to this role are restricted to stored procedures that are needed for minimal feature functionality. The role does not have execute rights on stored proce- dures that deal with more advanced feature functionality. ❑ ReportingAccess — This role has rights to stored procedures that deal with read-only opera- tions and search operations. The role also has rights to perform selects against the SQL Server views that were created for the feature. ❑ FullAccess — These roles have rights to execute all of the stored procedures associated with the feature as well as having select rights on all of a feature’s SQL views. None of the feature-specific roles grant access directly to the SQL tables because the features deal with data by way of stored procedures and optionally views. As a result, there is no reason for a member of a feature’s roles to manipulate the tables directly. This also means that in future releases the ASP.NET team has the freedom to change the underlying table schemas because all access to the data in these tables is by way of stored procedures or views. 427 SqlMembershipProvider 14_596985 ch11.qxp 12/14/05 7:51 PM Page 427 Technically, the Health Monitoring feature (aka Web Events) is an exception to this rule because it does not provide any mechanism for querying data from the event table other than through direct SELECT statements. Other features like Membership though expect you to always go through the object API or for purposes of running reports, through the SQL Server views. For the Membership feature, three roles are available to you: ❑ aspnet_Membership_BasicAccess — This role only allows you to call ValidateUser as well as GetUser and GetUserNameByEmail. ❑ aspnet_Membership_ReportingAccess — This role allows you to call GetUser, GetUserNameByEmail, GetAllUsers, GetNumberOfUsersOnline, FindUsersByName, and FindUsersByEmail. Members of this role can also issue select statements against the Membership views. ❑ aspnet_Membership_FullAccess — This role can call any of the methods defined on SqlMembershipProvider as well as query any of the Membership views. Most of the time, you will just add the appropriate account to one of the FullAccess roles. The other more restrictive roles are there for security sensitive sites that may have separate web applications for creating users as opposed to logging users in to the website. You can add an account to a role through any of the SQL Server graphical tools, or you can use TSQL like the following: exec sp_addrolemember ‘aspnet_Membership_FullAccess’, ‘NT AUTHORITY\NETWORK SERVICE’ After this command runs, whenever a website running as NETWORK SERVICE has a SqlMembershipProvider that attempts to call a Membership stored procedure in the database, the call will succeed because NETWORK SERVICE has login rights on the server and belongs to a database role that grants all of the necessary privileges to execute stored procedures. Database Schemas and the DBO User Many of the previous topics assume that you have sufficient privileges to install the application services schemas on your database server. If you or a database administrator have rights to create databases (that is, you are in the db_creator server role), or have “dbo” rights in a preexisting database, then you can just run the aspnet_regsql tool without any worries. However, there is a very important dependency that the current SQL-based providers have on the con- cept of the dbo user. If you look at any of the .sql installation scripts in the Framework’s installation directory, you will see that all of the tables and stored procedures are prepended with dbo: CREATE TABLE dbo.aspnet_Membership CREATE PROCEDURE dbo.aspnet_Membership_CreateUser and so on. Furthermore, the code inside of all of the stored procedures explicitly references object names (that is, tables and stored procedures) using the explicit dbo username:” 428 Chapter 11 14_596985 ch11.qxp 12/14/05 7:51 PM Page 428 EXEC dbo.aspnet_Applications_CreateApplication SELECT @NewUserId = UserId FROM dbo.aspnet_Users and so on. If you disassemble any of the SQL providers with a tool like ildasm, you will also see that the providers themselves use the dbo owner name when calling stored procedures: SqlCommand cmd = new SqlCommand(“dbo.aspnet_Membership_GetUserByEmail”, ); If you install the database schemas as a member of the System Administrators role, or as a member of the Database Creators role, none of this will affect you because an SA or a database creator are treated as dbo within a newly created database. In this case, because you are dbo, you can of course create objects associated with the dbo username. Problems arise though if you do not have dbo privileges in the database. For example, you can be running as someone other than dbo and still create tables in a database. Unfortunately, though if you were to just issue a command like: CREATE PROCEDURE aspnet_Membership_CreateUser a table object called your_account_name. aspnet_Membership_CreateUser is created instead. If this were allowed to happen, a provider like SqlMembershipProvider would never work because the provider would always be looking for a stored procedure owned by dbo and would never see the user-owned stored procedure. The reason that all of the providers explicitly look for a dbo-owned object is that at least on SQL Server 2000 (which is expected to be the main platform for running the application services databases for the first few years), there is a slight performance drain if you call stored procedures with- out including the owner name. From experience, the ASP.NET team found that this slight performance drain was actually so severe with the SQL Server schema for session state back in ASP.NET 1.1 that they had to QFE the session state database scripts and Session State server code to always user owner-qualified stored procedure names. To prevent the same problem with contention over stored procedure compilation locks from occurring with the new ASP.NET 2.0 database schema, the decision was made to owner-qualify all objects in the application services schemas. Of course, that decision created the problem of which owner name to use. Because dbo is a common owner name that is always available in SQL Server databases, the decision was made to hard-code the dbo owner name into the schemas and the providers. After Beta 1 shipped, problems arose with shared hosting companies that sell SQL Server databases for their customers. Some of these hosters do not grant dbo privileges in the database purchased by the customer. If you attempt to run the older Beta 1 versions of the database scripts the attempt fails. To work around this, the new requirement is that you must be one of the following to install the database schemas for the application services: ❑ You can be dbo in the database. ❑ You must be a member of both the db_ddladmin and db_securityadmin roles in the database. 429 SqlMembershipProvider 14_596985 ch11.qxp 12/14/05 7:51 PM Page 429 If you belong to both the db_ddladmin and db_securityadmin roles in a database, then as long as a shared hoster or some other entity creates the database for you ahead of time, you can log in to the database and successfully run any of the SQL installation scripts. You need to be in the db_ddladmin role to issue commands like CREATE TABLE or CREATE PROCEDURE. Other than db_ddladmin, only dbo has this right by default. As strange as it may seem, a db_ddladmin member can create database objects owned by other user accounts. However, just because a db_ddladmin can create such objects doesn’t mean a member of that role can use those objects. As a result, you also need to belong to db_securityadmin because at the end of the SQL installation scripts there are commands that create SQL Server roles and then grant execute rights and select rights on the stored procedures and views to the various roles. If you aren’t a member of the db_securityadmin role, the scripts won’t be able to setup the SQL Server roles and associated permissions properly. Although some hosters or companies might still be reticent to grant db_ddladmin and db_securityadmin rights, this set of rights is appropriate for most scenarios where all you want to do is prevent handing out dbo rights to everyone. A very important point to keep in mind from all of this discussion is that although you need to run with some kind of elevated privileges to install the database scripts, you don’t need these privileges to use the database objects. For any SQL based provider to successfully call the stored procedures, you only need to add the appropriate security accounts to one or more of the predefined SQL Server roles. You don’t have to grant the security accounts on your web servers dbo privileges or either of the two special security roles just discussed. In this way, at runtime you can still restrict the rights granted to the web server accounts and thus maintain the principle of least privilege when using any of the SQL-based providers. For future Framework releases, the ASP.NET team is considering tweaking the SQL-based providers to allow for configurable owner names. Implementing the feature would allow you to install the applica- tion services schema using any arbitrary user account. The account would only need rights to create tables, views and stored procedures, which is an even lower set of privileges than those available from db_ddladmin and db_securityadmin. Then the providers would have an extra configuration attribute for you to specify the correct owner name to be prepended by the providers to all stored procedure calls. Changing Password Formats When you configure SqlMembershipProvider you have the option of storing passwords in cleartext, as hashed values, or as encrypted values. By default, the provider will use SHA1 hashing with a random 16-byte salt value. As mentioned in the Membership chapter, you can change the hashing algorithm by defining a different algorithm in the hashAlgorithmType configuration attribute on the <membership /> element. If you choose encrypted passwords, the provider by default uses whatever is configured for encryption on the <machineKey /> element. The default algorithm for <machineKey /> is AES — although you can change this to 3DES instead with the new “decryption” attribute. If you choose to use encrypted passwords with SqlMembershipProvider, then you must explicitly provide a value for the decryptionKey attribute on <machineKey />, because if you were allowed to encrypt with the <machineKey /> default of AutoGenerate,IsolateApps your passwords could become undecryptable. For example, there would be no way to decrypt passwords across a web farm. Also, whenever the Framework is upgraded or installed on a machine, the auto-generated machine keys are regenerated. Overall, the danger of leading developers into a dead end with encryption was so great that the provider now requires you to explicitly supply the decryption key for <machineKey />. 430 Chapter 11 14_596985 ch11.qxp 12/14/05 7:51 PM Page 430 [...]... up the necessary ADO.NET command for calling the insert stored procedure shown earlier: private void InsertHistoryRow(string username, string password) { using (SqlConnection conn = new SqlConnection(connectionString)) { //Setup the command string command = “dbo.InsertPasswordHistoryRow”; SqlCommand cmd = new SqlCommand(command, conn); cmd.CommandType = System.Data.CommandType.StoredProcedure; //Setup... PasswordUsedBefore(string username, string password) { using (SqlConnection conn = new SqlConnection(connectionString)) { //Setup the command string command = “dbo.GetPasswordHistory”; SqlCommand cmd = new SqlCommand(command, conn); cmd.CommandType = System.Data.CommandType.StoredProcedure; //Setup the parameters SqlParameter[] arrParams = new SqlParameter[2]; arrParams[0] = new SqlParameter(“pUserName”,... characters in the random password int desiredLength = MinRequiredPasswordLength < 14 ? 14 : MinRequiredPasswordLength; byte[] randBytes = new byte[desiredLength]; char[] convertedResult = new char[desiredLength]; //First get some random values rcsp.GetBytes(randBytes); //Then convert these values into characters for (int i = 0; i < desiredLength; i++) { int indexOffset = ((int)randBytes[i]) % randChars.Length;... dbo.vw_aspnet_Applications a, dbo.vw_aspnet_Users u where a.LoweredApplicationName = LOWER(@pApplicationName) and a.ApplicationId = u.ApplicationId and u.LoweredUserName = LOWER(@pUserName) and ph.UserId = u.UserId order by CreateDate DESC This procedure is pretty basic — it accepts the username and application name and uses these two values to get to the UserId At which point, the procedure returns all of the rows... number of random byte values using RNGCryptoServiceProvider This ensures that the values are truly random as opposed to having some hidden dependency on a known seed The byte values are then converted into characters by treating each random byte value as an integer and then performing a modulus operation on the integer The resulting value is used as an index into the fixed character array randChars defined... initial password is logged to the PasswordHistory table: UserId Password PasswordSalt CreateDate {A71E13F5-DB 58- 4E10-BEB4- 982 5E5A263F2} tJUZ5K1A5JuWcrZoJjF1OMXGM +8= B8sbL04yOYwGyYZHT7AADA== 2005-07-27 21:04:10.257 447 Chapter 11 So far so good — a user is registered in the Membership tables and the initial password is stored in the history The next step is to get the custom provider working with the... custom provider implementation allows only uppercase and lowercase representations of a–z as well as the numbers 0–9 in a randomly generated password Using this approach you can easily change the characters allowed in a random password by editing the characters in the randChars variable Because the modulus operation always runs based on the length of randChars, you can change the length of the array without... to hook up your custom event handler to the provider in every web application that requires custom enforcement ❑ Derive from SqlMembershipProvider and override those methods that deal with creating or changing passwords (CreateUser, ChangePassword and ResetPassword) — You have to ensure that your custom provider is deployed in such a way that each website can access it, and you also need to configure... the ValidatingPassword event Realistically, either approach is perfectly acceptable The event handler was added in the first place because much of the extensibility model in ASP.NET supports event mechanisms and method overrides For example, when you author a page, you are usually hooking events on the page and its contained controls as opposed to overriding methods like OnClick or OnLoad For developers... changing or resetting a password The event handler doesn’t know the difference between a password change and a password reset After an event handler has inspected the password using whatever logic it wants to apply, it can indicate the success of failure of the check via the Cancel property If the custom password strength validation fails, then the event handler must set this property to true If you . identity. You can use the graphical management tools supplied with SQL Server 20 00 and the nonexpress SKUs of SQL Server 20 05 to do this. If you need to grant access to the NETWORK SERVICE account without. object names (that is, tables and stored procedures) using the explicit dbo username:” 4 28 Chapter 11 14_596 985 ch11.qxp 12/ 14 /05 7:51 PM Page 4 28 EXEC dbo.aspnet_Applications_CreateApplication. scenario like IIS6 applica- 421 SqlMembershipProvider 14_596 985 ch11.qxp 12/ 14 /05 7:51 PM Page 421 tion pools? It turns out that when you run ASP. NET (any version of ASP. NET for that matter) on IIS6,

Ngày đăng: 12/08/2014, 23:22

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan