Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Real - World ASP .NET—Building a Content Management System - StephenR. G. Fraser

.pdf
Скачиваний:
68
Добавлен:
24.05.2014
Размер:
4.59 Mб
Скачать

Listing 11-22: The AutSubmit bnSubmit_Click Method

private void bnSubmit_Click(object sender, System.EventArgs e)

{

content.SetStatus(Convert.ToInt32(dt.Rows[0]["ContentID"]),

Convert.ToInt32(dt.Rows[0]["Version"]),

(Convert.ToInt32(dt.Rows[0]["Status"])== StatusCodes.Creating ?

StatusCodes.Submitted : StatusCodes.Creating));

Response.Redirect("AutList.aspx");

}

Listing 11-23: The Content Database Table Helper SetStatus

public void SetStatus(int ContentID, int Version, int Status)

{

//UPDATE Content

//SET

//

Status

= @Status,

//ModifiedDate = @ModifiedDate

//WHERE ContentID = @ContentID

//AND Version = @Version

SqlCommand Command = new SqlCommand("Content_SetStatus", m_Connection); Command.CommandType = CommandType.StoredProcedure; Command.Parameters.Add(new SqlParameter("@ContentID", SqlDbType.Int)); Command.Parameters.Add(new SqlParameter("@Version", SqlDbType.Int)); Command.Parameters.Add(new SqlParameter("@Status", SqlDbType.Int)); Command.Parameters.Add(new SqlParameter("@ModifiedDate",

SqlDbType.DateTime));

Command.Parameters["@ContentID"].Value

= ContentID;

 

 

 

Command.Parameters["@Version"].Value

= Version;

 

 

 

Command.Parameters["@Status"].Value

= Status;

 

Command.Parameters["@ModifiedDate"].Value = DateTime.Now;

try

{

m_Connection.Open();

Command.ExecuteNonQuery();

}

finally

{

m_Connection.Close();

}

}

Summary

This chapter covered the CURVeS (create, update, remove, view, and submit) of CMS.NET's CMA.

First, it examined how to break a Web page into frames, and then it revisited the XMLdriven NavBar. It also described in some detail how to handle errors. Next, it covered the Content database and then finished up by going over all the functions that make up the first cut at the CMS.NET's CMA.

The next chapter is going to take a look at cookies, authentication, authorization, encryption, and maybe some other big words.

Chapter 12: Cookies, Authentication,

Authorization, and Encryption

Overview

If you are like me, an author having complete control of your Web site gives you the willies. Well, after this chapter, you can rest a little more easily as you start securing CMS.NET.

The first thing you must realize is that there is no such thing as a perfectly secure site. If a computer is connected to a network, someone will eventually figure out a way into the system (if there is some reason to do so). Beating security is a game to some hackers.

They have fun breaking walls of defenses that security teams spent weeks designing and implementing. And as a word to the wise, not all hacking attempts are from the outside. Internal staff members frequently are the root cause of many security breaches.

Security is like an onion. It is made up of layers upon layers. What I am covering in this book is just one layer. Some common layers that will not be covered are Windows NT or Windows 2000 and Internet Information Services (IIS) built-in security; firewalls; secured communications through SSL; and the frequently overlooked secured physical access to the system.

