© Martin Korneffel, Stuttgart 2005 +++ email: trac@n.zgs.de +++ web: www.s-line.de/homepages/trac
Im IIS können für Request an spezielle URL's benutzerdefinierte HttpHandler registriert werden. Nach der Registrierung wird dann der Request an den Url an den registrierten Handler umgeleitet. Der registrierte Handler ist dann für den Response verantwortlich.
Mittels benutzerdefinierter HttpHandler können z.B. in Datenbanken gespeicherte vom Browser abgerufen werden.
HttpHandler sind Klassen, die die Schnittstelle IHttpHandler implementieren. Die Quelltexte der Klassen sollten im Ordner App_Code abgelegt werden. Die ASP.NET Laufzeit sucht die Assemblys der HttpHandler implizit in diesem Ordner.
namespace DMS { namespace HttpHandler { public class GetImageHttpHnd : IHttpHandler { const string pn_file_id = "@file_id"; const string query = "select img from data.images where file_id = @file_id"; public GetImageHttpHnd() { } #region IHttpHandler Member bool IHttpHandler.IsReusable { get { return true; } } void IHttpHandler.ProcessRequest(HttpContext context) { // Die Bilddaten werden aus der Tabelle data.images ausgelesen. // Diese ordnet einem Guid, genannt file_id ein Bild zu // Querystring: getimg.ashx?file_id=4280D7CA-7565-4a10-A480-936D41FBD6D8 string txt_file_id = context.Request.QueryString["file_id"]; Guid file_id = new Guid(txt_file_id); // Datenbankzugriff vorbereiten DbProviderFactory dbFactory = SqlClientFactory.Instance; DbConnection conn = dbFactory.CreateConnection(); conn.ConnectionString = ConfigurationManager.ConnectionStrings["dmsminConnectionString"].ConnectionString; byte[] img = null; using (conn) { DbCommand cmd = dbFactory.CreateCommand(); cmd.CommandText = query; cmd.CommandType = CommandType.Text; cmd.Connection = conn; DbParameter pFileId = dbFactory.CreateParameter(); pFileId.ParameterName = pn_file_id; pFileId.DbType = DbType.Guid; pFileId.Direction = ParameterDirection.Input; cmd.Parameters.Add(pFileId); // Bilddaten abfragen conn.Open(); cmd.Parameters[0].Value = file_id; SqlDataReader reader = (SqlDataReader)cmd.ExecuteReader(CommandBehavior.SequentialAccess); while (reader.Read()) { // Mime- Type im Response einstellen context.Response.ContentType = "image/jpg"; // Bilddaten in 8040 Byte Paketen aus der DB an den Browser // übertragen System.IO.BinaryReader breader = new System.IO.BinaryReader(reader.GetSqlBytes(0).Stream); System.IO.BinaryWriter bwriter = new System.IO.BinaryWriter(context.Response.OutputStream); byte[] buffer; buffer = breader.ReadBytes(8040); while (buffer.Length == 8040) { bwriter.Write(buffer, 0, buffer.Length); buffer = breader.ReadBytes(8040); } bwriter.Write(buffer, 0, buffer.Length); } // EndWhile conn.Close(); } // EndUsing } // EndProc #endregion } // EndClass } // EndNamespace } // EndNamespace
Jeder beutzerdefinierte HttpHandler muß registriert werden. Dies geschieht über einen Eintrag in der web.config. Im Registrierungseintrag wird ein Url definiert, der dem HttpHandler zugeordnet ist, und auf die Klasse verwiesen, die den HttpHandler implementiert. Beispiel:
Unter dem Url getimg.ashx wird der in DMS.HttpHandler.GetImageHttpHnd implementierte registriert.
<system.web> <!-- Http- Handler registrieren --> <httpHandlers> <add verb="*" path="getimg.ashx" type="DMS.HttpHandler.GetImageHttpHnd"/> </httpHandlers> ... </system.web>
Definition |
|
---|---|
Authtifizierung |
Bezeichnet einen Prozess, bei dem die Anwender einer Webanwendung identifiziert werden |
Definition |
|
---|---|
Authorisierung |
Zuweisung von Rechten an atuhentifizierte Benutzer |
In den meisten Fällen erfolgt der Zugriff auf Webseiten annonym. Der IIS führt für annonyme Zugriffe einen Identitäswechsel durch. Der Zugriff auf die Seiten erfolgt in diesem Fall als Benutzer IUSER_Computername. Die Authorisierung erfolgt schließlich durch NTFS- Rechte
Beim
Identitätswechsel ist der IIS für die Authorisierung
verantwortlich. Das von der Authentifizierung gelieferte
Zugriffstoken wird an ASP.NET übergeben. Ist der
Identitätswechsel in der web.config freigeschaltet, dann erfolgt
der Zugriff aus ASP.NET unter dem im IIS authentifizierten Benutzer.
Ist kein Identitätswechsel freigeschaltet, dann erfolgt der Zugriff aus ASP.NET unter dem Benutzerkonto ASPNET.
Die Authorisierung erfolgt letztendlich über die NTFS- Zugriffsrechte.
<identity impersonate ="[true|false]" userName="[domain\user_name]" <!-- Benutzer, dessen Identität angenommen werden soll --> password="[user_password]"/>
Beispiel:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <identity impersonate="true" userName="DMSuser" password="d10ne" /> </system.web> </configuration>
Im IIS muß der Annonyme Zugriff freigeschaltet sein, damit Benutzer nicht schon von der IIS- Authentifizierung abgewiesen werden.
In der Web.config muß im Element <authorization> ein <deny users="?"/>. Hierdurch wird die Anmeldung annonymer Benutzer unterbunden. Sonst können Anonyme Benutzer ohne Login- Formular auf die Anwendung zugreifen.
Der Zugriff auf jedes Verzeichnis kann durch Web.config in diesem geregelt werden. Die web.config muß dazu ein authorization – Element enthalten.
<!ELEMENT authorization (allow | deny)*> <!ELEMENT allow EMPTY> <ATTLIST allow users CDATA <!-- Enthält Liste von Windows oder Formular- Benutzerkonten oder * = alle Benutzer oder ? = anonyme Benutzer --> roles CDATA <!-- Enthält Liste von Windows- Grupen, die zugreifen dürfen --> verb (GET | POST | HEAD)> <!-- HTTP- Befehle, die von den Benutzern ausführbar sind --> <!ELEMENT deny EMPTY> <ATTLIST deny users CDATA <!-- Enthält Liste von Windows oder Formular- Benutzerkonten oder * = alle Benutzer oder ? = anonyme Benutzer --> roles CDATA <!-- Enthält Liste von Windows- Grupen, die nicht zugreifen dürfen --> verb (GET | POST | HEAD)> <!-- HTTP- Befehle, die von den Benutzern nicht ausführbar sind -->
In Asp.Net 2.0 können Web.config Dateien mittels des Konfigurationstools implizit durch definition von Zugriffsregeln angelegt und in diesen authorization- Elemente implementiert.
Für kleinere Webanwendungen im Internet können die Benutzerkonten zur Authentifizierung vollständig in der Web.config angelegt werden:
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <system.web> <!-- Einrichten der Formularbasierten Authentifizierung --> <authentication mode="Forms"> <!-- Definition des Login- Formulares --> <forms name="MXMXMz" loginUrl="Login.aspx" protection="All"> <!-- Definition der Benutzerkonten --> <credentials passwordFormat="Clear"> <user name="mko" password="aspnet"/> <user name="marina" password="aspnet"/> </credentials> </forms> </authentication> <!-- Definition der Authorisierungen --> <authorization> <!-- Nur mko hat zugriff --> <allow users="mko"/> <allow users="marina"/> <!-- Alle anderen nicht --> <deny users="*" /> </authorization> </system.web> </configuration>
Asp.Net 2.0 wird mit einer auf SQL- Server implementierten Datenbank zu Benutzerverwaltung ausgeliefert. Benutzerkonten können dabei mittels des ASP.NET Konfigurationstool angelegt, und diesen Rechte zugewiesen werden. Diese Datenbankbasierte Benutzerkontenverwaltung wird Membership genannt.
In der machine.config wird die Membership- Benutzerverwaltung konfiguriert über ffolgendes Konfigurationselement:
<system.web> <membership> <providers> <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10" passwordStrengthRegularExpression=".*" /> </providers> </membership> <system.web>
Im Beispiel sind die Attribute connectionStringName und passwordStrengthRegularExpression hervorgehoben. Hintergrund sind Konfigurationsprobleme. Soll z.B. auf einem anderen Datenbankserver als .\SqlExpress die Benutzerdatenbank angelegt werden, dann muß der hier genannte ConnectionString ausgetauscht werden.
In der Grundeinstellung ist dem Attribut passwordStrengthRegularExpression der Wert "" (leere Zeichenkette) zugewiesen. Dadurch ist es nicht möglich, Benutzerkonten anzulegen, da kein Passwort auf diesen Regulären Ausdruck passt. Deshalb ist hie der Wert .* zugewiesen worden, der jedes Passwort zulässt.
Die FormsAuthentication Klasse ist im Namespace System.Web.Security definiert.
void LoginBtn_Click(Object sender, EventArgs e) { if (Page.IsValid) { if (FormsAuthentication.Authenticate(UserName.Text, UserPass.Text)) { FormsAuthentication.RedirectFromLoginPage(UserName.Text, false); } else { Msg.Text = "Invalid Credentials: Please try again"; } } }
Asp.Net 2.0 wurde um Websteuerelemente erweitert, mit denen die Programmierung von Authentifizierung vereinfacht wird.
Ein Anmeldeformulare wird einfach durch den plazieren und Konfigurieren des Login- Websteuerelementes erstellt. Die Anmeldelogik mit FormaAuthetication ist in diesem Steuerelement integriert. Das Anmeldeformular sollte den Namen Login.aspx haben (default).
Mittels des Websteuerelementes LoginStatus kann der aktuelle Anmeldestatus angezeigt werden. Weiter kann über das Formular ein Logoff erfolgen, wobei der Request zu einer Startseite umgeleitet werden kann.
Webbenutzersteuerelemente |
Zusammengesetzte Steuerelemente |
Benutzerdefinierte Steuerelemente |
---|---|---|
|
|
|
Diese Art von selbstprogrammierten Steuerelementen eignet sich für projektspezifische Elemente, die auf mehreren WebForm- Seiten innerhalb eines Projektes eingesetzt werden.
Bsp.: Seitenkopf für DMS- Simpel bestehend aus
<%@Control Language="c#" AutoEventWireup="false" Codebehind="WebFormCommonHeader.ascx.cs" Inherits="DMSsimpel.WebFormCommonHeader" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %> <TABLE id="Table1" cellSpacing="1" cellPadding="1" width="100%" border="0" bgcolor="lavender"> : <td><asp:Label ID="lblWebFormName" Runat="server">Name</td> : </TABLE>
namespace DMSsimpel { : using System.Web.UI.WebControls; using System.Web.UI.HtmlControls; /// <summary> /// Zusammenfassung für WebFormCommonHeader. /// </summary> public class WebFormCommonHeader : System.Web.UI.UserControl { protected System.Web.UI.WebControls.Label lblWebFormName; // Eigenschaften public string title { get { return lblWebFormName.Text; } set { lblWebFormName.Text = value; } } private void Page_Load(object sender, System.EventArgs e) { // Hier Benutzercode zur Seiteninitialisierung einfügen this.lblTime.Text = DateTime.Now.ToShortTimeString(); } : } }
Vor dem Einsatz auf einer Webform muß jedes Steuerelement registriert werden. Dies geschieht mit der Register- Direktive am Anfang der Webseite:
<%@ Register TagPrefix="uc1" TagName="WebFormCommonHeader" Src="WebFormCommonHeader.ascx" %>
<uc1:WebFormCommonHeader id="WebFormCommonHeader1" runat="server">
Die im Browser verwendeten Sprachen werden als ISO639-1 Sprachcode übertragen (z.B. de – Deutschland, es – Spanien).
Namensraum: System.Globalization
Im Server kann die Formatierung von Ausgaben bzw. das Parsen von Eingaben an einen kulturellen Kontext angepasst werden. Dazu ist ein neues Objekt vom Typ CultureInfo anzulegen und der Eigenschaft CurrentCulture des aktuellen Threads zuzuweisen. Dem Kontruktor von CultureInfo ist eine Kombination aus einem ISO639-1 Sprachcode und einem ISO3166 Regionalcode zuzuweisen.
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Laden der Resourcen mit Resourcenmanager.
protected ResourceManager gRes = new ResourceManager("DMSsimpel.res", typeof(search).Assembly);
Laden von Zeichenketten aus den Resourcen:
private void Page_Load(object sender, System.EventArgs e) { // Hier Benutzercode zur Seiteninitialisierung einfügen if(!IsPostBack) { string sLang = Request.UserLanguages[0]; // Kulturumgebung des Threads einstellen Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(sLang); // Durch Setzen der UICulture wird die entsprechende Satellitenassembly // geladen Thread.CurrentThread.CurrentUICulture = new CultureInfo(sLang); // Strings aus der Resourcendatei laden btnSearch.Text = gRes.GetString("search.btnSearch"); } }