}}
public static void Proces3() {
for (int i = 0; i < 10; i++) {
Monitor.Enter(stiva1);
stiva1.Enqueue("text");
Console.WriteLine("Proces3- operatia: {0}", i);
Monitor.Exit(stiva1);
Thread.Sleep(100);
}}
public static void Main() {
Thread t1 = new Thread(new ThreadStart(Proces1));
t1.Start();
Thread t2 = new Thread(new ThreadStart(Proces2));
t2.Start();
Thread t3 = new Thread(new ThreadStart(Proces3));
t3.Start();
t1.Join();t2.Join();t3.Join();
Console.ReadLine();
}}
Salvati fila cu numele Thread4.cs si compilati.
-83-
In exemplul de mai sus,fiecare thread blocheaza stiva,introduce o
valoare si apoi deblocheaza stiva.Cele trei thread-uri au intarzieri
diferite,astfel ca primul dintre ele termina operatiile cu mult in urma
celorlalte doua.Atunci cand doua thread-uri incerca sa acceseze stiva
simultan,cel care ajunge al doilea,trebuie sa astepte pana cand primul
fir elibereaza accesul.
Exista si alte clase destinate pentru sincronizare: Mutex,Interlocked,
AutoResetEvent,ManualResetEvent...etc.Alegerea solutiei de sincronizare
depinde de natura programului.
In principiu,intr-o aplicatie exista un fir de executie principal,
utilizat pentru a controla fluxul de executie al tuturor celorlalte fire
de executie si anume cel care executa functia Main().Pe langa acesta,mai
pot exista unul sau mai multe thread-uri ce executa in background operatii
de intretinere si control si unul sau mai multe fire de executie in care
ruleaza interfata vizuala cu utilizatorul (una sau mai multe ferestre).
Este esentiala eliberarea memoriei,imediat ce firele de executie nu
mai sunt utile.Pentru a forta operatia de "garbage collection" se poate
apela metoda GC.Collect().
EXEMPLU:
using System;
using System.Threading;
using System.Collections.Generic;
class Garbage{
static void Main() {
Garbage.MakeSomeGarbage();
Console.WriteLine(" Total memorie consumata: {0}",
GC.GetTotalMemory(false));
GC.Collect();
Console.WriteLine(" Dupa eliberarea memoriei: {0}",
GC.GetTotalMemory(true));
Console.ReadLine();
}
static void MakeSomeGarbage() {
Array a1 = Array.CreateInstance(typeof(Thread),2000);
for(int i = 2; i < 1900); i++)
{ a1.SetValue(new Thread(MakeSomegarbage),i); }
}}
Salvati fila cu numele Garbage.cs si compilati.
In exemplul de mai sus,se masoara memoria dupa crearea unei arii de
thread-uri goale,si apoi dupa fortarea eliberarii memoriei prin Collect().
Thread-urile multiple creaza impresia de procesare paralela.Modul in
care se organizeaza si sistematizeaza firele paralele de executie,denota
experienta si personalitatea programatorului.Nu se pot formula sfaturi
generale,dar in mod sigur este bine sa alegeti solutiile prin care se
consuma cat mai putina memorie pentru fiecare operatie,iar blocurile mari
de memorie se impart in blocuri cat mai mici.De cele mai multe ori,este
foarte practic ca principalele functii ale programului sa fie impartite
in module.Nu numai ca se grabeste executia,dar modulele vor putea fi
utilizate sau adaptate si pentru alte programe si aplicatii.Daca oferiti
aceste module si altor programatori,este bine sa fie insotite si de o
documentatie cat mai clara si de filele de resurse necesare.
-84-
REFLEXIE
Prin reflexie (reflection) se intelege abilitatea de a putea inspecta
codul programului,in timpul executiei si cea de a putea manipula unele
elemente din program.Aceste abilitati se pot exploata fie pentru a scrie
rutine pentru depanare automata,fie pentru a scrie programe de analiza,de
tip parser.Prin reflexie,se pot:
-crea instante noi ale unui obiect,
-enumera membrii de acelasi fel (acelasi tip de data),ai unui obiect
-executa membrii unui obiect din program
-prelua informatii despre un anumit tip de data
-prelua informatii (metadate) despre un modul executabil
-inspecta atributele unui tip de data
-crea si compila module noi
Clasele specializate pentru acest tip de operatii sunt grupate in:
System.Reflection si System.Reflection.Emit.Principalele clase utilizate
sunt Assembley,Type si Module.
Astfel,pentru a citi metadatele modulului aflat in executie se poate
utiliza metoda Assembley.FullName.
EXEMPLU:
using System;
using System.Reflection;
public class Reflexie {
public static void Main() {
Module[] moduleArray;
moduleArray = Assembley.GetExecutingAssembley().GetModules(false);
Module myModule = moduleArray[0];
Assembly myAssembly = myModule.Assembley;
Console.WriteLine("Modulul curent = {0}.",myAssembly.FullName);
Console.ReadLine();
}
}
Salvati fila cu numele Reflexie1.cs si compilati.
Acest gen de operatie este util in etapa de depanare a unui program,
pentru a identifica ce module sunt incarcate in memorie si ce modul se
afla in executie in momentul unei exceptii,sau al unei erori de executie.
System.Reflection include un numar foarte mare de clase specializate
pentru o anumita operatie.Astfel,doar pentru a culege informatii despre
modulul executabil,exista peste 20 de clase al caror nume incepe cu
Assembley: AssemblyCompanyAttribute,AssemblyFileVersionAttribute...etc.
Alte clase ofera informatii specializate despre membrii clasei: FieldInfo,
MemberInfo,MethodInfo,ParameterInfo etc.Alte clase specializate ofera
date despre procesorul actual: ProcessorArchitecture sau despre locatia
unei resurse: ResourceLocation.
Toate informatiile preluate prin reflexie,pot fi utilizate pentru a
programa bucle de raspuns automat,la anumite situatii ce intervin doar in
etapa de executie a programului.De exemplu,programul poate sa ruleze
module diferite,in functie de arhitectura procesorului utilizat pentru a
rula aplicatia.In alte situatii,se pot programa bucle pentru tratarea
exceptiilor si erorilor generate de un anumit context de executie sau de
o anumita configuratie hardware (depanare automata).
-85-
EXEMPLU:
using System;
using System.Reflection;
public class Reflexie2 {
public int CampDeDate1 = 0;
protected string CampDedate2 = null;
public static void Main(){
FieldInfo[] camp;
Type tip1 = typeof(Reflexie2);
camp = tip1.GetFields(BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Public);
Console.WriteLine("Clasa curenta are urmatoarele campuri de date:");
for(int i = 0; i < camp.Length; i++) {
Console.WriteLine("Nume: {0}",camp[i].Name);
Console.WriteLine("Tip de data: {0}",camp[i].DeclaringType);
Console.WriteLine("Public: ?= {0}",camp[i].IsPublic);
Console.WriteLine("Membru: ?= {0}",camp[i].MemberType);
Console.WriteLine("Tip: {0}",camp[i].FieldType);
Console.WriteLine("IsFamily: ?= {0}",camp[i].IsFamily);
}
Console.ReadLine();
}}
Salvati fila cu numele de Reflexie2.cs si compilati.
In exemplul de mai sus,se returneza campurile de date ale unei clase
si domeniul de vizibiliate.O astfel de operatie este utila pentru a putea
lucra runtime,cu date al caror tip de date este necunoscut,sau pentru a
identifica spatiul de vizibilitate al unei astfel de variabile.
EXEMPLU:
using System;
using System.Reflexion;
[AttributeUsage(System.AttributeTargets.Class,AllowMultiple=true)]
class AtributulMeu : System.Attribute {}
[AtributulMeu,AtributulMeu]
[System.Obsolete("Aceasta clasa este perimata !",true]
class ClasaMea {
public static void Main() {
System.Reflexion.MemberInfo info = typeof(ClasaMea);
Console.WriteLine("Atributele pentru ClasaMea sunt:");
for (int i = 0; i < attributes.Length; i++)
{ Console.WriteLine(attributes[i]); }
Console.ReadLine();
}
}
Salvati fila cu numele Reflexie3.cs si compilati.
In exemplul de mai sus,se citesc atributele asociate clasei ClasaMea.
Acest gen de operatie,poate fi utila in etapa de autodepanare si control
pentru a identifica o exceptie generata de unul dintre atributele clasei
intr-un anumit context de executie.Pentru verificare,se executa clasa
fara atributul respectiv,sau se corecteaza mediul de executie.
-86-
Tot prin reflexie se poate invoca si o metoda a unui tip de data din
program,fara a mai crea o instanta (un obiect).
EXEMPLU:
using System;
using System.Reflection;
class Exemplu {
static void Main(){
Type t = typeof(String);
MethodInfo substr = t.GetMethod("Substring",
new Type[] { typeof(int),typeof(int) }};
Object result =
substr.Invoke("Telefon= 0722-NUMAR",new Object[]{ 9,10});
Console.WriteLine("{0} returned {1}.",substr,result);
Console.ReadLine();
}
}
Salvati fila cu numele Reflexie4.cs si compilati.
In exemplul de mai sus,se invoca metoda Substring(Int32,Int32) pentru
tipul de data string.Se observa in exercitiul de mai sus,obiectul t de tip
Type.Clasa Type este clasa radacina pentru intrega functionalitate a
System.Reflection,iar membrii aceste clase se utilizeaza pentru a obtine
majoritatea informatiilor necesare.(vezi referinta pentru Type)
Clasa Type este o clasa de baza abstracta ce permite implementari
multiple.In timpul executiei,sistemul de operare va crea automat o clasa
derivata din Type,denumita RuntimeType.Aceste clase derivate de tip
Runtime permit doar o impelementare unica per obiect si pot fi incluse in
operatii de comparare.Cu alte cuvinte,obiectele create din clasa Type nu
au identitate decat in momentul executiei.
Clasele System.Reflection pot fi utilizate fara restrictii pentru a
prelua informatii despre membrii publici ai obiectelor din program,dar
necesita o permisiune de tip ReflectionPermission in cazul membrilor
privati si protejati ai obiectelor (adica in cazul membrilor la care
accesul este interzis in mod normal).
System.Reflection.Emit contine o serie de clase destinate pentru a
putea genera module in timpul executiei,sau pentru a putea genera si
metadate in limbaj intermediar Microsoft.Aceste clase se utilizeaza mai
ales pentru a edita comenzi automate pentru compilator,sau pentru a
genera script-uri pentru server.Acest gen de operatii,depasesc nivelul
programatorului incepator si este bine sa fie testate sub observatia unui
programator avansat.Orice eroare inclusa in modulele si script-urile
generate dinamic,nu poate fi identificata sau testata in timp eficient
si poate forma un asa numit "virus informatic".Acest gen de operatii,nu
se recomanda decat pentru programatorii profesionisti.Exemplu: pentru
a seta algoritmul de raspuns al unui server la o anumita situatie din
retea.
In sinteza,reflexia este un procedeu de autoinspectie a codurilor
din program,ca un fel de imagine in oglinda a unei persoane.Este destinata
mai ales pentru programe de analiza,sau verificare si control automat al
mediului de executie.
-87-
SECURITATEA APLICATIILOR
Prin notiunea de securitate a unei aplicatii se intelege siguranta in
exploatare.Siguranta in executie a unei aplicatii nu este o entitate
distincta,ci este doar o componenta a unui context mult mai larg,format
din securitatea sistemului de operare.In cazul calculatoarelor izolate,
notiunile de securitate se rezuma la un minimum de verificari de format
al datelor si la operatii simple pentru managementul memoriei.In cazul
retelelor de calculatoare,probelemele de securitate ale sistemului sunt
cu atat mai mari,cu cat creste complexitatea retelei si numarul de
utilizatori.Din acest motiv,masurile de securitate se pot impartii in
nivele de securitate. Exemple:
1. -masuri valabile pentru un anumit utilizator
2. -masuri valabile pentru un grup de utilizatori
3. -masuri ce afecteaza toti utilizatorii unei anumite unitati
4. -masuri ce afecteaza o anumita aplicatie
5. -masuri ce intereseaza grupuri de aplicatii dintr-o unitate
6. -masuri ce intereseaza grupuri de calculatoare din retea
7. -masuri ce intereseaza administratorii de sistem
... etc.
Nivelele de securitate se pot forma in functie de criteriile de
selectie.Toate masurile de securitate se concretizeaza prin anumite tipuri
de restrictii,selective sau supraselective.Aplicatiile nu castiga nici un
plus de functionalitate,dar se elimina eventualele erori de executie ale
unor utilizatori neavizati,sau se previne scurgerea de informatii utile
spre persoanele neautorizate.Din acest motiv,nu se vor programa seturi de
astfel de masuri,decat atunci cand sunt strict necesare.In mod normal,
aplicatiile de tip "open source",destinate pentru a fi executate pe
unitati de tip monopost,nu necesita nici un fel de masuri speciale de
securizare.In schimb,aplicatiile de tip Web,destinate pentru reteaua
Internet,trebuie sa respecte masurile standard de securizare.Aceste
masuri standardizate,sunt valabile pentru orice limbaj de programare.
Limbajul C# nu adauga nici un fel de masuri speciale sau noi,ci doar
exploateza seturile de clase si intefete oferite de platforma .NET.
Platforma .NET ofera urmatoarele biblioteci de clase specializate:
Security, Security.AccessControl, Security.Authentication, Security.
ExtendedProtection, Security.ExtendedProtection.Configuration, Security.
Cryptography, Security.Cryptography.Pkcs, Security.Cryptography.Xml,
Security.Cryptography.X509Certificates, Security.Permissions, Security.
Policy, Security.Principal si Security.RightsManagement.
Toate aceste biblioteci DLL,contin seturi de resurse ce permit tot
arsenalul de masuri de securitate,de la cele simple,pana la codificarile
complexe.In acest manual nu vor fi prezentate decat cateva exemple
simpliste,de interes general.In mod normal,securitatea de exploatare a
sistemului este asigurata prin firme specializate,ce combina masurile
de tip software,cu cele de tip hardware.Din acest motiv,ori de cate ori
doriti sa securizati o aplicatie,este recomandabil sa apelati la o firma
specializata.Cu atat mai mult,atunci cand aplicatia arhiveaza sau
prelucreaza date cu caracter economic sau secret.Puteti insa implementa si
masuri de securizare personalizate,atunci cand doriti sa limitati accesul
la date pentru utilizatori neautorizati (persoane sau alte calculatoare).
-88-
EXEMPLU: -producatorii de spam-uri,utilizeaza motoare automate de cautare
pentru a identifica si prelua orice adresa e-mail din paginile de tip
HTML,din reteaua Web.Pentru a evita aceste motoare,se pot inlocui toate
adresele e-mail din site cu pictograme in care adresa este scrisa intr-o
resursa de tip grafic (exemplu o imagine editata cu Paint).
Masurile de securitate pot interesa doar un obiect sau o interfata
grafica,sau pot interesa intreaga aplicatie.De exemplu,pentru a securiza
doar un text,sau un fragment de text,se poate utiliza clasa SecureString
din Sistem.Security:
EXEMPLU:
using System;
using System.Security;
public class Exemplu {
public static void Main(){
Console.WriteLine("Introduceti parola:");
string sir1 = Console.ReadLine();
SecureString sec1 = new SecureString();
foreach (char ch in sir1)
sec1.AppendChar(ch);
Console.WriteLine("Textul securizat este: ");
Console.WriteLine(sec1);
Console.WriteLine("Parola desecurizata este: ");
Console.WriteLine(sir1.ToString());
Console.ReadLine();
}}
Salvati fila cu numele Security1.cs si compilati.
O alta clasa frecvent utilizata este PermissionSet() cu ajutorul careia
se pot introduce in mediul de executie diverse permisiuni:
EXEMPLU: using System;
using System.Reflection;
using System.Security.Permissions;
using System.Security;
using System.IO;
using System.Collections;
class ClasaTest {
public static void PermissionSetDemo() {
PermissionSet ps1 = new PermissionSet(PermissionState.None);
Console.WriteLine("Adauga un set de permisiuni: ");
ps1.AddPermision(new EnvironmentPermission(
EnvironmentPermissionAccess.Read,"USERNAME"));
ps1.AddPermision(new EnvironmentPermission(
EnvironmentPermissionAccess.Read,"COMPUTERNAME"));
Console.WriteLine("Numar de permisiuni = " + ps1.Count);
Console.WriteLine("Proprietate SyncRoot = " + ps1.SyncRoot);
}
static void Main(string[] args) {
PermissionSetDemo();
Console.ReadLine();
}}
Salvati fila cu numele Security2.cs si compilati.
-89-
O data introduse in mediul de memorie,aceste permisiuni vor reglementa
accesul la un anumit tip de resurse.In exemplul de mai sus,permit citirea
celor doua variabile: "USERNAME" si respectiv "COMPUTERNAME".
O alta situatie foarte frecventa o reprezita accesul la resurse din
afara aplicatiei,in special la file si fisiere.Pentru aceste operatii,se
pot utiliza clasele din System.Security.AccesControl:
EXEMPLU:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.AccesControl;
namespace ConsoleApplication1 {
class Program{
static string fila1;
static void Main(string[] args){
fila1 = "csc.exe";
try { using (FileStream st1 = new FileStream(fila1,
FileMode.Open, FileAccess.Read))
{ FileSecurity sec1 = st1.GetAccessControl();
foreach (FileSystemAccessRule lege1 in
sec1.GetAccessRules(true,true,
typeof(System.Security.Principal.NTAccount)))
{ Console.WriteLine("{0}{1} acces tip {2} pentru {3}",fila1,
lege1.AccessControlType == AccessControlType.Allao ?
"permite": "blocheaza",lege1.FileSystemRights,
lege1.IdentifyReference.ToString());
}}}
catch { Console.WriteLine("Adresa incorecta !"); }
Console.ReadLine();
}}}
Salvati fila cu numele Security3.cs si compilati.
In exemplul de mai sus,se citesc atributele compilatorului csc.exe
din directorul curent.In mod asemanator,se pot citi sau edita toate
restrictiile de acces la fisier sau fila.Observati ca accesul este
nerestrictionat pentru administratorul de sistem,pentru autoritatea NT si
pentru userul care administreaza unitatea (administrator de sistem).
Prin acest mecanism,se poate restrictiona accesul la unele fisiere,
fie pentru copii,fie pentru persoanele neautorizate.Drepturile de acces
si sau audit al filei,se concretizeaza sub forma unor "legi" (rules)
salvate sub forma de obiecte de tip FileSystemAccesRule.Asemanatoare cu
FileSecurity este clasa FileSystemSecurity destinata pentru a putea
reglementa accesul la filele de tip sistem.
O situatie particulara se intalneste in cazul aplicatiilor de retea
tip Web,in care trebuie sa existe o polita de evidenta prin care se
specifica explicit drepturile de acces la o anumita resursa.Exemplu cel
mai clar,este pentru filele de tip applet,care nu pot avea acces la
resursele sistemului,decat daca exista o polita explicita.Aceasta polita
se poate edita manual,intr-o fila text,se poate edita cu instrumnete
specializate,sau se poate utiliza un obiect de tip System.Policy.
-90-
Daca un astfel de obiect reglementeaza mai multe astfel de reguli de
acces,se poate utiliza un obiect de tip Evidence,pentru a organiza aceste
seturi de legi.
EXEMPLU:
using System;
using System.Collections;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using System.Globalization;
public class ExempluDeEvidenta {
public bool CreateEvidence() {
bool retVal = true;
Evidence ev1 = new Evidence(null);
Console.WriteLine("Se creaza evidenta1: ");
Url url = new Url("http://www.BlogulMeu.com");
Url url2 = new Url("http://www.ZiarulLocal.com");
Url url3 = new Url("http://www.CompaniaMea.com");
ev1.AddHost(url);
ev1.AddHost(url2);
ev1.AddHost(url3);
PrintEvidence(ev1).ToString();
return retVal;
}
public static int PrintEvidence(Evidence myEvidence) {
int p = 0;
Console.WriteLine("Adresele din evidenta sunt: ");
if ( null == MyEvidence) return 0;
IEnumerator list = myEvidence.GetEnumerator();
while (list.MoveNext())
{ Console.WriteLine( list.Current.ToString()); }
return p;
}
public static void Main() {
ExempluDeEvidenta Test = new ExempluDeEvidenta();
bool ret = Test.CreateEvidence();
Console.ReadLine();
}}
Salvati fila cu numele Security4.cs si compilati.
In mod similar,se poate edita dinamic polita de restrictii si sau de
permisiuni,pentru toate resursele din aplicatie,in functie de profilul
userului.
In mod normal,nu se aplica masuri de securitate decat pentru societati
comerciale,comunicatii speciale criptate sau pentru informatiile cu
caracter secret.Masurile de securitate standard din reteaua Web,sunt de
fapt seturi de recomandari,ce pot fi modificate in functie de necesitatile
din viata de zi cu zi.Fiind vorba despre un domeniu destul de sensibil,
este recomandabil sa consultati o firma de specialitate,ori de cate ori
trebuie sa rezolvati sau sa reglementati restrictiile de acces pentru
aplicatii ce urmeza sa ruleze in retea.
-91-
PLATFORMA .NET
Platforma .NET este un produs software,destinat pentru sistemul de
operare Windows,cu scopul de a produce aplicatii de tip Web si XML.Este
un concept radical diferit fata de produsele anterioare,prin faptul ca
utilizeaza un limbaj intermediar,comun pentru toate limbajele compatibile
cu sistemul Windows.Toate aplicatiile,idiferent in ce limbaj au fost
scrise,urmeaza sa fie compilate pentru a genera un executabil ce contine
coduri simbolice denumite generic MSIL (Microsoft intermediate language).
Platforma include si interpretor al acestui limbaj intermediar,denumit
generic CLR (Common Language Runtime),care asigura mediul de executie si
transforma codul intermediar in cod masina.Ca rezultat,modulele editate
in limbaj C# pot fi combinate cu module scrise in Visual Basic sau in
Java#,pentru a forma aplicatii complexe.Cu alte cuvinte,CLR este ca un
fel de executabil,ce deschide o fereastra (un container) in care urmeaza
sa fie citite si interpretate datele ce formeaza aplicatia.Prin acest
mecanism,se construieste in memorie un mediu de executie configurat
Dostları ilə paylaş: |