If the information on your site is highly classified, I strongly recommend that you hire a security expert. These people live and dream security. If your site is like many Web sites in which the information is anything but confidential, what I cover here is more than enough. By adding a firewall, implementing Windows NT or Windows 2000 and IIS builtin security, and adding SSL (https://) communications where appropriate, most Web sites should be secure enough.

This chapter does not cover all of the security features provided by .NET. Instead, it covers mostly what is used by CMS.NET.

ASP.NET Web Application Security

ASP.NET security addresses the areas of authentication, authorization, impersonation (the other big word I promised at the end of the preceding chapter), and encryption. Authentication is the process of ensuring that a user is who he says he is. Authentication does not grant access; it just verifies the user's identity. The process of verifying authenticity usually means requesting a username and password from the user. If the username and password match a same combination stored in the system, the user is authenticated.

Authorization is the process of authorizing a user for access. Usually authorization is granted to a user having the correct username or to users who perform the correct role. Impersonation is the process of giving an ASP.NET application the identity or authentication/authorization of a user so that it can execute on the user's behalf in a secured location. Impersonation is usually used if IIS is implemented to authenticate and authorize a user.

Encryption is the process of converting a stream of text into another stream of text that can't be read or deciphered. The most frequent usage of encryption in ASP.NET is for password storage.

CMS.NET Security Structure

Like most Web sites, CMS.NET has areas it wants to restrict from the average user. The approach CMS.NET takes in restricting access is fairly standard:

1.Authenticate the user.

2.Store the authentication so that it doesn't have to be repeated for the current session.

3.Authorize the user based on role or function.

4.Provide access.

Of authentication, authorization, impersonation, and encryption, CMS.NET only uses ASP.NET's authentication and encryption and, in the case of authentication, only partially.

It is true that ASP.NET provides a complete solution for each of these four areas, but I feel the choice of using the web.config file to store all security information is a little too dangerous, and the reliance on IIS for role-based authorization is too cumbersome. Also, CMS.NET has no need for impersonation because each task performed must have an authenticated and authorized user to carry it out.

Figure 12-1 shows CMS.NET's approach to security. A client request is first processed by IIS. How IIS is configured is really of little concern to CMS.NET. In fact, the default settings work just fine.

Figure 12-1: CMS.NET's security flow

After the request makes it through IIS, it is challenged by ASP.NET. If ASP.NET finds

that the request has an authentication cookie attached to it—meaning that the user has

already been authenticated for this session—it bypasses the next few steps and goes directly to authorization.

On the other hand, if no authentication cookie is found, the request is sent to a login form to get enough information for authentication. CMS.NET takes the authentication information and compares it to its database of password-encrypted valid users. If CMS.NET finds that the user is authentic, it then passes the request back to ASP.NET so that it can create an authentication cookie for the next request in the session. If CMS.NET fails to find an account to match the user, the user is denied access.

Because requests are authorized based on the roles of the user, ASP.NET then immediately sends the request back to CMS.NET so that it can be compared to the user's authorized roles. If a user's role matches the needed role for the request, the user's request is allowed to access the desired Web page. Of course, if CMS.NET cannot find a matching role, the user is denied access to the system.

Cookies and Session Objects

Though cookies and session objects in and of themselves are not a security feature, it is important that I cover them at least briefly.

Cookies

Cookies are the primary method for ASP.NET implementation of session state and Web site security.

There is nothing special about cookies. They are just small, often temporary text files that are stored on a client computer. The information stored in a cookie is submitted along with any requests or responses.

Though many people worry about cookies, they are not dangerous. Here's why:

§All cookies have an expiration date. Upon expiration, the browser no longer submits the cookie with the request.

§A cookie is restricted to 2KB in size.

§The browser has a set limit on how much disk space to allocate for cookies. After this allotment is exceeded, older cookies are replaced.

§The storing of cookies on the client machine is handled by the browser and is outside the control of the server from which it originated.

§A Web server can only access cookies it has created itself.

The cookie file is made up of key/value pairs. It is possible to store almost any text in these files. In the case of ASP.NET and security, they contain session state and possibly an authentication certificate.

Because HTTP is stateless, meaning that each transaction it sends to and receives from a Web server is independent of the others, there was a time when Web servers tried to stuff all sorts of session information into cookies. All this did was make the amount of information transferred between client and server that much larger.

ASP.NET has come up with a more elegant solution. As of now, all that needs to be sent as a cookie is an autogenerated session identifying key. All the rest of the session data is then accessed using something called a session object.

To put it bluntly, with ASP.NET, you no longer have to worry about creating session cookies. The only reason to create cookies now is if you want the data stored on the client to persist longer than the current session.

To create a cookie, you create and instance a class called the HttpCookie, containing the key and value. Optionally, you can set the expiration date. Then, you add it to the HTTP Response.

HttpCookie TheAnswerCookie = new HttpCookie("TheAnswer", "42");

// Expire one year from now

DateTime dt = DateTime.Now;

TimeSpan ts = new TimeSpan(365,0,0,0);

TheAnswerCookie.Expires = dt.Add(ts);

Response.Cookies.Add(TheAnswerCookie);

Getting the cookie key and values from a request is only slightly more difficult—as you

have to deal with an array within an array—because a request can have multiple cookies and each cookie can have multiple values. The following code displays the authentication cookie, which was previously discussed, and SessionID.

HttpCookieCollection allCookies = Request.Cookies;

for ( int key = 0; key < allCookies.Count; key++)

{

HttpCookie thisCookie = allCookies[key];

Response.Write("Name: "+ thisCookie.Name.ToString() + "<BR>");

for ( int val = 0; val < thisCookie.Values.Count; val++)

{

Response.Write("Value" + val + ": "+ thisCookie.Values[val] + "<BR>");

}

}

Session Objects

Session objects are very similar in function to cookies. The big difference is that the data is stored on the server and not on the client. This means the session data doesn't have to be sent across the Internet. It also means it can be stored in its native form and doesn't have to be converted continually to text or, in some cases, encrypted text.

This is a godsend to a developer because you really don't have to worry about session state any longer. All the nitty-gritty of maintaining session state is handled behind the scenes by ASP.NET.

Session objects are probably some of the easiest things to code in ASP.NET. They are stored and retrieved using key/value pairs. To store a session object, you simply write the following:

Session["StringKey"] = object;

To retrieve a session object, use the following:

object = (ObjectType) Session["StringKey"];

If the object type is string, the type caste is not needed. The following is a simple example of placing a string and an integer on a session object and then retrieving them again:

int TheAnswer = 42;

Session["UltraSecretPassword"] = "password";

Session["TheAnswer"] = TheAnswer;

...

String pwd = Session["UltraSecretPassword"];

int WhatIsQuestion = (int) Session["TheAnswer"];

Authentication

Authentication is the process of obtaining and verifying the identity of the user requesting access to a restricted part of the Web site. .NET provides three different methods of authenticating users.

Forms Authentication

The process by which users are authenticated is by being challenged for the existence of an authentication cookie. If the cookie is available, authentication succeeds. If it's

missing, the request is redirected to a custom HTML page, which requests a username and password. These are then fed back into the forms authentication process to be authenticated.

Passport Authentication

This is a centralized authentication service provided by Microsoft that allows a single logon.

Windows Authentication

This is the authentication provided by IIS. All authentications are done by IIS, which in turn passes the authenticated identity to ASP.NET for use. This method uses impersonation to allow the ASP.NET application to run.

CMS.NET Authentication Code Updates

CMS.NET uses only a portion of the forms authentication method of authenticating. Basically, it uses ASP.NET to challenge the request for an authentication cookie. If it is found, it forwards the request to CMS.NET for authorization. If it doesn't find the cookie, it forwards the request to CMS.NET to be authenticated. Once authenticated, CMS.NET sends the request back to ASP.NET, which generates an authentication cookie and then sends the request back to CMS.NET for authorization.

Updating web.config

Enabling authentication in ASP.NET requires only the updating of the web.config file. On the other hand, implementing authentication takes a little more effort, as you will find out. The changes to web.config are quite simple (see Listing 12-1). Just change the default

<authentication> element mode attribute of None to the desired authentication method of Windows, Passport, or Forms. In the case of CMS.NET, you changed it to Forms. Then, because you selected forms authentication, you need to add the

<forms> element and provide two attributes: loginUrl, which is the virtual path to the login form page, and name, which is the name assigned to the cookie.

Listing 12-1: Root Directory web.config Authentication Updates

<!-- AUTHENTICATION This section sets the authentication policies of the application. Possible modes are "Windows", "Forms", "Passport" and "None"

-->

<authentication mode="Forms">

<forms loginUrl="login.aspx" name="CMSNETAUTH" /> </authentication>

There are many other options that will not be covered here.

Note I recommend reading the documentation that comes with .NET. It actually provides a fairly thorough explanation of the web.config file. Just look for "ASP.NET Configuration Sections."

Creating Directory-Specific web.config

You would think that now that you have <authentication> enabled, ASP.NET would start to challenge all users for authentication. Well, not quite. If everyone can access a directory, there is no need to authenticate anyone. This is the case with the root directory

of CMS.NET. To have ASP.NET challenge a user, the web.config file must contain

<authorization> elements.

Wait a minute! What happens if you want one area of the Web site to allow all users and another to allow only specific users? How can one web.config file handle this? It can't. You must include a web.config file for each directory for which you want specific user

access. You don't—in fact, you can't —include all elements of the web.config file in a subdirectory. For authentication/authorization, you only need a web.config file that

contains <authorization> elements.

In CMS.NET, you want everybody to have access to the root directory, so you don't add any <authorization> elements in the root directory copy of web.config. On the other hand, you only want specific people to access the administration directory. Listing 12-2 shows how the web.config file should look.

Listing 12-2: Subdirectory-Specific web.config

<?xml version="1.0" encoding="utf-8" ?> <configuration>

<system.web>

<authorization>

<allow roles="Administrator,Author,Editor,Authorizer,Deployer" /> <deny users="?" />

</authorization>

</system.web>

</configuration>

The only element that ASP.NET cares about is the following:

<deny users="?" />

This line means that the directory denies all anonymous users. You can also think of this element as "authenticate everyone."

The element

<allow roles="Administrator,Author,Editor,Authorizer,Deployer" />

does absolutely nothing because window authentication is not enabled. Role-based authorization is only done using Windows authentication.

So, why have it here? CMS.NET has its own version of role-based authentication, and this seems like the correct place to put this entry. Maybe, in the future, forms authentication will have role-based authorization, and you will be able to remove the rolebased code from CMS.NET. CMS.NET's role-based authorization will be covered shortly.

The Login Web Page

You place the login Web page in the root directory so that you can access it without having to worry about authentication or authorization. And, as you can see in Figure 12- 2, the Web page is simply two text boxes and a check box.

Figure 12-2: The login Web page

As you can see in Login.aspx (see Listing 12-3), nothing is new except for a check box intrinsic control that you haven't used until now.

Listing 12-3: The Login Web Page

<form id="login" method="post" runat="server" >

<IMG src="Administration/Images/administration.jpg" >

<HR width="100%" SIZE=1>

<TABLE cellSpacing=1 cellPadding=1 width="95%" border=0>

<TR>

<TD width="25%"></TD>

<TD>

<H2><FONT color=darkslategray>Login</FONT></H2>

<P>

<asp:ValidationSummary id=ValidationSummary1 runat="server"

HeaderText="The following error(s) occurred while login in:">

</asp:ValidationSummary>

</P>

<P>

<asp:Label id=ErrorMsg runat="server" ForeColor="Red"></asp:Label>

</P>

<TABLE cellSpacing=1 cellPadding=5 width=300 border=0>

<TR>

<TD width="15%">

<P align=right><STRONG>Username:</STRONG></P> </TD >

<TD width="85%">

<asp:TextBox id=tbUsername runat="server" Width="100%"> </asp:TextBox>

</TD >

<TD width="2%">

<asp:RequiredFieldValidator id=RequiredFieldValidator1 runat="server" ErrorMessage="You must enter a Username"

Display="Dynamic" ControlToValidate="tbUsername">*

</asp:RequiredFieldValidator>

</TD >

</TR> <TR> <TD>

<P align=right><STRONG>Password:</STRONG></P> </TD >

<TD>

<asp:TextBox id=tbPassword runat="server" Width="100%" TextMode="Password">

</asp:TextBox> </TD >

<TD>

<asp:RequiredFieldValidator id=RequiredFieldValidator2 runat="server" ErrorMessage="You must enter a password"

Display="Dynamic" ControlToValidate="tbPassword">*

</asp:RequiredFieldValidator>

</TD >

</TR> <TR>

<TD colSpan=3> <P align=center>

<asp:CheckBox id=cbPersist runat="server" Text="Save my username and password">

</asp:CheckBox>

</P>

</TD >

</TR> <TR>

<TD colSpan=3> <P align=center>

<asp:Button id=bnLogin runat="server" Text="Login"> </asp:Button>

</P>

</TD >

Соседние файлы в предмете Программирование