Maximizing.ASP.dot.NET.Real.World.ObjectOriented.Development [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Maximizing.ASP.dot.NET.Real.World.ObjectOriented.Development [Electronic resources] - نسخه متنی

Jeffrey Putz

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Example: Protecting Your Images from Bandwidth Leeching


Let's apply the use of an HttpHandler to a real-world example. Imagine that you're analyzing your server logs, and you find that you have an enormous number of referrals from some site that you don't recognize. You check out the URL of the referrer and discover that some jerk is deep-linking to one of your prize photos of the Grand Canyon. The high-resolution photo is costing you 150kb toward your bandwidth limit on every request. It also demonstrates a high disregard for copyright.

To combat the problem, we'll develop an HttpHandler that checks to see if incoming requests for .jpg files came from your own site, not someone else's. If the referrer is either blank (the URL of the image was entered into a new browser window directly) or from someone else's site (your leeching friend), we'll serve an alternate image indicating that the user should visit your site directly for the photograph.

Listing 8.4 shows the finished class, as well as the web.config settings to make it work.

Listing 8.4. Anti-image leeching HttpHandler

C#


using System;
using System.Web;
public class JpgHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string FileName = context.Server.MapPath(context.Request.FilePath);
if (context.Request.UrlReferrer.Host == null)
{
context.Response.ContentType = "image/JPEG";
context.Response.WriteFile("/no.jpg");
}
else
{
if (context.Request.UrlReferrer.Host.IndexOf("mydomain.com") > 0)
{
context.Response.ContentType = "image/JPEG";
context.Response.WriteFile(FileName);
}
else
{
context.Response.ContentType = "image/JPEG";
context.Response.WriteFile("/no.jpg");
}
}
}
public bool IsReusable
{
get
{ return true; }
}
}

VB.NET


Imports System
Imports System.Web
Public Class JpgHandler
Implements IHttpHandler
Public Sub ProcessRequest(context As HttpContext)
Dim FileName As String = _
context.Server.MapPath(context.Request.FilePath)
If context.Request.UrlReferrer.Host Is Nothing Then
context.Response.ContentType = "image/JPEG"
context.Response.WriteFile("/no.jpg")
Else
If context.Request.UrlReferrer.Host.IndexOf("mydomain.com")_
> 0 Then
context.Response.ContentType = "image/JPEG"
context.Response.WriteFile(FileName)
Else
context.Response.ContentType = "image/JPEG"
context.Response.WriteFile("/no.jpg")
End If
End If
End Sub
Public ReadOnly Property IsReusable() As Boolean
Get
Return True
End Get
End Property
End Class

web.config


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<httpHandlers>
<add verb="*" path="*.jpg" type="JpgHandler, MyDll" />
</httpHandlers>
</system.web>
</configuration>

The first step in our ProcessRequest() method is to identify the file name of the requested image. After we know that, we determine whether the UrlReferrer property of the Response object is null. If it is, that means the request isn't referred by a page on our site, so we set the content type of the response and use the Response object's WriteFile() method to send an image called "/no.jpg."

If there is a referrer, the next step is to determine whether it contains our domain name. If it does, the referral comes from our own site, and it's acceptable for the image to be served. If the referrer doesn't have our domain name, the request came from another site, so we should serve the alternative image.

Regardless, we set the IsReusable property to true because there's no reason why the class instance can't be reused for every request.

This class must be compiled to an assembly, and that assembly should be placed in the /bin folder of the application. You can compile with the command line compilers or in Visual Studio by building the project.

HttpHandlers can also be written in an .ashx file without being compiled, as shown in Listing 8.5, where we construct an image generator used to create a visual security code that helps prevent automated sign-ups in your Web application. The text generated by the images is stored in Session to be used for comparison to the user's input. Figure 8.2 shows the image generated when the page a user is viewing requests the handler.

Listing 8.5. Image generation HttpHandler

C#

[View full width]


<%@ WebHandler Language="C#" Class="RegisterImageHandler" %>
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Web;
using System.Web.SessionState;
public class RegisterImageHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "image/gif";
Bitmap b = new Bitmap(200, 60);
Graphics g = Graphics.FromImage(b);
g.FillRectangle(new SolidBrush(Color.White), 0, 0, 200, 60);
Font font = new Font(FontFamily.GenericSerif, 48, FontStyle.Bold, GraphicsUnit.Pixel);
Random r = new Random();
string letters = "ABCDEFGHIJKLMNPQRSTUVWXYZ";
string letter;
StringBuilder s = new StringBuilder();
for (int x = 0; x < 5; x++)
{
letter = letters.Substring(r.Next(0, letters.Length - 1), 1);
s.Append(letter);
g.DrawString(letter, font, new SolidBrush(Color.Black), x * 38, r.Next(0, 15));
}
Pen linePen = new Pen(new SolidBrush(Color.Black), 2);
for (int x = 0; x < 6; x++)
g.DrawLine(linePen, new Point(r.Next(0, 199), r.Next(0, 59)), new Point(r.Next(0,
199), r.Next(0, 59)));
b.Save(context.Response.OutputStream, ImageFormat.Gif);
context.Session["pfregisterimage"] = s.ToString();
context.Response.End();
}
public bool IsReusable {
get { return true; }
}
}

VB.NET

[View full width]


<%@ WebHandler Language="VB.NET" Class="RegisterImageHandler" %>
Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Text
Imports System.Web
Imports System.Web.SessionState
Public Class RegisterImageHandler
Implements IHttpHandler
Implements IRequiresSessionState
Public Sub ProcessRequest(context As HttpContext)
context.Response.ContentType = "image/gif"
Dim b As New Bitmap(200, 60)
Dim g As Graphics = Graphics.FromImage(b)
g.FillRectangle(New SolidBrush(Color.White), 0, 0, 200, 60)
Dim font As New Font(FontFamily.GenericSerif, 48, FontStyle.Bold, GraphicsUnit.Pixel)
Dim r As New Random()
Dim letters As String = "ABCDEFGHIJKLMNPQRSTUVWXYZ"
Dim letter As String
Dim s As New StringBuilder()
Dim x As Integer
For x = 0 To 4
letter = letters.Substring(r.Next(0, letters.Length - 1), 1)
s.Append(letter)
g.DrawString(letter, font, New SolidBrush(Color.Black), x * 38, r.Next(0, 15))
Next x
Dim linePen As New Pen(New SolidBrush(Color.Black), 2)
Dim x As Integer
For x = 0 To 5
g.DrawLine(linePen, New Point(r.Next(0, 199), r.Next(0, 59)), New Point(r.Next(0,
199), r.Next(0, 59)))
Next x
b.Save(context.Response.OutputStream, ImageFormat.Gif)
context.Session("pfregisterimage") = s.ToString()
context.Response.End()
End Sub
Public ReadOnly Property IsReusable() As Boolean
Get
Return True
End Get
End Property
End Class

HTML in a page calling the handler


<img src=" />

Figure 8.2. Image generated by our handler.5

To place the image generated by this handler in a page, we use good old-fashioned HTML, as shown in the code listing. We start this simple text file with a @WebHandler directive, similar to the way we declare a @Page or @Control directive. We tell ASP.NET the language that we'll use and the name of our class, which must match the name we're about to give it. As with our previous handler, most of the action happens in the ProcessRequest() method. First, the code randomly generates a five-letter string. Then it uses various classes from the Drawing namespace to generate a bitmap based on those letters, randomly staggering the characters and drawing some lines over it to make it less machine readable.Chapter 17, "More Advanced Topics." After we've sent the image to the requesting user, we save the string of random letters to the Session object.

If we were to use this in an application, we might put a text box right below the graphic generated by the handler for the user to type in the letters. On postback of the form, we would compare the user's input with the value saved in Session to confirm that the user is indeed human and not some machine signing up on our site to spam our forums, for example.

HttpHandlers are a sort of endpoint for a request. Sometimes you may want to execute code from other points in an application's lifecycle. For these instances, you may use HttpModules.


/ 146