Upload
turing-club
View
522
Download
1
Embed Size (px)
Citation preview
VBJ 70
Scrivi a
specificando
nell’oggetto della
e-mail:
IN OFFERTAVBJ n. 70
OPPURE
inviaci il coupon
sottostante
al numero di fax
0587/732232
Potrai acquistare
i libri qui riportati con
uno
SCONTOECCEZIONALE
del 10% anche se
acquisti solo un libro
OPPURE
del 20% se acquisti
3 libri
CSS Mastery: Advanced Web Standards Solutions
di A. Budd
Friends of EDISBN 1590596145280 pp - 43,70 €
Agile Software Construction
di J. Hunt
SpringerISBN 1852339446254 pp - 65,47 €
ASP.NET 2.0 Unleasheddi S. Walther
SamsISBN 0672328232
1992 pp + CD - 52,95 €
Building Scalable Web Sites
di C. Henderson
O’ ReillyISBN 0596102356348 pp - 39,99 €
Oracle HTML DB Application Express
di L. Linnemeyer e B.D. Brown
Mc Graw HillISBN 883864456X540 pp - 43,00 €
Windows Forms 2.0 Programming
di C. Sells
Addison WesleyISBN 03212679661292 pp - 52,95 €
IN OFFERTA VBJ 70
E D I T O R I A L E
N. 70 - Luglio/Agosto 2006 VBJ 7
Il significato di “open source”
Oggi ho partecipato a una riunione il cui scopo era decidere quali tecnologie utilizzare per un applicativo di grandi dimensioni per la pubblica amministrazione. Come
spesso accade in questi casi, si era formato quasi naturalmente un gruppo di dotnettiani e uno di javisti. In realtà l’accento non era tanto sui linguaggi ma sulla filosofia di fondo, quindi chiamerò questi ultimi gli opensourciani. Anche se è facile immaginare in quale gruppo mi trovavo io, devo dire che il confronto è stato costruttivo e mi ha permesso di imparare alcune cose che non conoscevo.
La conclusione più interessante, però, non è stato tanto pesare le ragioni dei due gruppi, quanto constatare quanto soggettiva sia la definizione di open source, sia tra i suoi sostenitori che tra i detrattori. C’è chi utilizza questo termine come sinonimo di gratuito, chi per indicare che i programmi open source sono forniti in sorgente, altri ancora per indicare che i fra-mework stessi sono disponibili in sorgente, chi sostiene che i linguaggi open source sono standard e non proprietari, e che sono supportati da una grande comunità di appassionati che hanno sviluppato centinaia di componenti gratuite per tutti i gusti.
Tutto vero. Peccato che anche il .NET Framework sia gratuito e fornito per il 90% in sorgente (con l’iniziativa SSCLI), che il C# sia uno standard ECMA, e che anche per .NET esista una vastissima community che ha prodotto dei piccoli capolavori. Quanto al fatto di fornire i sorgenti con le proprie applicazioni, quella ovviamente è una scelta degli svilup-patori (o è un vincolo contrattuale, come accade spesso con la pubblica amministrazione) che è ovviamente utilizzabile anche con il software .NET (o Delphi, o VB6, ecc.)
Nei fatti, non è affatto semplice definire cosa significhi realmente open source, soprat-tutto se prendiamo in esame le numerose varianti di licenza disponibili in quel mondo. Le cose vanno persino peggio se si considerano le altre componenti che compongono una tipica applicazione, ad esempio il database o i server applicativi. Incredibilmente, a volte mi tocca spiegare che il database Oracle non è affatto gratuito (anzi!), anche se gira su un sistema open source, come del resto non lo è neanche MySql nelle configurazioni in cluster. E viceversa, devo chiarire che Microsoft SQL Server Express non solo è gratuito ma permette anche una migrazione assolutamente indolore verso il SQL Server “vero” quando occorrono migliori prestazioni e scalabilità.
Non voglio essere frainteso. Io sono convinto che il movimento open source ha fatto molto e continuerà a fare moltissimo per il mondo IT. Ad esempio, ha fornito software ai paesi del terzo e quarto mondo, dove una licenza di Windows Server 2003 costa quanto lo stipendio annuale di un impiegato, e ha reso possibile la costruzione di computer da 100$ che contribuiranno in modo determinante alla crescita culturale ed economica di quei paesi.
Ma se davvero vogliamo fare un discorso economico (e non ideologico), dovremmo considerare il Total Cost of Ownership (TCO): una macchina Linux costa meno di un equi-valente sistema Windows, ma la sua installazione e amministrazione richiede esperienze ben più vaste di quelle in possesso di un impiegato “medio” di una azienda “media”. In un mondo dove la manodopera (soprattutto se qualificata) costa tanto, risparmiare sul costo del software è davvero un buon affare come sembra?
Francesco Balena www.dotnet2themax.it/blogs
o n l i n e . i n f o m e d i a . i tn. 70 - luglio/agosto 2006
bimestrale - anno dodicesimo
Direttore Re spon sa bi leMarialetizia Mari ([email protected])
Direttore EsecutivoFran ce sco Balena ([email protected])
Managing EditorRenzo Boni ([email protected])
CollaboratoriRaffaele Di NataleAndrea Ferendeles
Fabio PerronePaolo Pialorsi
Gian Maria RicciJustyn Roberts
Direzione Natale Fino ([email protected])
Marketing & Advertising Segreteria: 0587/736460
AmministrazioneSara Mattei
Grafica([email protected])
Technical BookLisa Vanni ([email protected])
Segreteria Enrica Nassi
StampaTIPOLITOGRAFIA PETRUZZI
Citta’ di Castello (PG)
Ufficio AbbonamentiTel. 0587/736460 - Fax 0587/732232e-mail: [email protected]
www.infomedia.it
Gruppo Editoriale Infomedia srlVia Valdera P., 116 - 56038 Ponsacco (PI) Italia
Tel. 0587/736460 - Fax 0587/[email protected]
Sito Web www.infomedia.it
Manoscritti e foto originali anche se non pub bli ca ti, non si restituiscono. È vietata la ri pro du zio ne
anche parziale di te sti e immagini.
Si prega di inviare i comunicati stampa e gli inviti stampa per
la redazione all’indirizzo: [email protected]
Visual Basic Journal è una rivista diGruppo Editoriale Infomedia S.r.l. Via Valdera P, 116 Ponsacco - Pisa.
Registrazione presso il Tribunale di Pisa n. 20/1999
9
SOMMARIO
N. 70 - Luglio/Agosto 2006 VBJ
N.70L U G L I O / A G O S T O
Editoriale 7
.NET Tools 61
RUBRICHE
11Windows Workflow FoundationI componenti chiave di WinFX, la prossima versione di API managed per Windows
di Paolo Pialorsi
SPECIALE
19CAPermutations: una libreria per risolvere problemi combinatoriRegine, amazzoni e un'introduzione ai problemi combinatori.
di Francesco Balena
.NET Sql Authorization Manager (NetSqlAzMan)Un gestore di applicazioni sviluppate con il .NET Framework 2.0
di Andrea Ferendeles
Generics in C# 2.0L’introduzione della programmazione generica è sicuramente la novità più interessante del .NET 2.0, scopriamone le caratteristiche principali.
di Gian Maria Ricci
Common Time mSuite SecurityLa programmazione orientata ai template enfatizza il riuso non solo dei componenti, ma anche delle loro modalità di utilizzo
di Lorenzo Vandoni
TECNICHE
APPLICATIVI
27
C#
45
MOBILE
52
11N. 70 - Luglio/Agosto 2006 VBJ
.NET 3.0: Windows Workflow Foundation
di Paolo Pialorsi (www.devleap.com)
Continuiamo la serie di articoli dedica-
ti all’introduzione di WinFX, di recente
rinominato .NET 3.0 da parte di Micro-
soft. Come abbiamo già visto nel primo articolo
di questa serie [1], .NET 3.0 è la prossima ver-
sione di API managed per Windows, cioè basa-
te sul .NET Framework di Microsoft, che vedrà
la luce insieme a Windows Vista, ma che funzio-
nerà anche su Windows XP Service Pack 2 e su
Windows Server 2003.
In questo appuntamento concentriamo la nostra
attenzione su Windows Workflow Foundation
(WF), il motore di workflow pensato per gestire,
creare e descrivere flussi applicativi e processi
di business.
Perché WF
Il concetto di workflow in quanto tale è general-
mente noto come flusso operativo/funzionale che
descrive e controlla un processo di business, secon-
do regole e percorsi definiti da un esperto del do-
minio di applicazione. Praticamente ogni giorno,
quando scriviamo il codice delle
nostre applicazioni, definiamo
dei flussi operativi/funzionali
che sono assimilabili a dei work-
flow. Pensiamo a tutti quei casi
in cui farciamo il nostro codice
di costrutti If, While, chiamate
a metodi, a servizi esterni, ecc.
in funzione dei requisiti funzio-
nali che ci vengono indicati dal
progetto in fase di sviluppo. In
realtà alle spalle di quel codice
vi sono ragionamenti, diagram-
mi di flusso e processi :in una
parola, appunto, il “progetto”.
Spesso il problema che deriva
dalla definizione di un proces-
so sotto forma di codice è il fatto
che quello stesso codice, rivisto
magari anche solo alcuni mesi
dopo, se non è opportunamen-
te commentato e documentato
diventa estremamente criptico.
Inoltre a volte il codice che gesti-
sce i flussi funzionali è annega-
to nel codice che gestisce l’inter-
faccia utente. Pensiamo ad una
form nella quale un pulsante o
una textbox devono essere atti-
vati solo se l’utente sceglie una
determinata altra opzione, sem-
Vediamo i componenti chiave di WinFX, la prossima
versione di API managed per Windows.
Paolo Pialorsi, è un consulente e autore specializzato nello
sviluppo di servizi SOA e soluzioni in architettura distribuita
basate sul Framework .NET di Microsoft. Lavora nell’omonima
società Pialorsi Sistemi S.r.l. e fa parte del gruppo DevLeap. Può
essere contattato via email: [email protected]. Mantiene il blog
personale all’indirizzo http://blogs.devleap.com/paolo/.
Windows Workflow Foundation
12 VBJ N. 70 - Liglio/Agosto 2006
preconfezionati e ci darà la possibilità di de-
finirne altri. Noi stessi, come sviluppatori, po-
tremo prevedere all’interno delle nostre ap-
plicazioni il supporto per WF. Avremo quindi
un framework di workflow pervasivo e diffu-
so, che diventerà lo strumento principe per
coordinare i processi aziendali.
System e Human WorkflowIn generale, prescindendo per un momento
da WF, i workflow sono di solito divisi in un
due macro-aree:
• System Workfl ow: descrivono processi di
business che riguardano l’interazione e l’in-
tegrazione tra sistemi. Sono ad esempio tut-
ti quei flussi di scambio dati, o quei processi
batch, che una volta descritti e implementati
non richiedono interazioni dirette da parte di
un utente, se non per configurarli e mandarli
poi in esecuzione. Di solito hanno una durata
pre disponibile nella form. Qualora dovessimo
realizzare un software con interfaccia utente
sia web che Windows, con un approccio orien-
tato al codice, saremmo costretti a descrivere
queste condizioni di abilitazione o disabilita-
zione dell’interfaccia, sia nel codice web che
in quello Windows.
Ecco che uno strumento come Workflow
Foundation ci consente invece di descrive in
forma grafica, attraverso dei designer di cui
poi parleremo, i flussi operativi delle nostre
applicazioni, collegandoli se necessario all’in-
terfaccia utente, potendo però prescindere dal-
la particolare tipologia di strato di presenta-
zione (web, Windows, ecc.).
In questo modo possiamo concentrare dap-
prima la nostra attenzione sul flusso (Figura
3) per poi collegarlo all’eventuale interfaccia
utente applicativa, che diventa solo un detta-
glio rispetto alla logica che sta alla base del
prodotto software.
L’idea forte e vincente di WF è quella di ren-
dere disponibile il motore di workflow nel-
la gran parte dei prodotti software di Micro-
soft. Infatti WF sarà presente in Windows Vi-
sta, sarà installabile su Windows XP Service
Pack 2 e Windows Server 2003. Il prossimo
2007 Microsoft Office system ospiterà WF per
la gestione di workflow documentali. Office
Sharepoint Server 2007 offrirà dei workflow
Windows Workflow Foundation
Fi gu ra 2 I nuovi template di progetto per
Visual Studio e WF
Fi gu ra 1 Architettura di Windows Workflow
Foundadtion
WinFx è un insieme di
librerie managed, per la
gestione delle applicazioni
del domani
13N. 70 - Luglio/Agosto 2006 VBJ
limitata nel tempo e in caso di accesso a basi
dati svolgono per lo più attività atomiche.
• Human Workfl ow: sono flussi funziona-
li che richiedono l’interazione con uno o più
utenti. Generalmente sono molto variabili nel
loro flusso, in funzione delle azioni eseguite
dagli utenti. Hanno una durata eventualmente
anche estesa nel tempo e se coinvolgono delle
basi di dati possono avere l’esigenza di gesti-
re long-running transaction e attività di com-
pensazione in caso di annullamento. Sono ad
esempio processi di approvazione documen-
tale e di gestione/istruttoria di pratica di la-
voro.
Con WF possiamo descrivere entrambe le
casistiche di flussi.
Architettura di WFDal punto di vista architetturale (Figura 1)
WF è pensato per essere estremamente esten-
dibile e personalizzabile, come tutto .NET 3.0.
Dal punto di vista di WF un workflow è co-
stituito da:
• Un insieme di Activity, che sono da
pensare come i singoli mattoncini su cui si
fonda un workflow. Le Activity sono i singo-
li passi di un flusso. Possono essere sia delle
Activity scelte nel set di attività di base (Base
Activity Library), di alcune delle quali parle-
remo meglio più avanti in questo articolo, sia
delle attività custom, create da noi o da terze
parti, arricchendo di funzionalità l’infrastrut-
tura di base di WF.
• Le Activity sono definite all’interno
di un Workflow, che è una tipologia partico-
lare di Activity, in grado di contenerne altre
e che può essere eseguito direttamente.
• I Workflow sono realizzabili dichiaran-
do direttamente del codice, oppure in modo
decisamente più comodo sfruttando appositi
Visual Designer. Esiste ad esempio un’esten-
sione di Visual Studio 2005 per disegnare i
flussi di WF. Anche altri prodotti di Microsoft
offrono dei designer alternativi e che non ri-
chiedono la presenza di Visual Studio 2005.
Ad esempio 2007 Microsoft Office system pre-
vede un designer semplificato di workflow al-
l’interno di SharePoint Designer 2007, l’evo-
luzione dell’attuale FrontPage.
• Una volta definito un Workflow come
insieme di Activity, utilizzando un Visual De-
signer, abbiamo bisogno di un Host che, come
dice il termine, ospiti il Workflow e lo alimen-
ti con eventuali parametri e/o eventi.
• L’Host che ospita il Workflow si appog-
gia ad un motore di esecuzione (Runtime En-
gine) che altro non è se non una classe .NET,
di nome WorkflowRuntime, che si preoccupa
di caricare in memoria i Workflow, eseguen-
doli e gestendone lo stato e la persistenza.
• Il WorkflowRuntime si appoggia a dei
servizi infrastrutturali di base (Runtime Ser-
vice), personalizzabili ed estendibili secondo
le regole di sviluppo OOP. I Runtime Servi-
ce consentono di arricchire di funzionalità il
Runtime, offrendo servizi di persistenza, ge-
Windows Workflow Foundation
Fi gu ra 3 Un esempio di Sequential Workflow
WinFx funzionerà anche su
Windows XP Service Pack
2 e su Windows Server
2003
14 VBJ N. 70 - Liglio/Agosto 2006
stione dello stato, tracking, comunicazione
con l’esterno, ecc.
Workflow e Activity di basePer iniziare ad utilizzare WF è necessario sca-
ricare .NET 3.0 [2] e installarlo insieme alle
estensioni per Visual Studio 2005. Possiamo
definire un nuovo progetto di tipo Workflow
(Figura 2), ad esempio un Sequential Work-
flow, vedremo poi le tipologie di Workflow
definibili. A questo punto troviamo a nostra
disposizione un designer grafico nel qua-
le possiamo trascinare, dalla Toolbox di Vi-
sual Studio 2005, le singole Activity come se
fossero dei controlli di una form. Ogni Acti-
vity è descritta da una specifica simbologia
grafica, sia nella Toolbox che poi nel grafo
del Workflow (Figura 3). Il risultato di que-
sto drag’n’drop di Activity all’interno del no-
stro flusso sarà una classe .NET della quale
potremo personalizzare il comportamento e
le funzionalità. Un Workflow può anche es-
sere definito con un file XML, la cui esten-
sione per WF è XOML. Un file XOML descri-
ve la serializzazione di un oggetto Workflow.
Il vantaggio di poter definire anche dei file
XOML e non solo classi di codice, al di là che
siano state realizzate con il designer grafico o
meno, è che all’occorrenza possiamo pensare
di creare dei nostri designer che producano
i Workflow in formato XOML, per poi compi-
larli con un apposito compilatore (WFC.EXE
= Workflow Compiler).
Come abbiamo già visto, le Activity sono le
unità minime di un Workflow. Nella pratica
un’Activity non è altro che una classe .NET
che deriva, direttamente o indirettamente,
Windows Workflow Foundation
da una classe base definita del framework di
classi di WF e che si chiama System.Workflo
w.ComponentModel.Activity.
Vediamo lo scopo di alcune tra le principali
Activity del motore di base di WF:
• Code: esegue del codice .NET. Si trat-
ta sicuramente dell’Activity più intuitiva per
chi è abituato a scrivere codice. Il rischio del-
la CodeActivity è di creare un Workflow che
poi non è altro che un insieme di poche Co-
deActivity, che alla fine riproducono esatta-
mente il comportamento di un’applicazione
che si poteva tranquillamente scrivere senza
WF. Conviene pensare a questa Activity come
ad un punto di contatto con il mondo “code-
oriented” da utilizzare con parsimonia. Piut-
tosto se abbiamo porzioni di codice da esegui-
re in modo ripetitivo nei nostri flussi, convie-
ne crearsi delle Activity custom e inserire al
loro interno il codice, oppurtunamente para-
metrizzato.
• Delay: come dice il nome, una DelayAc-
tivity sospende il flusso per un tempo impo-
stabile.
• IfElse: rappresenta un costrutto If ... Then ... Else all’interno del flusso e permette
di eseguire delle valutazioni e delle scelte nel
percorso del flusso.
• InvokeWebService: consente di invoca-
re un WebService (SOAP + HTTP) ester-
no, gestendone poi l’input, l’output ed even-
tuali Fault con le relative Activity (WebSer-
viceInput, WebServiceOutput, WebService-
Fault).
• InvokeWorkfl ow: permette di avviare un
Workflow esterno, con la possibilità di attiva-
re processi asincroni.
• Sequence: esegue una sequenza di al-
tre Activity.
• Parallel: parallelizza delle attività o se-
quenze di Activity.
• Replicator: permette di definire un bloc-
co di flusso che sarà poi eseguito N volte, dove
N dipende da come, caso per caso, andremo ad
alimentare il flusso. Si pensi ad un processo
di approvazione con firme multiple. Il concet-
to di approvazione tramite firma sarà descrit-
Un Workflow è un insieme
di Activity eseguite in un
host che si appoggia al
WorkflowRuntime
15N. 70 - Luglio/Agosto 2006 VBJ
to all’interno del Replicator, poi il numero di
firme necessarie sarà un dettaglio di ciascu-
na particolare istanza del flusso. Per ciascun
firmatario sarà eseguito il flusso previsto dal
Replicator.
• While: dal nome si evince che si tratta
di un costrutto iterativo in base ad una con-
dizione, esattamente come un Do ...While.
• CallExternalMethod: invoca un metodo
dell’ambiente di hosting. È utilizzato per con-
sentire al Workflow di chiamare il suo Host,
eventualmente passandogli delle informazio-
ni.
• HandleExternalEvent: si tratta di un’atti-
vità complementare a quella precedente. Pre-
vede la possibilità di sospendere il flusso in
attesa che l’host invochi un evento per sbloc-
carlo e passargli eventualmente delle infor-
mazioni che gli consentano di proseguire nel
processo.
Vi sono altre Activity di base, che per ora
non vedremo, così come esistono già diverse
Activity personalizzate, scaricabili da Internet
[3]. Anche prodotti Microsoft come 2007 Mi-
crosoft Office system e Office SharePoint Ser-
ver 2007 prevedono delle librerie di Activity
personalizzate per la gestione dei documenti
e dei contenuti di Sharepoint.
Tipologie di Workflow in WFIn Workflow Foundation sono definibili due
tipologie di Workflow: Sequential Workflow e
State Machine Workflow.
I Sequential Workflow (Figura 3) si utilizza-
no per descrivere flussi che sono costituiti da
una sequenza nota di Activity. Di solito un Se-
quential Workflow è temporalmente definito
e limitato. Spesso si utilizzano per rappresen-
tare dei System Workflow, in quanto le inte-
razioni tra sistemi sono generalmente note e
definite a priori, così come le eventuali varian-
ti nel flusso. Il più delle volte non richiedono
interazioni con l’utente, anche se non possia-
mo escluderlo in modo assoluto. Da un punto
di vista operativo sono la tipologia più sempli-
ce di Workflow, in quanto prevedono solo la
definizione della sequenza logica di Activity
e di condizioni per attivarle. Per contro sono
flussi poco versatili e poco adatti a subire va-
riazioni eccessive di comportamento.
Gli State Machine Workflow (Figura 4) sono
invece pensati secondo l’idea di macchina a
stati finiti, che probabilmente molti di noi co-
noscono anche solo per averla studiato all’uni-
versità. In sostanza descrivono quei flussi in
cui non è semplice definire un percorso lo-
gico sequenziale ed è invece più immediato
pensare ai possibili stati in cui si può trovare
il “sistema”. Rifacendoci ad un esempio uni-
versalmente comprensibile, dovendo descri-
vere un flusso di gestione ordini, potremmo
trovarci nei seguenti stati:
• Ordine inserito
• Ordine in verifica al reparto vendite
• Ordine in backorder, perché manca
merce a magazzino
• Ordine evaso
• Ordine consegnato
• Ordine annullato
• Ordine completato
Questi sono solo alcuni dei possibili stati di
Windows Workflow Foundation
Fi gu ra 4 Un esempio di State Machine Workflow
16 VBJ N. 70 - Liglio/Agosto 2006
Windows Workflow Foundation
un processo di gestione di un ordine, proba-
bilmente non sono i soli. Un processo che de-
scriva la gestione di un ordine dovrebbe po-
terli gestire tutti, pensando anche al fatto che
possiamo seguire diverse strade per arrivare
agli stessi stati. Ad esempio “Ordine inserito”
è sicuramente lo stato iniziale, così come “Or-
dine completato” è sicuramente lo stato con-
clusivo. Tra questi due stati potremmo però
avere una verifica del reparto vendite che, a
fronte di uno scoperto di fido del cliente, ci
porti nello stato di “Ordine annullato” per poi
considerare chiuso l’ordine (“Ordine Comple-
tato”). Oppure qualora manchi giacenza a ma-
gazzino potremmo portarci nello stato “Ordi-
ne in backorder”, mentre in caso di disponi-
bilità di merce potremmo evaderlo (“Ordine
evaso”), quindi consegnarlo (“Ordine conse-
gnato”) e infine considerarlo concluso (“Ordi-
ne completato”). D’altra parte però, se anche
dovessimo trovarci in “Ordine in backorder”,
poi andremmo comunque in “Ordine evaso”
non appena la merce fosse arrivata a magazzi-
no. Potremmo discutere ore dei possibili stati
di un ordine. Il messaggio che voglio trasmet-
tere è che un flusso di questo tipo è molto va-
riabile nel suo comportamento, ma è certo ri-
spetto a quelli che sono i suoi possibili stati.
Ecco quindi che uno State Machine Workflow
si prefigge di descrivere flussi di questo tipo,
che probabilmente sarebbero eccessivamen-
te articolati per poter essere incasellati in un
Sequential Workflow.
Generalmente uno State Machine Workflow
è guidato da eventi esterni, spesso scatenati
da interattività con utenti (Human Workflow).
Sono di solito processi duraturi nel tempo e
possono richiedere long-running transactions,
con le relative compensation in caso di falli-
mento, qualora richiedano attività di modifica
su basi dati e risorse esterne in genere.
Hosting e Runtime ServiceCome abbiamo già detto relativamente al-
l’architettura di WF, i Workflow devono esse-
re ospitati da un’applicazione Host ed eseguiti
nel WorkflowRuntime, che si appoggia a dei
Runtime Service. L’applicazione Host può es-
sere un qualsiasi software in grado di suppor-
tare il runtime di .NET Framework. Potrebbe
ad esempio essere un’applicazione Windows
Forms, un sito web ASP.NET, un portale Sha-
repoint, un’estensione di Microsoft Office, un
servizio del sistema operativo, ecc. In que-
sto articolo introduttivo ho volutamente evi-
tato di soffermarmi sui dettagli del codice, in
quanto ho preferito trasmettere l’idea e la lo-
gica alla base di WF. Per vedere un esempio
di base di codice di un Host è però sufficien-
te creare un template di progetto Sequential
Workflow Console Application da Visual Stu-
dio 2005 e visualizzare il codice di avvio del-
l’applicazione:
C# - .NET 3.0
using(WorkflowRuntime workflowRuntime =
new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted +=
delegate(object sender, WorkflowCompletedEventArgs e)
{waitHandle.Set();};
workflowRuntime.WorkflowTerminated +=
delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
WorkflowInstance instance =
workflowRuntime.CreateWorkflow(typeof
(WorkflowConsoleApplication1.Workflow1));
instance.Start();
waitHandle.WaitOne();
}
Come si può notare, è sufficiente istanziare
la classe WorkflowRuntime, per poi chieder-
le di creare una WorkflowInstance, a partire
da un Workflow, definito con gli strumenti a
nostra disposizione, per poi avviarla. L’istan-
za di WorkflowRuntime potrà anche essere
configurata ed estesa nel suo comportamen-
to, aggiungendo dei WorkflowRuntimeServi-
ce. Si tratta di oggetti in grado di fornire ser-
17N. 70 - Luglio/Agosto 2006 VBJ
Windows Workflow Foundation
vizi infrastrutturali al contorno del motore di
WF. Ad esempio se abbiamo l’esigenza di per-
sistere lo stato di un Workflow tra un’Activi-
ty e l’altra, pensiamo ad una DelayActivity
o all’attesa di un evento, possiamo utilizzare
un WorkflowPersistenceService che si occu-
perà di gestire il salvataggio dello stato del
flusso. In WF esiste già un SqlWorkflowPer-
sistenceService nativo, che salva lo stato in
SQL Server, per aumentare la scalabilità delle
nostre soluzioni. Se invece dobbiamo traccia-
re i flussi, possiamo utilizzare un Tracking-
Service, come ad esempio il SqlTrackingSer-
vice. In generale esistono diversi servizi al
contorno e possiamo crearne anche di nostri,
con l’obiettivo di supportare e arricchire il fra-
mework di base.
ConclusioniUn quesito abbastanza diffuso, quando si
parla di WF, è che in realtà, almeno in appa-
renza, in casa Microsoft vi sono già servizi che
potrebbero sembrare potenziali concorrenti di
WF, come BizTalk Server e SQL Server Inte-
gration Services (SSIS). In realtà è sbagliato
pensarli come concorrenti di WF. BizTalk Ser-
ver è un servizio server pensato per gestire
soluzioni principalmente message oriented,
orientate all’integrazione tra applicazioni e si-
stemi gestionali/ERP e informativi in genere.
BizTalk descrive nell’Orchestration Designer
dei flussi sequenziali, infatti nella sua prossi-
ma versione dovrebbe appoggiarsi a WF per
farlo, ma questa è solo una minima parte del
lavoro che un BizTalk server può svolgere.
Anche SSIS non è un concorrente di WF, né
tantomeno di BizTalk, infatti SSIS è pensato
per lavorare con i dati, per gestire scambi di
record da una sorgente ad una destinazione.
SSIS e BizTalk poi sono vere e proprie appli-
cazioni o servizi, che sono eseguite in un loro
contesto. WF invece è eseguibile all’interno
di altre applicazioni, anche e principalmen-
te nostre, per consentire a noi di descrivere i
flussi operativi dei nostri processi.
Microsoft .NET 3.0 ad oggi è in versione Beta
2 e l’ultima build disponibile alla data in cui
scrivo questo articolo è di Maggio 2006. Ben-
ché in beta è però scaricabile dal sito di Mi-
crosoft [2] dedicato all’argomento. Inoltre sia
WCF che WF sono in versione GoLive, cioè
possiamo utilizzarli in applicazioni reali, oltre
che per ricerca e sviluppo interno. Consiglio
quindi di scaricare l’ultima build di .NET 3.0
e iniziare a valutare questo nuovo e interes-
sante framework che in parte rivoluzionerà il
modo di scrivere le nostre applicazioni. È an-
che utile fare riferimento al sito specifico di
WF [3] per scaricare esempi, activity custom
e trovare contenuti di vario genere, utili ad
inquadrare meglio questa tecnologia.
Riferimenti[1] Paolo Pialorsi – “WinFx: Windows
Communication Foundation”, VBJ n° 69
[2] http://www.netfx3.com/
[3] http://wf.netfx3.com/
[4] http://www.devleap.com/winfx/
La persistenza dello stato
dei Workflow è garantita
da servizi personalizzabili
del WorkflowRuntime
19N. 70 - Luglio/Agosto 2006 VBJ
CAPermutations: una libreria per risolvere problemi combinatori
di Francesco Balena
D a quando ho potuto mettere le mani su
un computer sono sempre stato affasci-
nato dai problemi combinatori. In prima appros-
simazione, un problema combinatorio prevede la
scelta di una (o più) permutazioni o combinazioni
di N elementi in modo da soddisfare alcuni vinco-
li. È facile intuire che molti problemi si risolvono
solo grazie a tecniche combinatorie:
• La generazione di tutti gli anagrammi di
una parola richiede la generazione di tutte le per-
mutazioni possibili dei suoi caratteri, per poi sce-
gliere tra le parole ottenute quelle di senso com-
piuto
• Un programma per generare sistemi di To-
tocalcio, Lotto, Totip e simili richiedono la gene-
razione di tutte le colonne possibili, da cui vengo-
no poi scelte quelle che soddisfano alcuni requisi-
ti (tipo numero minimo e massimo di segni, ecc.)
• Un programma per determinare l’orario sco-
lastico, oppure più in generale, per stabilire turni
di lavoro richiede di generare tutte le possibili as-
segnazioni (persona,turno) per poi scegliere quel-
le che soddisfano i vincoli impostati dall’utente
• Molti problemi matematici si basano sul-
la generazione di tutte le possibili permutazioni o
combinazioni di N elementi, ad esempio la genera-
zione degli quadrati magici di ordine N oppure la
risoluzione del famoso problema
delle regine (ovvero: come siste-
mare N regine su una scacchie-
ra N*N in modo che nessuna dia
scacco ad un’altra)
• Lo stesso vale per molti
giochi di tipo enigmistico, come
ad esempio il Sodoku oppure le
parole crociate.
• Il problema dello zaino:
abbiamo N oggetti di peso o in-
gombro differenti da trasportare
in uno zaino che ha una capaci-
tà (come peso o volume) massi-
ma pari a un certo valore: quali
oggetti scegliere in modo che la
capacità dello zaino sia sfrutta-
ta al massimo, in modo cioè che
la somma dei volumi o dei pesi
degli oggetti scelti sia la più vi-
cina possibile (ma non superio-
re) alla capacità dello zaino? Se
pensate che invece di uno zaino
avete a che fare con un contai-
ner, vedete che il problema ha
delle implicazioni pratiche non
indifferenti
• Il modo migliore per ta-
Tecniche
Permutazioni
20 VBJ N. 70 - Liglio/Agosto 2006
Una delle cose più intriganti di un problema
combinatorio è il fatto che anche problemi ab-
bastanza semplici richiedono spesso soluzio-
ni complesse dal punto di vista computazio-
nale, e soprattutto richiedono tanto tempo di
CPU a meno di non ottimizzare al meglio l’al-
goritmo. Le possibili permutazioni di 10 og-
getti distinti è pari al fattoriale di 10, ovvero
1*2*3*4*5*6*7*8*9*10 = 3.628.800. Disporre i
numeri 1-16 su una griglia 4x4 per vedere qua-
li combinazioni generano un quadrato magico
(ossia un quadrato in cui la somma lungo le
righe, colonne, e diagonali è costante) richie-
de l’analisi di 20mila miliardi di posizioni, e
così via. Per riuscire a risolvere questi proble-
mi in tempi accettabili si richiede spesso di
ottimizzare il codice al massimo e di trovare
delle tecniche di “potatura” in modo da poter
scartare interi gruppi di soluzioni prima di do-
verle analizzare una a una. Anche in questo
modo, la risoluzione di un quadrato magico
di ordine 5 può richiedere alcuni giorni an-
che sulle CPU più performanti. Per avere una
idea di quante varianti vi siano per questi pro-
blemi combinatorio, date una occhiata al sito
The Combinatorial Object Server [2].
Ogni problema combinatorio è una storia a
sè stante, nel senso che il codice per trovare
le soluzioni di uno schema di Sodoku è molto
diverso dal codice per generare l’orario scola-
stico ottimale o per trovare il tragitto aereo mi-
gliore. D’altra parte, queste applicazioni han-
no anche molti tratti in comune. In particola-
re, la parte che genera le varie permutazioni
o combinazioni di elementi è spesso simile.
Non uguale, ma simile. Quello che cambia in
ciascun caso sono le routine che controllano
se una combinazione è valida o meno, oppu-
re le funzioni che procedono alla “potatura”
degli alberi delle soluzioni. Alla fine ho pen-
sato: perchè non estrapolare l’algoritmo di ge-
nerazione delle combinazioni in modo da po-
terlo riutilizzare in occasioni differenti? Il ri-
sultato è la libreria CAPermutations, ovvero
l’oggetto di questo articolo.
La libreria in questione contiene solo una
gliare sagome bidimensionali da una super-
ficie piana si determina provando i diversi
modi di combinare le varie sagome in modo
da minimizzare il materiale non utilizzato (si
pensi ad esempio al problema di tagliare in
modo ottimale le pelli di una sedia o un di-
vano a partire dal pellame a disposizione ed
evitando i punti in cui il pellame non è uti-
lizzabile o presenta imperfezioni)
• Il percorso ottimale per andare dalla
località A alla località B in trenoo aereo può
essere risolto combinando i vari percorsi in-
termedi, in modo da ridurre la distanza com-
plessiva, il costo complessivo dei biglietti, il
numero delle coincidenze aeree o ferroviarie,
oppure ancora il tempo speso aspettando tali
coincidenze. (Pensate ad esempio a come pre-
notate un viaggio con Expedia.)
• La generazione di permutazioni e com-
binazioni è anche alla base di numerose tec-
niche di “attacco” per scardinare alcuni siste-
mi di sicurezza. Ad esempio, i programmi che
tentano di trovare le password per un sito fun-
zionano combinando le parole in un diziona-
rio che contiene le parole e nomi propri più
comuni.
Potrei continuare con altri esempi, ma credo
che sia chiaro il fatto che le tecniche combi-
natorie possono essere utili in moltissimi casi.
Per saperne di più, non dovete fare altro che
gogglare un po’ su termini come “permuta-
tions” o “combinations” e scoprirete un sac-
co di cose interessanti.
In questi anni ho scritto numerosi program-
mi che richiedevano la generazione di permu-
tazioni o combinazioni di elementi simili. For-
se il primo programma di questo tipo è stato
un generatore di sistemi per il totocalcio che
girava su Sinclair Spectrum. Uno dei più re-
centi è stato il Sodoku Solver [1] che risolve
automaticamente gli schemi di Sodoku più
complessi in qualche frazione di secondo, di-
rettamente dal vostro broswer. Nei vent’anni
intercorsi tra questi due programmi, ho usa-
to tecniche combinatorie per ottimizzare la
soluzione di alcuni problemi come quelli ci-
tati sopra.
Tecniche
21N. 70 - Luglio/Agosto 2006 VBJ
classe, Permutations, che però già in questa
prima versione è in grado di risolvere la mag-
gior parte dei problemi citati in precedenza.
Per i problemi non particolarmente comples-
si, utilizzare questa libreria è davvero sempli-
ce: si crea una istanza della classe e si passa
al costruttore un vettore contenente tutti gli
elementi da permutare, poi si entra in un ci-
clo For Each che permette di enumerare tut-
te le possibili permutazioni. La classe Permu-
tations usa i generics, in modo da accettare
e restituire un array tipizzato contenente gli
elementi che devono essere (o che sono sta-
ti) combinati:
‘ genera le permutazioni dei caratteri A,B,C,D
Dim elements() As Char = {“A”c, “B”c, “C”c, “D”c}
Dim perms As New Permutations(Of Char)(elements)
For Each chars() As Char In perms
‘ crea e visualizza la stringa ottenuta
‘ concatenando i caratteri in the risultato
Console.Write(New String(chars) & “, “)
Next
Il codice C# è altrettanto semplice:
// genera le permutazioni dei caratteri A,B,C,D
char elements[] = {“A”c, “B”c, “C”c, “D”c};
Permutations<Char> permutations = New Permutations<Char>
(elements);
foreach ( char[] chars in perms )
{
// crea e visualizza la stringa ottenuta
// concatenando i caratteri del risultato
Console.Write(new string(chars) + “, “);
}
Ecco il risultato che appare nella finestra di
console, ovvero tutte le possibili permutazioni
degli N elementi forniti in input:
ABCD, ABDC, ACBD, ACDB, ADBC, ADCB, BACD, BADC, BCAD, BCDA, BDAC, BDCA, CABD, CADB, CBAD, CBDA, CDAB, CDBA, DABC, DACB, DBAC, DBCA, DCAB, DCBA,
Invece di un loop For Each potete anche usa-
re il metodo GetAllPermutations, che resti-
tuisce in un colpo solo tutte le pemutazioni.
Poichè ogni permutazione è un vettore di tipo
T (dove T è definito al momento di istanziare
la classe generica Permutations), allora il ri-
sultato di questo metodo è un jagged array
di tipo T, ovvero un vettore dove ciascun ele-
mento è a sua volta un vettore di tipo T.
‘ VB
Dim results()() As Char = perms.GetAllPermutations()
// C#
char[][] results = perms.GetAllPermutations();
La classe Permutations è anche in grado di
determinare le permutazioni di un gruppo di
K elementi presi dall’insieme di N elementi
forniti in input, con K <= N . Per ottenere tali
permutazioni basta passare al costruttore un
secondo argomento, pari al numero K di ele-
menti che devono apparire nel risultato:
‘ genera le permutazioni dei due caratteri scelti tra
‘ i caratteri A,B,C,D
Dim elements() As Char = {“A”c, “B”c, “C”c, “D”c}
Dim perms As New Permutations(Of Char)(elements, 2)
‘ .... per ciascun loop come prima
Ecco il risultato generato dal ciclo:
AB, AC, AD, BA, BC, BD, CA, CB, CD, DA, DB, DC,
La classe Permutations permette di risolvere
una numerosa classe di problemi combinato-
ri e statistici. Ad esempio, se A,B,C,D rappre-
sentano 4 città, l‘insieme delle permutazioni
rappresentano tutti i possibili percorsi che le
uniscono e che non ripassano mai da una di
esse: un programma può facilmente analiz-
zare questi percorsi per trovare quello che
richiede meno tempo o ha un costo minore.
Se invece gli elementi rappresentano possi-
bili azioni – ad esempio, l’azione di sistemare
una pedina su una determinata casella delle
scacchiera – allora l’insieme delle permuta-
zioni permette di stabilire quale sequenza di
azioni tra quelle possibili permette di ottenere
il risultato migliore (ad esempio, vincere una
Tecniche
22 VBJ N. 70 - Liglio/Agosto 2006
partita di tris). È importante notare che il ri-
sultato non conterrà due elementi uguali, il
che è corretto perchè non vogliamo visitare
due volte la stessa città e non possiamo siste-
mare due pedine nella stessa casella.
La classe Permutations permette anche di
generare le combinazioni di K oggetti pre-
si da un universo di N oggetti, come al solito
con K <= N. L’unica differenza tra permuta-
zioni e combinazioni è che con queste ulti-
me l’ordine è ininfluente, quindi ad esempio
la soluzione ABC è considerata equivalente a
ACB, BAC, BCA, CAB, e CBA perchè quello
che conta sono gli elementi che compaiono
nel risultato e non il loro ordine. Le combina-
zioni permettono di risolvere tipi di problemi
differenti da quelli visti finora. Per esempio,
le combinazioni degli elementi {Giuseppe,Fra
ncesco,Marco,Piero,Gianni,MariaTeresa} con
K=2 potrebbero servire per generare il calen-
dario della prima serie di partite di un torneo
di tennis a cui partecipano sei membri del
team di Code Architects, in modo che ciascu-
na persona si batta una volta contro tutte le
altre. In questo caso occorre usare le combi-
nazioni perchè non occorre disputare la par-
tita Francesco-Giuseppe se si è già giocata la
partita Giuseppe-Francesco. (In altre parole,
l’ordine degli elementi è ininfluente.)
Per generare combinazioni anzichè permu-
tazioni, è sufficiente passare un valore enu-
merativo PermutationKind come terzo ar-
gomento al costruttore della classe Permu-
tations. Ecco ad esempio come generare le
partite del torneo:
Dim elements() As String = {“Giuseppe”, “Francesco”,
“Marco”, “Piero”, “Gianni”, “MariaTeresa”}
Dim perms As New Permutations(Of String)(elements, 2, _
PermutationKind.Combination )
‘ anzichè PermutationKind.Permutations
For Each elem() As String In perms
‘ ciascun elemento del risultato è un array
‘ con due elementi
Console.WriteLine(“{0} - {1}”, elem(0), elem(1))
Next
Tecniche
Ed ecco il risultato che appare nella conso-
le window.
Giuseppe - FrancescoGiuseppe - MarcoGiuseppe - PieroGiuseppe - GianniGiuseppe - MariaTeresaFrancesco - MarcoFrancesco - PieroFrancesco - GianniFrancesco - MariaTeresaMarco - PieroMarco - GianniMarco - MariaTeresaPiero - GianniPiero - MariaTeresaGianni – MariaTeresa
Fin qui niente di particolarmente eccitan-
te, visto che è facile ottenere lo stesso risul-
tato con qualche ciclo innestato di C# o VB,
soprattutto se i valori di K e N sono costanti.
Con K o N variabili occorre prevedere degli
array che gestiscono gli indici dei vari loop,
ma è un codice alla portata di tutti.
Le cose cominciano a diventare interessan-
ti quando l’insieme degli elementi contiene
elementi uguali, che non possono quindi es-
sere considerati distinti quando si generano
le permutazioni o le combinazioni. L’esempio
classico è la generazione di anagrammi: il nu-
mero totale di anagrammi della parola “case”
è 23, dato dal numero di pemutazioni possi-
bili di 4 lettere (=1*2*3*4) meno uno per evi-
tare di conteggiare la parola originale. D’al-
tra parte, il numero di anagrammi della pa-
rola “casa” è soltanto 11, perchè la parola ori-
ginale contiene due lettere uguali e quindi il
numero di permutazioni distinte che è pos-
sibile creare è pari a 12, non 24. Questo par-
ticolare inizia a complicare non poco la strut-
tura di un programma C# o VB che risolve
il problema specifico, ma la classe Permuta-
tions rimuove automaticamente le ripetizio-
ni dal risultato (Figura 1).
Ecco il codice nell’evento Click nel pulsante
23N. 70 - Luglio/Agosto 2006 VBJ
“Show anagrams” del programma demo:
‘ si prepara a generare le permutazioni dei caratteri
‘ della parola
Dim chars() As Char = txtWords.Text.ToCharArray()
Dim permutations As New Permutations(Of Char)(chars)
lstAnagrams.Items.Clear()
For Each chrs() As Char In permutations
Dim anagram As String = New String(chrs)
‘ nel risultato non include la parola originale
If anagram <> txtWords.Text Then _
lstAnagrams.Items.Add(anagram)
Next
lblMessage.Text = String.Format(“Found {0} anagrams”, _
lstAnagrams.Items.Count)
Come ho fatto notare prima, nella maggior
parte dei casi quando chiediamo le permuta-
zioni o combinazioni di un gruppo di elementi
non vogliamo che lo stesso elemento compaia
più volte. Ad esempio, se un elemento rappre-
senta la posizione di una regina posta sulla
scacchiera, l’elemento non può comparire più
di una volta perchè una casella non può con-
tenere più pezzi. Altri problemi combinato-
ri però non hanno questa limitazione. Se ad
esempio stiamo calcolando tutte le possibili
permutazioni di due dadi, dovremo includere
anche i risultati in cui vi sia un doppio uno,
un doppio due, ecc. Per ottenere questo risul-
tato occorre specificare un valore maggiore di
1 come quarto argomento del costruttore del-
la classe Permutations:
‘ ricava le possibili permutazioni di due dadi
Dim elements() As Integer = {1, 2, 3, 4, 5, 6}
‘ passiamo 2 come quarto argomento potendo accettare
‘ che lo stesso valore appaia due volte
Dim perms As New Permutations(Of Integer)(elements, 2, _
PermutationKind.Permutations , 2)
For Each dice() As Integer In perms
Console.WriteLine(“{0} {1}”, dice(0), dice(1))
Next
In una prima versione della libreria avevo
usato un booleano per indicare se le ripetizio-
ni erano ammesse o meno, ma usare un inte-
ro ha il vantaggio di permettere una maggiore
flessibilità. Ad esempio, è possibile generare
tutte le permutazioni di tre dadi in cui lo stes-
so valore compare al massimo due volte:
Dim perms As New Permutations(Of Integer)(elements, 3, _
PermutationKind.Permutations, 2)
Criteri di selezione
La feature più potente della libreria CAPer-
mutations è la possibilità di impostare dei cri-
teri di selezione delle varie permutazioni. In
pratica, è possibile fornire alla libreria l’indi-
rizzo di un metodo di callback: questo meto-
do viene chiamato mentre viene generata una
nuova permutazione, e quindi il programma
client ha la possibilità di scartare le permu-
tazioni che non interessano. La cosa interes-
sante è che la routine di callback viene chia-
mata non soltanto quando la permutazione
è stata completata, ma anche durante le fasi
intermedie. Supponiamo ad esempio di voler
calcolare le permutazioni dei numeri 1-9 ma
con la condizione che il numero N non si tro-
vi in posizione N-esima. Ovviamente possia-
mo generare le 9! permutazioni dei numeri in
questione e poi scartare quelli che non soddi-
sfano la condizione, ma il metodo di callback
permette di accelerare notevolmente i tempi
di elaborazione: infatti non ha senso prova-
Tecniche
Fi gu ra 1 Il generatore di anagrammi in azione
24 VBJ N. 70 - Liglio/Agosto 2006
Tecniche
re per poi scartare i milioni di permutazioni
che presentano la cifra 1 al primo posto, ma
è molto più efficiente dire “non farlo!” nel
momento il cui la classe Permutations prova
a generare la prima permutazione errata, di-
cendole in pratica di saltare tutte le permu-
tazioni di quel tipo.
Ecco un programma Visual Basic che
risolve il problema delle permutazioni di
questo tipo:
Sub GeneratePermutations()
‘ genera le permutazioni delle cifre 1-5
Dim elements() As Integer = {1, 2, 3, 4, 5}
Dim permutations As New Permutations(Of Integer) _
(elements, 5, PermutationKind.Permutations, 1, _
AddressOf PermutationFilter)
For Each perm() As Integer In permutations
Dim sb As New System.Text.StringBuilder
For Each n As Integer In perm
sb.Append(n)
Next
Console.WriteLine(sb.ToString)
Next
End Sub
Private Function PermutationFilter( _
ByVal permutation() As Integer, _
ByVal level As Integer, _
ByVal backtracking As Boolean) As PermutationResult
‘ l’elemento appena aggiunto
Dim number As Integer = permutation(level)
‘ esegue il backtracking se l’elemento non è
‘ uguale alla sua posizione
If number <> (level + 1) Then
Return PermutationResult.Proceed
Else
Return PermutationResult.Backtrack
End Function
La procedura di callback, detta anche proce-
dura di filtro, accetta tre argomenti e restitui-
sce un enumerativo PermutationResult. Il pri-
mo argomento è il vettore che rappresenta la
permutazione che è stata costruita fino a quel
momento; il secondo argomento rappresenta
il livello di costruzione della permutazione,
ovvero l’indice zero-based dell’elemento che
è stato appena aggiunto prima di chiamare il
metodo di callback. Il terzo argomento è Fal-
se se la permutazione è stata costruita, True
se siamo in fase di backtrack (vedi dopo). Il
metodo deve restituire PermutationResult.P
roceed se la permutazione può essere accet-
tata, Permutation-Result.Backtrack se deve
essere scartata.
La possibilità di effettuare backtracking, ov-
vero di tornare indietro sui propri passi se il
metodo di callback restituisce PermutationRe
sult.Backtrack, aumenta enormemente il po-
tenziale della libreria e le permette di risol-
vere problemi combinatori molto complessi.
Ecco ad esempio una classe che risolve il fa-
moso problema delle regine, ovvero come si-
stemare N regine su una scacchiera N*N in
modo che non si diano scacco a vicenda. Si
tratta di un classico problema combinatorio
su cui, prima dell’avvento dei computer, si
sono arrovellati dei geni come Gauss e altri
famosi matematici.
Questo problema corrisponde a trovare una
permutazione dei numeri 1-N, dove ogni ele-
mento P(n) della permutazione rappresenta
la colonna in cui posizionare la regina della
riga N. Il solo fatto di richiedere permutazio-
ni delle cifre 1-N (dove ogni elemento della
permutazioni può apparire una sola volta) as-
sicura che le regine si trovino su colonne ol-
Fi gu ra 2 Ricerca delle soluzioni per il problema delle
regine (e delle amazzoni)
25N. 70 - Luglio/Agosto 2006 VBJ
Tecniche
tre che su righe separate. Di fatto quindi, il
metodo di callback deve soltanto tenere trac-
cia di quali diagonali (principali e secondarie,
ovvero quelle in direzione NO-SE e quelle in
direzione NE-SO) sono occupate dalle regine
poste sulla scacchiera fino a quel momento.
Nel Listato 1 è riportato il codice C# di una
classe che calcola tutte le soluzioni del pro-
blema, con N qualsiasi.
Poichè la procedura di filtro deve gestire gli
array di booleani mainDiags e secDiags (che
contengono true se la diagonale corrispondente
è stata già occupata), la stessa routine deve
anche rimettere i valori a false quando – in
fase di backtracking – la regina viene rimossa
da quella posizione per tentare un’altra
strada. Ecco allora che si spiegano le seguenti
istruzioni :
// se backtracking, aggiorna i valori e ritorna
if ( backtracking )
{
mainDiags[mainDiag] = false;
secDiags[secDiag] = false;
return PermutationResult.Backtrack;
}
Con qualche piccola aggiunta alla
procedura di callback è anche possibile
risolvere il problema delle amazzoni (o
delle super-regine) dove una amazzone è
una regina con super-poteri che è anche in
grado di muoversi come un cavallo. Queste
sono le sole righe che occorre aggiungere
nel punto segnato da un commento nel
listato della classe:
// ulteriori test per il problema delle amazzoni
if ( Kind == ProblemKind.Amazons )
{
// controlla le celle della riga precedente
if ( row > 0 && ( columns[row - 1] == col - 2
|| columns[row - 1] == col + 2 ) )
return PermutationResult.Backtrack;
// controlla le celle di due righe prima
if ( row > 1 && ( columns[row - 2] == col - 1
|| columns[row - 2] == col + 1 ) )
return PermutationResult.Backtrack;
}
Ho preparato un programma che permette
di risolvere il problema delle regine e delle
amazzoni con N compreso tra 4 e 20 (Figura
2). In aggiunta alle feature appena descritte,
il programma è anche in grado di scartare le
riflessioni e le rotazioni, per ottenere quelle
che si definiscono le soluzioni base del pro-
blema. Grazie alla classe Permutations, con
una manciata di istruzioni è stato possibile
risolvere un problema combinatorio davvero
complesso. E il tutto in modo super-efficien-
te: sul mio computer il problema delle regine
di ordine 12 è risolto in circa 1.5 secondi, per
trovare tutte le 1787 soluzioni base.
Al solito, il sorgente del programma è alle-
gato all’articolo.
Una ultima, importante nota: questa
versione della libreria CAPermutations
è disponibile come DLL compilata e
può essere usata esclusivamente nei
programmi freeware o no-profit. Se avete
dubbi su questa forma di licenza o se avete
la necessità di utilizzarla in applicazioni
commerciali, contattatemi via email.
Riferimenti
[1] http://www.dotnet2themax.it/sodoku/
default.aspx
[2] http://www.theory.cs.uvic.ca/~cos/
root.html
26 VBJ N. 70 - Liglio/Agosto 2006
Tecniche
Li sta to 1 Il codice per il problema delle regine
using System;using System.Collections;using System.Collections.Generic;
namespace CodeArchitects{ public class Queens : IEnumerable { // campi di input public readonly int Side; // campi utilizzati dal metodo filtro bool[] mainDiags; bool[] secDiags;
// costruttore
public Queens(int side) { this.Side = side; }
// il metodo enumeratore delega // all’enumeratore della classe // Permutations
public IEnumerator GetEnumerator() { Permutations<int> permutations = CreatePermutationObject(); return permutations.GetEnumerator(); }
// metodo di supporto che inizializza // e restituisce un oggetto Permutations // da utilizzare per l’enumerazione dei // quedrati
private Permutations<int> CreatePermutationObject() { // inizializza il vettore permutazione // con numeri nell’intervallo 1-N int[] numbers = new int[Side]; for ( int i = 0; i < Side; i++ ) numbers[i] = i; // inizializza i campi utilizzati dal // metodo filtro mainDiags = new bool[Side * 2 + 1]; secDiags = new bool[Side * 2 + 1]; // crea e restituisce // l’oggetto Permutations return new Permutations<int>
(numbers, Side, PermutationKind.Permutations, 1, Filter); }
// il metodo filtro viene invocato quando // viene aggiunta o rimossa una nuova // regina dalla scacchiera
PermutationResult Filter(int[] columns, int row, bool backtracking) { // la colonna della regina appena // aggiunta alla riga int col = columns[row]; // le diagonali utilizzate // da questa regina int mainDiag = row - col + Side; int secDiag = row + col; // se backtracking, aggiorna // i valori e ritorna if ( backtracking ) { mainDiags[mainDiag] = false; secDiags[secDiag] = false; return PermutationResult.Backtrack; }
// controlla se le diagonali sono // già occupate da un’ulteriore regina if ( mainDiags[mainDiag] || secDiags[secDiag] ) return PermutationResult.Backtrack;
// ( ... aggiungere qui il codice del // problema delle amazzoni)
// se arriva qui, contrassegna le // diagonali come “prese” mainDiags[mainDiag] = true; secDiags[secDiag] = true; // segnala che la nuova // permutazione è ok return PermutationResult.Proceed; } }}
27N. 70 - Luglio/Agosto 2006 VBJ
.NET SqlAuthorization Manager(NetSqlAzMan)
di Andrea Ferendeles
NetSqlAzMan è rivolto a tutti gli svi-
luppatori Microsoft .NET 2.0 che ne-
cessitano di gestire autorizzazioni ap-
plicative loosely-coupled, cioè debolmente ac-
coppiate con il codice sorgente, in modo velo-
ce e snello avendo queste autorizzazioni sem-
pre a disposizione in un database relazionale
come MS Sql Server (2000/MSDE/2005/Express).
Chi di voi già conosce MS Authorization Manager
(AzMan) oppure ADAM (Active Directory Applica-
tion Mode) allora è nel posto giusto… ma aspetta-
tevi tante novità.
NetSqlAzMan è un progetto open source ed
è ospitato dalla community SourceForge.net.
Da questo link è possibile scaricare sia i sorgen-
ti (C#.net) sia il pacchetto di installazione (.MSI)
per la piattaforma Win32: http://netsqlazman.sour-
ceforge.net.
Sicurezza nelle applicazioni
Quando si parla di sicurezza
applicativa è possibile in gene-
re scrivere simbolicamente la se-
guente equazione:
{ Sicurezza } = { Autenticazione }
+ { Autorizzazione }
dove per Autenticazione si in-
tende la fase di verifica delle cre-
denziali (chi sei?) e per Autoriz-
zazione, il momento in cui, ac-
certata l’identità dell’utente, si
guarda a cosa questo utente può
o non può fare. In genere la fase
di autenticazione avviene prima
di tutte ed è sufficiente accerta-
re una sola volta le credenziali
dell’utente senza poi ogni volta
(a run-time) ripetere tale opera-
zione (pensiamo al momento del
“logon” sul nostro PC).
La seconda fase dà per scontato
che qualcuno abbia già procedu-
to alla verifica delle credenziali e
Il nome è pittoresco ma non si tratta né di un super-eroe,
né di un dentifricio raccomandato dai migliori dentisti
italiani. È un gestore di autorizzazioni per applicazioni
sviluppate con il .NET Framework 2.0 (smart-client/
web).
Andrea Ferendeles, si occupa da diversi anni di sviluppo,
progettazione software e basi dati su tecnologia Microsoft.
È attualmente alle dipendenze della società Eidos Sistemi di
Formazione e collabora con Microsoft Italia per la gestione del
Microsoft eGovernment Competence Center per la Pubblica
Amministrazione. Ha partecipato come speaker a conferenze
tecniche come TeckTalk 2004 tenendo sessioni su tematiche
legate all’accesso dati avanzato con Sql Server e .NET e alla
realizzazione di servizi Windows con .NET. È certificato MCT,
MSF, MCSD e MCDBA. Può essere contattato tramite e-mail
all’indirizzo [email protected].
APPLICATIVI
NetSqlAzMan
28 VBJ N. 70 - Liglio/Agosto 2006
ed alcuni “Ruoli Applicativi” ovvero gruppi
di persone che nell’Applicazione posso com-
piere le medesime operazioni. Supponiamo
che l’applicazione che stiamo scrivendo deb-
ba avere funzioni di gestione della contabilità
aziendale, del magazzino e così via, insomma
il classico gestionale.
L’applicazione dovrà operare delle distinzioni
e permettere determinate operazioni ad utenti
ben specificati, mentre ad altri le stesse ope-
razioni dovranno essere negate. Per esempio
consideriamo l’operazione “visualizza - bilan-
cio di fine anno” che riporta in dettaglio i co-
sti ed i ricavi di un anno di attività. È ragione-
vole dire che tale operazione deve esser con-
cessa solo all’amministratore dell’azienda e al
più ai suoi dirigenti, ma sicuramente non agli
impiegati. È inoltre ragionevole pensare che
spesso l’amministratore od uno dei suoi diri-
genti, per pura pigrizia o mancanza di tempo,
vogliano “delegare” questa operazione ad una
segretaria, ovvero concederle (magari tempo-
raneamente) il permesso di compiere tale ope-
razione in loro vece.
Ora, come si può realizzare un’applicazione
del genere, senza “cablare” nel codice istru-
zioni del tipo:
If (utente = “Mario” or utente = “Giuseppe”) then
(autorizzato)
Else
(non autorizzato)
In primo luogo dobbiamo cercare di astrarre
il più possibile dal concetto di “singolo uten-
te” e passare invece al concetto di “gruppo di
utenti” ovvero un insieme di utenti a cui que-
sta operazione verrà concessa. All’atto poi del
disegno fisico decideremo quali utenti appar-
tengono a quale gruppo:
If (utente appartiene al gruppo “Amministratori”) then
(autorizzato)
Else
(non autorizzato)
che quindi l’identità dell’utente sia “accerta-
ta” e “nota”. A questo punto, di fronte alla ri-
chiesta dell’utente di una applicazione, di ese-
guire una determinata operazione, il sistema
di Autorizzazioni fornisce una risposta, prele-
vando tutte le informazioni necessarie a pren-
dere tale decisione da una qualche fonte dati
(ad esempio le ACL del File System).
Volendo a tutti costi fare un esempio, basta
pensare a quando ci rechiamo in aeroporto
per prendere un aereo.
Quando ci presentiamo al Check-In, ci vie-
ne chiesto biglietto aereo e documento d’iden-
tità e ci viene rilasciato un “ticket” di sicu-
rezza che è costituito dalla “carta d’imbarco”
(Autenticazione). A questo punto, e solo dopo
aver ritirato la carta d’imbarco, possiamo re-
carci all’uscita preposta per il nostro volo. Al-
l’interno della zona d’imbarco però, non sare-
mo “autorizzati” a prendere un volo qualsia-
si ma solo ed esclusivamente il volo indicato
nella carta d’imbarco stessa; tale controllo si
esaurisce al momento dell’imbarco (Autoriz-
zazione) e solo dietro presentazione del “tic-
ket” rilasciato durante il check-in. Mi scuso
se l’esempio è risultato banale ma è bene fare
chiarezza, almeno in questo contesto, per ca-
pire esattamente in quale contesto NetSqlAz-
Man si colloca.
Ed eccoci dunque al punto: NetSqlAzMan è
proprio colui che conserverà e custodirà le au-
torizzazioni, dando risposta “si, sei autorizza-
to” oppure “no, non sei autorizzato” a chiun-
que ne faccia richiesta (le applicazioni). Net-
SqlAzMan si appoggia invece al sistema ope-
rativo MS Windows per espletare la fase di
autenticazione (Kerberos / NTLM).
Cerchiamo ora di capire, con un esempio
concreto, il meccanismo delle autorizzazio-
ni in un contesto applicativo. Immaginiamo
una applicazione gestionale di una Azienda
qualunque. All’interno di questa Azienda pos-
siamo sicuramente identificare alcuni “Ruoli
Aziendali” come ad esempio: l’amministrato-
re, i dirigenti, le segretarie, gli impiegati, ecc.
APPLICATIVI
29N. 70 - Luglio/Agosto 2006 VBJ
Così facendo però stiamo introducendo un
legame troppo forte tra i “gruppi” e ciò che i
gruppi stessi “possono fare”. Cosa accadreb-
be infatti se domani decidessimo di passare
di competenza una certa operazione da un
gruppo ad un altro?
Proviamo allora ad operare un ulteriore pro-
cesso di disaccoppiamento e dire:
If (utente è autorizzato a compiere l’operazione X) then
(autorizzato)
Else
(non autorizzato)
Siamo passati in questo modo a fare la cosa
più semplice e naturale e cioè a chiederci, a
prescindere dal nome ed a prescindere dal
gruppo/ruolo di appartenenza, se quell’uten-
te può fare o no quella determinata opera-
zione. L’unico elemento di collegamento tra
l’applicazione e il repository delle autorizza-
zioni, è il nome dell’operazione stessa. L’in-
sieme di tali nomi definisce “un contratto”
e, come tale, è vincolante; se si cambia o nel-
l’applicazione o nel repository anche il nome
di una sola operazione sarà necessario modi-
ficare l’altro/a di riflesso.
L’identificazione univoca dell’utente ci ver-
rà fornita dal sistema di Autenticazione (Win-
dows), mentre il sistema di Autorizzazioni do-
vrà rispondere “si” o “no” alla domanda “è au-
torizzato a compiere l’operazione X”?. È ne-
cessario dunque conservare in qualche repo-
sitory, una specie di tabella di verità che per
ogni “operazione” esprima il “si” o il “no” per
APPLICATIVI
Ri qua dro 1 Caratteristiche e differenze
Ms AzMan:
• È COM.• È dotato di una console mmc 2.0 (COM).• Il suo storage può essere un file Xml o ADAM (Active Directory Application Mode – è un LDAP).• È role-based.• Supporta gruppi applicativi statici/dinamici, members/non-members.• Struttura formata da Roles � Tasks � Operations. (Roles e Tasks gerarchici, Operations no).• Si possono dare autorizzazioni solo ai Ruoli.• Non implementa il concetto di “delega”.• Non gestisce le autorizzazioni “nel tempo”.• Non scatena eventi.• L’unico tipo di autorizzazione è “Allow” (per dire “deny” occorre rimuovere l’utente/gruppo dal Ruolo).• Supporta Scripting / Biz rules.
NetSqlAzMan:
• È .NET 2.0.• È dotato di una console mmc 3.0 (.NET).• Il suo storage è un database Sql Server (2000/MSDE/2005/Express).• È basato su tecnologia Tdo - Typed Data Object.
• È Item-based.• Struttura formata da Roles � Tasks � Operations. (Tutti gerarchici).• Si posso dare autorizzazioni a Ruoli, Task e Operazioni.• Supporta gruppi applicativi statici/dinamici, members/non-members.• Test delle query LDAP direttamente dalla console.• È time-dependant.• È delegate-compliant.• Scatena eventi (ENS).• Supporta 4 tipi di autorizzazione:
o Allow with delegation (autorizzato e autorizzato a delegare).
o Allow (autorizzato).
o Deny (non autorizzato).
o Neutral (permesso neutrale, dipende dai permessi degli Items di livello superiore).
• Autorizzazioni gerarchiche.• Non supporta Scripting / Biz rules.
30 VBJ N. 70 - Liglio/Agosto 2006
ogni utente/gruppo.
Questo repository in NetSqlAzMan si chiama
Storage ed è ospitato da un database Sql Ser-
ver (nel pacchetto di installazione è presente
lo Script Sql sia per la versione 2000 sia per
la versione 2005).
AzMan vs NetSqlAzManCome accennato prima esiste un prodotto
Microsoft analogo e denominato Authoriza-
tion Manager (AzMan); AzMan è presente na-
tivamente in Windows XP SP1+ e Windows
Server 2003.
La sostanziale differenza tra AzMan è Net-
SqlAzMan è che il primo è Role-based, ovvero
basa tutto sul concetto di appartenenza ad un
Ruolo e operazioni contenute in ciascun ruolo,
mentre il secondo è Item-based (o se preferi-
te Operation-based) ovvero utenti o gruppi di
utenti o gruppi di gruppi che possono o non
possono appartenere a Ruoli oppure esegui-
APPLICATIVI
re determinati Task e/o Operazioni.
Nel Riquadro “Caratteristiche e Differenze”,
vediamo le sostanziali caratteristiche e diffe-
renze tra i due prodotti.
La struttura che troviamo sia nello Stora-
ge che visivamente aprendo la console (Start
– Esegui – “NetSqlAzMan.msc”) è quella del
Riquadro 1.
Store e Store GroupPer Store si intende un raggruppamento lo-
gico di applicazioni. A questo livello è possi-
bile definire due tipologie di oggetti: Store
Group e Application.
Gli Store Group sono dei gruppi applicativi
di: Utenti/Gruppi Windows, altri Store Group
(come i ruoli di COM+ o i gruppi di sicurezza
di Windows); ogni gruppo può essere di tipo
Basic o LDAP ovvero definito staticamente,
cioè per selezione diretta, oppure definito di-
namicamente, tramite una query LDAP, che
Fi gu ra 1 Creare uno Store Group
31N. 70 - Luglio/Agosto 2006 VBJ
NetSqlAzMan risolve a run-time. In questo
modo è ad esempio possibile creare un grup-
po di utenti Active Directory che abbiamo un
nome che inizi per “Andrea” e permessi di
Dial-In. In Figura 1 vediamo come creare uno
Store Group; nel codice sotto un esempio di
query LDAP per includere tutti gli Utenti Ac-
tive Directory che abbiano un nome che inizi
per Andrea e permessi di Dial-In ed in Figura
2 come eseguire la query LDAP direttamente
dalla console di NetSqlAzMan.
(&(objectCategory=user)(cn=Andrea*)
(msNPAllowDialin=TRUE))
I Gruppi “Basic” sono inoltre costituiti
da Members e Non-Members ovvero utenti/
gruppi/Store Groups che devono essere
“considerati” nella costituzione dello Store
Group mentre i non-members sono utenti/
gruppi/Store Groups che non deveno esse-
re considerati. In altre parole, l’elenco dei
membri costituenti un gruppo Basic è dato da
{ Members } – { Non-Members}. Dato che i
members/non-members possono essere a loro
volta altri Store Group è possibile realizzare
potenti e complessi gruppi ricorsivi. Nella Fi-
gura 3 la definizione dei Members e dei Non-
Members di un gruppo Basic.
Gli Store Group hanno una visibilità circo-
scritta a livello di Store, quindi saranno vi-
sibili da tutte le Application contenute nel-
lo Store.
Gli Store Group sono l’ideale per implemen-
tare il concetto di “Ruolo Aziendale” ovvero
un raggruppamento di persone che in Azienda
svolgono una determinata funzione a prescin-
dere poi dai diritti che ciascuno ruolo avrà in
ogni applicazione; ecco alcuni esempi di ruoli
aziendali: “Dirigenti”, “Impiegati”, “Respon-
APPLICATIVI
Fi gu ra 4 Definzione di Non-Members in un gruppo
Basic
Fi gu ra 3 Definizione di Members nel gruppo BasicFi gu ra 2 Eseguire la query LDAP direttamente dalla
console di NetSqlAzMan
32 VBJ N. 70 - Liglio/Agosto 2006
APPLICATIVI
sabili UO”, ecc….
Per chi fosse interessato ad un approfondi-
mento circa la sintassi e le potenzialità del-
le query LDAP rimando a questo interes-
sante articolo di Microsoft sulla sintassi del-
le query LDAP: http://www.microsoft.com/
technet/prodtechnol/exchange/2003/insider/
ldapquery.mspx.
Application e Application GroupPer Application si intende proprio l’applica-
zione che interrogherà a run-time lo storage di
NetSqlAzMan; ricordo che qui la definizione è
puramente logica quindi non è richiesta alcu-
na corrispondeza con il tipo o il nome dell’ap-
plicazione reale. Per evitare qualsiasi confu-
sione conviene comunque assegnare lo stesso
nome e magari scrivere una breve descrizione
di ciò che fa l’applicazione nell’apposito cam-
po’ come mostrato nelle Figure 5 e 6.
Un Application Group è identico in tutto e
per tutto ad uno Store Group con la sola dif-
ferenza che il suo scoping (visibilità) è circo-
scritto alla sola Application in cui è definito;
un Application Group può considerare tra i
suoi members/non-members uno Store Group
ma non può mai accadere il viceversa.
Gli Application Group sono l’ideale per rap-
presentare i “Ruoli Applicativi”.
Item DefinitionsAll’interno di ogni Application si possono
definire infiniti Item; ogni Item può essere
di tipo Ruolo, Attività od Operazione (Role,
Task, Operation). A ciascun tipo di Item at-
tribuiremo rispettivamente il seguente signi-
ficato logico:
• Role: è un insieme di “utenti” che nel-
l’applicazione possono compiere le
stesse operazioni;
o Un Role può avere membri di tipo
Role, Task, Operation.
o Esempi di Role sono: “Amministrato-
re”, “Responsabile”, “Visualizzato-
re”.
• Task: è una macro-funzionalità logica
dell’Applicazione
o Un Task può avere membri di tipo
Task, Operation.
o Esempi di Task sono: “Inserimento”,
“Modifica”, “Visualizzazione Re-
port”.
• Operation: è una micro-funzionalità
dell’Applicazione
o Una Operation può avere membri solo
di tipo Operation.
o Esempi di Operation sono: “Inserisci
Fi gu ra 5 Creare una nuova Application
Fi gu ra 6 Assegnare una descrizione ad un oggetto
Application
33N. 70 - Luglio/Agosto 2006 VBJ
APPLICATIVI
nuovo utente”, “Modifica utente”, “Vi-
sualizza Report 1”.
Spesso accade che logicamente il poter com-
piere una determinata operazione significhi
automaticamente poterne compiere delle altre
magari di sotto livello, oppure si può utilizza-
re strumentalmente questo concetto per asse-
gnare delle autorizzazioni gerarchiche.
Consideriamo, a scopo di esempio, le ope-
razioni di “Cancellazione” ed “Inserimento”
e supponiamo che esistano alcuni gruppi di
utenti autorizzati a “cancellare”, altri autoriz-
zati ad “inserire” ed altri ancora autorizzati a
poter sia “cancellare” che “inserire”. In questo
caso è opportuno creare un Task “Modifica” e
due Operation “Inserimento” e “Cancellazio-
ne”, quindi entrare nelle proprietà del Task
(dalla console) e dire che esso è composto da
due Operation (Item membri). Questo fatto
sarà di particolare rilievo quando andremo ad
assegnare le autorizzazioni a questi Item, in
quanto i diritti dati al Task (Item contenitore)
saranno ereditati dalle Operation (Item mem-
bri) ma non avverrà il viceversa (ereditarietà
verso il basso); chi sarà autorizzato a “modi-
ficare” sarà implicitamente autorizzato anche
a poter “inserire” e “cancellare”. In Figura 7
un esempio di questa gerarchia.
Quando avremo creato tutte le Operation
ed, aggregate in Task logici dell’Applicazio-
ne, potremo finalmente dire cosa può fare ogni
Ruolo applicativo. Creiamo tanti Role quanti
sono i ruoli applicativi individuati nell’ana-
lisi dell’applicazione ed indichiamo per cia-
scun Ruolo quali solo i Task di cui quel Ruo-
lo si compone.
Fi gu ra 7 Creare una gerarchia tra Role e Task
34 VBJ N. 70 - Liglio/Agosto 2006
APPLICATIVI
Item AuthorizationsUna volta definiti tutti gli Item (Role, Task,
Operation) e creata una opportuna gerarchia
tra essi, ci dovremo preoccupare di “riempi-
re” questi contenitori con utenti/gruppi reali
e quindi “chi … può fare … cosa”, indicando
per ciascuno di essi i permessi.
Il “chi” potrà essere uno seguenti oggetti:
• Un utente Windows
• Un gruppo Windows
• Uno Store Group
• Un Application Group
Il “può fare” potrà essere una delle seguen-
ti autorizzazioni:
• Allow with delegation
• Allow
• Deny
• Neutral
Il “cosa” sarà uno degli Item definiti al pas-
so precedente.
• Role
• Task
• Operation
Se la gerarchia degli Item è stata costruita
correttamente, in genere, e a meno di situazio-
ni particolari, sarà sufficiente assegnare per-
messi solo ai Ruoli. Quando un’applicazione
chiederà a NetSqlAzMan … “posso fare l’Ope-
razione X ?”, il run-time verificherà se l’ope-
razione appartiene ad un Task che a sua vol-
ta appartiene ad un Role di cui l’utente del-
l’applicazione fa parte.
Se dalla console NetSqlAzMan si seleziona-
no una o più Application, o addirittura l’inte-
Fi gu ra 8 Impostare le Authorization di un Item ed eventuali Authorization Attribute
35N. 70 - Luglio/Agosto 2006 VBJ
ro Store, è possibile visualizzare la gerarchia
degli Items facendo clic destro con il mou-
se e scegliendo la voce “Items Hierarchical
View” (Figura 11).
Diamo ora un significato alle quattro auto-
rizzazioni disponibili ricordando che in Net-
SqlAzMan è presente il concetto di “delega”
ovvero un utente che delega un altro uten-
te a compiere un’operazione a lui originaria-
mente concessa.
In particolar modo chi possiede l’autorizza-
zione di “Allow with delegation” potrà sicu-
ramente compiere l’operazione ed in più po-
trà delegare uno o più utenti a compiere per
suo conto la stessa operazione. Questo mec-
canismo di delega, per ragioni di sicurezza,
non può essere esteso oltre il primo livello.
Ciò significa che l’utente delegato non potrà
a sua volta delegare un altro utente a com-
piere la stessa operazione (“allow with dele-
gation” non si propaga).
Il diritto di Allow concede le autorizzazioni
a poter compiere quel determinato Item sen-
za diritto di delega.
Il diritto di Deny nega viceversa qualsiasi
autorizzazione mentre un’autorizzazione di
tipo Neutral è invece neutrale, cioè non dice
né “si” né “no”, ma lascia decidere agli Item
di livello superiore.
Le autorizzazioni Neutral esistono al solo
scopo amministrativo e consentono di man-
tenere nello store l’associazione “chi”/”cosa”
senza però dire se il “cosa” può essere o non
può essere fatto. Un tipico utilizzo dei Neu-
tral è per quegli Item i cui permessi cambia-
no continuamente, e sarebbe dunque tedioso
aggiungere e cancellare continuamente i sog-
getti delle autorizzazioni dallo Storage; me-
glio lasciarli lì e modificare solo il permesso
all’occorrenza.
Un’ultima considerazione va fatta per le
autorizzazioni di tipo Deny; se su in Item,
ad un utente viene dato detto permesso di
Deny, questo utente non potrà sicuramente
compiere tale operazione ma non potrà nem-
meno compiere nessuna delle eventuali sot-
to operazioni (Item figli) anche se ad una di
queste fossero dati permessi di Allow o Allow
with delegation; come avviene per le autoriz-
zazioni del File System e di Sql Server, vince
il permesso più restrittivo. Viceversa se su un
Item vengono dati allo stesso soggetto sia il
permesso di Allow sia il permesso Allow with
delegation vince il permesso meno restrittivo
e cioè Allow with delegation.
Attenzione che questa affermazione è vera
solo per autorizzazioni date sullo stesso Item
e non per vale per gli Item gerarchici; Allow
with delegation non viene propagato sugli
Item figli.
In Figura 8 la scheramata della console che
consente di impostare le autorizzazioni.
NetSqlAzMan è Delegate-compliantQuando un’autorizzazione viene data dal-
l’Amministratore di NetSqlAzMan attraver-
so la console di amministrazione si parla pro-
priamente di “Autorization”. Lo stesso mec-
canismo può essere essere adoperato in fase
di run-time da utenti speciali che consentono
ad altri utenti di poter compiere una determi-
nata operazione in loro vece. In questo caso
utilizzeremo il termine “delega”.
Per delegare, l’utente delegante deve innan-
zitutto avere diritti di Allow with delegation
direttamente sull’Item in questione e deve ap-
partenere al ruolo Sql Server: NetSqlAzMan_
Users. Nello storage sql sono infatti presenti
3 (tre) diversi Database Roles:
• NetSqlAzMan_Administrators
(controllo completo)
• NetSqlAzMan_Users (solo lettura e per
messo di delega sugli Item con per
messo Allow with delegation)
• NetSqlAzMan_Readers (solo lettura)
Più avanti vedremo come utilizzare il me-
todo Item.CreateDelegate delle NetSqlAz-
Man API.
APPLICATIVI
36 VBJ N. 70 - Liglio/Agosto 2006
NetSqlAzMan è Time-dependant
Ogni autorizzazione può esse-
re “elargita” per un intervallo di
tempo indeterminato o determina-
to. I due campi Valid From e Valid
To nella finestra delle autorizzazio-
ni indicano rispettivamente la data
(e ora) di inizio e fine validità del-
l’auorizzazione stessa. Combinan-
do questa caratteristica con la pos-
sibilità di aggiungere più di un’au-
torizzazione per soggetto e per in-
tervalli temporali diversi, più l’ere-
ditarietà delle autorizzazioni, più la
tipologia del permesso (consenti o
nega) è possibile esprimere auto-
rizzazioni che mutano nel corso del
tempo. Si può dire ad esempio che
un utente “u1” potrà eseguire l’Item “x” solo
dal 1-gen-2006 al 30-giu-2006 e successivamen-
te dal 1-gen-2007 al 30-giu-2007. In questi due
intervalli temporali potremo inoltre escludere
periodi specifici, aggiungendo altri permessi
per intervalli minori e di tipo Deny.
Stesso identico discorso può esser fatto per
le deleghe, in quanto esse sono a tutti gli ef-
fetti delle autorizzazioni.
Authorization AttributeL’ultimo anello della catena di questa strut-
tura è rappresentato dagli Authorization Attri-
bute ovvero gli attributi di una autorizzazione.
Fisicamente un attributo è rappresentato da
una semplice coppia “key-value” (chiave-va-
lore) entrambi di tipo stringa. Per ogni Autho-
rization è possibile definire infiniti attributi
con il solo vincolo che il nome dell’Attribute
(la parte key) dovrà essere univoca per quel-
l’autorizzazione. Viceversa sarà possibile de-
finire un altro attributo con la stessa key in
un’altra autorizzazione.
Lo scopo degli Authorization Attribute è
quello di consentire al livello più capillare
l’aggiunta di informazioni custom per ogni
singola autorizzazione, aumentando così il li-
vello di granularità dei permessi.
Un tipico utilizzo degli attributi è quello dei
dati di profilo di un utente. Supponiamo che
un utente “u1” rivesta in una Azienda IT il
ruolo di “Capo progetto” di un certo proget-
to “p1”; immaginiamo inoltre che nell’Azien-
da sia stata sviluppata una applicazione che
consenta ai capi-progetto di monitorare lo sta-
to di avanzamento dei progetti loro assegna-
ti. Supponiamo anche che l’applicazione con-
templi fra gli altri una operazione “Controlla
SAL” (Stato Avanzamento Lavori). Che succe-
de se l’utente “u1” volesse delegare un utente
“u2”, risorsa di fiducia del suo team di svilup-
po, a controllare in sua vece lo stato del pro-
getto “p1”? Una delega adoperata da “u1” a
“u2” direbbe che “u2 è autorizzato a compie-
re l’operazione Controlla SAL al posto di u1”
ma non si porterebbe appresso l’informazio-
ne … “…per il solo progetto p1”.
L’aggiunta di un attributo “progetto-p1” (key-
value) all’autorizzazione di delega da “u1” a
“u2” risolve tale problema; resta il fatto che
NetSqlAzMan di fronte ad una richiesta di
“u2” di “posso eseguire l’item Controlla SAL?”
risponderà Allow; sarà poi compito dell’ap-
plicazione leggere gli eventuali Authoriza-
tion Attribute e filtrare l’elenco dei proget-
ti da utilizzare per l’operazione. Altri esempi
di attributi sono dati da: “Data di autorizza-
APPLICATIVI
Fi gu ra 9 Impostazione delle informazioni di
connessione allo Storage di NetSqlAzMan
37N. 70 - Luglio/Agosto 2006 VBJ
zione”, “UO di appartenenza”, “Settore”, “Di-
partimento”, ecc….
NetSqlAzMan Snap-In e creazione del DataBase Sql Server
Vediamo come implementare fisicamente
quanto detto finora, attraverso lo Snap-In di
NetSqlAzMan.
Prima di tutto occorre creare un nuovo da-
tabase su Sql Server; il nome che vi consi-
glio è NetSqlAzManStorage ma qualsiasi altro
nome va bene uguale, quindi eseguite l’appo-
sito script che trovate nella cartella di installa-
zione di NetSqlAzMan (c’è sia la versione per
Sql Server 2000 che 2005), avendo cura di se-
lezionare il database appena creato (da Query
Analyzer o Sql Management Studio) prima di
far partire lo script.
Creato il database possiamo
far partire la console in 3 diver-
si modi:
• Start – Programmi - .NET
Sql Authorization Manager –
NET Sql Authorization Manag-
er Console
• Start – Esegui –
NetSqlAzMan.msc
• Start – Esegui – mmc e poi
Aggiungi/Rimuovi Snap-In,
quindi scegliere .NET Sql Au-
thorization Manager dall’elenco
e cliccare sul pulsante Aggiun-
gi.
Ora dobbiamo dire a NetSqlAz-
Man qual è lo Storage da gesti-
re – Figura 9; faremo questa ope-
razione facendo clic con il tasto
destro del mouse sul nodo .NET
Sql Authorization manager e
scegliendo la voce Storage con-
nection. Specifichiamo dunque
il nome del server ed eventua-
lemente l’istanza Sql Server sulla quale ab-
biamo create il database ed eseguito lo script
Sql, il tipo di autenticazione (Sql o Windows),
il nome dello Storage più eventuali parame-
tri aggiuntivi che finiranno direttamente nel-
la stringa di connessione ADO.NET (ad es.
“Enlist = false;”).
NetSqlAzMan può funzionare in due dive-
re modalità: “Administrator” e “Developer”;
la prima non considera Utenti/Gruppi/Well
Know SIDs locali alla macchina ma soltanto
Utenti/Gruppi/Well Know SIDs del Dominio o
della Foresta Active Directory e non consen-
te la manipolazione delle Operation (in quan-
to considerate ad uso degli sviluppatori); la
seconda modalità li contempla entrambi. La
modalità “Developer” è stata pensata apposi-
tamente per la sola fase di sviluppo, quando
l’ambiente di Deployment non è ancora dispo-
APPLICATIVI
Fi gu ra 10 Un esempio complet di Store
38 VBJ N. 70 - Liglio/Agosto 2006
nibile o comunque noto. In questa modalità
sarà inoltre compito dello sviluppatore defi-
nire da quali Operazioni si compone ciascun
Task (definiti precedentemente dall’analista).
Per cambiare modalità occorre utilizzare la
console e, facendo clic con il tasto destro del
mouse sul nodo .NET Sql Authorization Ma-
nager, scegliere la voce Options.
A questo punto siamo pronti a creare Store,
Store Group, Application, Application Group,
Role, Task, Operation, Authorization e Autho-
rization Attribute facendo semplici clic con il
mouse, tasto destro – New Store, New Appli-
cation, ecc…. In Figura 10 un esempio di Sto-
re a lavoro finito.
Quando abbiamo finito salviamo la console
in modo da non dover fornire nuovamente al
prossimo avvio le informazioni di connessio-
ne allo Storage di NetSqlAzMan.
NetSqlAzMan API – Il Run-Time Engine
Una volta creata la struttura dalla console di
NetSqlAzMan, vediamo come le applicazioni
possano interrogare lo storage attraverso le
API del run-time engine. Creiamo dunque la
nostra applicazione (smart client, web, ecc…
) con VS.NET 2005 ed aggiungiamo un riferi-
mento all’Assembly .NET NetSqlAzMan.dll.
L’assembly dovrebbe essere visibile nell’elen-
co dei componenti della finestra di dialogo
“aggiungi riferimento”; se così non fosse cer-
catelo nello cartella di installazione di NetSq-
lAzMan.
In testa al nostro codice aggiungiamo due
clausole using/imports per dichiarare di vo-
lere utilizzare i namespace NetSqlAzMan e
NetSqlAzMan.Interfaces. Ora tutto il codice
necessario per interrogare lo storage si ridu-
ce a queste poche righe, come mostrato an-
che nel codice allegato all’articolo:
Listato 2:
C#
using NetSqlAzMan;
using NetSqlAzMan.Interfaces;
...
string cs = “Data Source=(local);Initial Catalog =
NetSqlAzManStorage;Integrated Secuirty = SSPI;”;
IAzManStorage storage = new SqlAzManStorage(cs);
System.Security.Principal.WindowsIdentity identity =
System.Security.Principal.WindowsIdentity.GetCurrent();
//For each Operation …
//Can I do “My Operation” ?
AuthorizationType authorizaion = storage.CheckAccess(“My
Store”, “My Application”, “My Operation”, identity,
DateTime.Now, true);
switch (authorizaion)
{
case AuthorizationType.AllowWithDelegation:
//Yes, I can ... and I can delegate
break;
case AuthorizationType.Allow:
//Yes, I can
break;
case AuthorizationType.Deny:
case AuthorizationType.Neutral:
//No, I cannot
break;
}
VB.NET
Imports NetSqlAzMan
Imports NetSqlAzMan.Interfaces
...
Dim cs As String = “Data Source=(local);Initial Catalog =
NetSqlAzManStorage;Integrated Secuirty = SSPI;”
Dim storage As IAzManStorage = New SqlAzManStorage(cs)
Dim identity As System.Security.Principal.WindowsIdentity
= System.Security.Principal.WindowsIdentity.GetCurrent()
‘Per ciascuna Operazione …
‘Posso eseguire “My Operation” ?
Dim authorizaion As AuthorizationType =
storage.CheckAccess(“My Store”, “My Application”, “My
Operation”, identity, DateTime.Now, True)
Select Case authorization
Case AuthorizationType.AllowWithDelegation
‘Sì, posso ... e posso delegare
Case AuthorizationType.Allow
‘Sì, posso
Case AuthorizationType.Deny Or AuthorizationType.Neu
APPLICATIVI
39N. 70 - Luglio/Agosto 2006 VBJ
tral
‘No, non posso
End Select
Per prima cosa dobbiamo creare un’istanza
della classe NetSqlAzManStorage, fornendo al
costruttore la stringa di connessione al data-
base Sql Server, quindi ricavare l’identità del-
l’utente che sta utilizzando l’applicazione.
Per ricavare la WindowsIdentity per una ap-
plicazione ASP.NET utilizziamo la proprietà
LogonUserIdentity della classe HttpRequest
della pagina .aspx; se ci troviamo invece in
una applicazione Smart-Client utilizzeremo il
metodo statico System.Security.Principal.Wi
ndowsIdentity.GetCurrent().
A questo punto sarà sufficiente fornire al
metodo CheckAccess i seguenti parametri di
input:
• StoreName (System.String): il nome
dello store
• ApplicationName (System.String): il
nome dell’applicazione
• ItemName (System.String): il nome
dell’Item (un Role, un Task od una
Operation).
• windowsIdentity (System.Security.Pri-
ncipal.WindowsIdentity): l’identità
dell’utente
• ValidFor (System.DateTime): Da-
teTime che indica per quale istante
temporale si richiede il controllo (ti-
picamente DateTime.Now).
• OperationsOnly (System.Boolean):
true per indicare che il l’item dovrà
essere necessariamente una Opera-
tion, false altrimenti (se si vuole con-
trollare l’accesso ad un Task o un Ruo-
lo).
La risposta che il metodo CheckAccess for-
nirà sarà del tipo enumerativo NetSqlAzMan
.AuthorizationType ed attribuiremo a tale ri-
sposta i seguenti significati:
• AuthorizationType.AllowWithDelegat-
ion: accesso consentito con diritto di
delega.
APPLICATIVI
• AuthorizationType.Allow: accesso
consentito senza diritto di delega.
• AuthorizationType.Deny: accesso ne-
gato.
• AuthorizationType.Neutral: accesso
neutrale (e quindi negato).
Delega applicativa
Se vogliamo implementare nella nostra ap-
plicazione una pagina .aspx o una Form Win-
dows specifica per consentire agli utenti stessi
dell’applicazione di delegare, dovremo repe-
rire prima le seguenti informazioni:
• L’Item (Role, Task, Operation) ogget-
to della delega;
• chi è l’utente “delegante”;
• chi è l’utente “delegato”;
• l’intervallo temporale di validità tem-
porale della “delega” (dal … al)
informazioni che poi passeremo tutte insie-
me al metodo NetSqlAzMan.SqlAzManItem.
CreateDelegateAuthorization(…).
Partendo dalla classe NetSqlAzManStorage,
possiamo “navigare” nel DOM di NetSqlAz-
Man utilizzando i metodi accessori GetXXX()
o più semplicemente facendo uso di indexer,
come mostrato nei listati 3 e 4, sempre nel
codice allegato.
È sempre possibile ed anzi consigliabile ri-
cavare a run-time l’elenco degli Item defini-
ti nello Storage ma di questi dovremo consi-
derare solo quelli che hanno il permesso Al-
lowWithDelegation, come mostrato nel listato
5, in quanto solo sugli Item con questo specia-
le permesso sarà consentito delegare.
Listato 5:
C#
using NetSqlAzMan;
using NetSqlAzMan.Interfaces;
...
string cs = “Data Source=(local);Initial Catalog =
NetSqlAzManStorage;Integrated Secuirty = SSPI;”;
40 VBJ N. 70 - Liglio/Agosto 2006
IAzManStorage storage = new SqlAzManStorage(cs);
foreach (IAzManItem item in storage[“My Store”][“My
Application”].GetItems(ItemType.Role))
{
foreach (IAzManAuthorization auth in item.GetAuthori
zations())
{
if (auth.AuthorizationType == AuthorizationType.A
llowWithDelegation)
{
//Per questo “item” si può delegare
}
}
}
VB.NET
Imports NetSqlAzMan
Imports NetSqlAzMan.Interfaces
...
Dim cs As String = “Data Source=(local);Initial Catalog =
NetSqlAzManStorage;Integrated Secuirty = SSPI;”
Dim storage As IAzManStorage = New SqlAzManStorage(cs)
For Each item As IAzManItem In storage(“My Store”)(“My
Application”).GetItems(ItemType.Role)
For Each auth As IAzManAuthorization In
item.GetAuthorizations()
If auth.AuthorizationType =
AuthorizationType.AllowWithDelegation Then
‘Per questo “item” si può delegare
End If
Next
Next
Dopo aver individuato l’Item og-
getto della delega e l’identità del-
l’utente delegante (stesso proce-
dimento illustrato nel listato 2) ci
dovremo preoccupare dell’utente
“delegato” ovvero quello al quale
vogliamo concedere il diritto di po-
ter compiere l’Item in nostra vece.
Tale identità è rappresentata uni-
vocamente solo dal SID (Security
IDentifier) dell’utente Windows.
I SID sono custoditi dall’infra-
struttura Active Directory alla
quale l’applicazione appartiene; per ricava-
re un SID dobbiamo essere in possesso della
Login corrispondente ed in genere occorre-
rà dunque una tabella di corrispondenze tra
il nome dell’Utente ad esempio (nome e co-
gnome) e la sua Login (DOMINIO\Utente). Il
.NET Framework 2.0 per fortuna viene incon-
tro a questa esigenza e ci mette a disposizione
due nuove e fondamentali classi per compie-
re questa operazione: System.Security.Princi
pal.NTAccount e System.Security.Principal.S
ecurityIdentifier che combinate assieme con-
sentono di ricavare il SID di un utente data la
sua Login e/o viceversa; per un esempio ve-
dere il listato 6.
Il SID così ricavato verrà passato come pa-
rametro al costruttore della classe NetSqlAz
Man.SqlAzManSID.
Gli ultimi due parametri sono di tipo
System.DateTime? (ovvero nullabili) e rap-
presentano data e ora di inizio e fine validi-
tà della delega. Se uno dei due o entrambi
avranno valore nullo si intenderà la delega
come senza scadenza o senza inizio validità o
a tempo indeterminato. Nel listato 7 un esem-
pio di delega applicativa.
Il metodo NetSqlAzMan.SqlAzManItem.C
APPLICATIVI
Fi gu ra 11 Vista gerarchica degli Item
41N. 70 - Luglio/Agosto 2006 VBJ
reateDelegateAuthorization(…) restituisce
un’istanza di tipo IAzManAuthorization che
possiamo utilizzare per aggiungere uno o più
attributi come mostrato nel listato 8.
Listato 8:
C#
using NetSqlAzMan;
using NetSqlAzMan.Interfaces;
using System.Security.Principal;
...
IAzManAuthorizationAttribute attr =
del.CreateAuthorizationAttribute(“My Key”, “My Value”);
VB.NET
Imports NetSqlAzMan
Imports NetSqlAzMan.Interfaces
Imports System.Security.Principal
...
del.CreateAuthorizationAttribute(“My Key”, “My Value”)
A delega effettuata l’utente “delegato” po-
trà così accedere alle funzionalità dell’appli-
cazione rappresentate dagli Item sui quali è
stato delegato (il permesso che la delega as-
segna è Allow).
Quando si opera con le deleghe diviene fon-
damentale sapere se l’utente ha già delegato
altri oppure no, semplicemente magari per
impedire che lo stesso utente possa compie-
re nuovamente l’operazione di delega sul me-
desimo delegato. Per fare ciò occorre leggere
le autorizzazioni date su un determinato Item
facendo uso dei metodi NetSqlAzMan.SqlAz
ManItem.GetAuthorizationsOfOwner(…) for-
nendo il SID dell’utente “delegante” oppure,
per deleghe su specifici utenti il metodo Net-
SqlAzMan.SqlAzManItem.GetAuthorizations(
…) passando il SID del “delegante” ed il SID
del “delegato”. Un esempio di utilizzo di que-
sti due metodi nel listato 9.
Infine, per eliminare una delega fatta da un
utente “u1” ad un utente “u2” esiste il metodo
NetSqlAzMan.SqlAzManAuthorization.Delete-
DelegateAuthorization(…); i parametri da for-
nire sono al solito la WindowsIdentity dell’uten-
te “u1” ed il SID dell’utente “u2” (listato 10).
Listato 10:
C#
using NetSqlAzMan;
using NetSqlAzMan.Interfaces;
using System.Security.Principal;
...
IAzManItem item = ...;
WindowsIdentity u1 = WindowsIdentity.GetCurrent();
IAzManSid u2 = ...;
item.DeleteDelegateAuthorization(u1, u2);
VB.NET
Imports NetSqlAzMan
Imports NetSqlAzMan.Interfaces
Imports System.Security.Principal
...
Dim item As IAzManItem = ...
Dim u1 As WindowsIdentity = WindowsIdentity.GetCurrent()
Dim u2 As IAzManSid = ...
item.DeleteDelegateAuthorization(u1, u2)
Manipolare lo Storage NetSqlAzMan da codice .NET
Le NetSqlAzMan API sono molto utili per
manipolare lo Storage Sql Server direttamen-
te da codice .NET. Basti pensare che la conso-
le amministrativa utilizza internamente pro-
prio queste API; ne deriva dunque che tutto
quello che possiamo fare da console lo pos-
siamo fare anche da codice.
Sarebbe però estremamente lungo ed one-
roso descrivere ogni singolo metodo di ogni
classe presente nel DOM di NetSqlAzMan,
si rimanda perciò al chm fornito insieme al
prodotto.
Nell’esempio mostrato nel listato 11, utilizia-
mo il DOM per creare a run-time uno Store,
una Application, un Role, un Task, una Ope-
ration e rendere quest’ultima un Item mem-
bro del Task ed il Task un Item membro del
APPLICATIVI
42 VBJ N. 70 - Liglio/Agosto 2006
Role; sempre nell’esempio viene creata una
Authorization ed un AuthorizationAttribute.
Ricordiamoci che l’utente che eseguirà tale
codice dovrà appartenere al Database Role di
Sql: NetSqlAzMan_Administrators.
Le API utilizzano Tdo - Typed Data Object
(vedi [3]) per leggere e scrivere da Sql Ser-
ver e questo implica un aumento delle per-
formance e tutta la sicurezza (ad esempio no
Sql injection) fornita da Tdo.
ENS (Event Notification System)
Tutte le classi di NetSqlAzMan scatenano
eventi e questo fatto si rivela molto utile se
ad esempio volessimo tener traccia in un log
di tutte le operazioni effettuate dagli utenti
sullo Storage. Inoltre tutti gli eventi possibi-
li ed immaginabili di ogni classe, sono stati
concentrati e centralizzati in un’unica classe
ad eventi statici: SqlAzManENS.
L’ENS è un potente e comodo Sistema di No-
tifica Eventi da utilizzarsi sia a scopo ammi-
nistrativo sia per catturare tutti gli eventi che
accadono sullo Storage per mano della nostra
applicazione. Nel listato 12 un esempio di uti-
lizzo della classe NetSqlAzManENS.
Listato 12:
C#
using NetSqlAzMan;
using NetSqlAzMan.Interfaces;
using NetSqlAzMan.ENS;
...
SqlAzManENS.StoreCreated +=
new StoreCreatedDelegate(SqlAzManENS_StoreCreated);
...
void SqlAzManENS_StoreCreated(IAzManStore storeCreated)
{
System.Diagnostics.Debug.WriteLine(
storeCreated.Name + “ store created”);
}
VB.NET
Imports NetSqlAzMan
Imports NetSqlAzMan.Interfaces
Imports NetSqlAzMan.ENS
...
Dim WithEvents ens As SqlAzManENS ‘class-level field
...
Private Sub ens_StoreCreated(ByVal storeCreated As
NetSqlAzMan.Interfaces.IAzManStore)
Handles ens.StoreCreated
System.Diagnostics.Debug.WriteLine(
storeCreated.Name + “ store created”)
End Sub
Conclusioni
Credo saremmo tutti d’accordo nel dire che
molte applicazioni necessitano o hanno neces-
APPLICATIVI
• Windows 2000/XP/2003• .NET Framework 2.0
(http://msdn.microsoft.com/netframework/downloads/updates/default.aspx)• MMC (Microsoft Management Console) 3.0
(http://www.microsoft.com/downloads/details.aspx?familyid=61FC1C66-06F2-463C-82A2-CF20902FFAE0&displaylang=it)
• Sql Server 2000/MSDE/2005/Express(http://msdn.microsoft.com/vstudio/express/sql/download/)
Requisiti di installazione
43N. 70 - Luglio/Agosto 2006 VBJ
sitato nel passato di un sistema centralizzato
di gestione delle autorizzazioni. A chi di voi ad
esempio fa questo mestiere, sarà capitato si-
curamente almeno una volta nella vita di ave-
re un’esigenza simile per una applicazione.
Come è andata a finire? Tutto a mano? Tutto
da capo ogni volta? Tutto custom nel DB?
Ci sono molte altre feature in NetSqlAz-
Man, tra cui:
• CheckAccess asincrona (BeginChe-
ckAccess / EndCheckAccess)
• NetSqlAzMan cusom Exceptions
• Tutte le operazioni sullo
Storage posso essere transazionali
(Storage.BeginTransaction/
CommitTransaction/
RollBackTransaction)
• Import/Export in formato XML diret-
tamente dalla console
• Import da MS Authorization Manag-
er
• Test delle query LDAP per i gruppi
dinamici dalla console (Store Group e
Application Group)
• Tutte le operazioni fatta dalla console
vengono loggate nella Application Log
della macchina
Il solo fatto che poi sia .NET 2.0 nativo e si
appoggi a Sql Server per lo Storage delle au-
torizzazioni, rendono questo prodotto sicura-
mente interessante e meritevole almeno di
una prova.
Vi ricordo infine che per il tutto, ovvero sia
per la console sia per il run-time engine, è
disponibile il codice sorgente (C#.NET) ol-
tre che ovviamente al pacchetto di installa-
zione (vedi [4]).
Ringraziamenti
Devo rivolgere un particolare ringraziamen-
to a “Catho” che mi ha dato preziosi sugge-
rimenti in fase di progettazione di NetSqlAz-
Man, oltreché a svolgere un minuzioso lavo-
APPLICATIVI
ro di testing. Grazie “Catho”.
Bibliografia
[1] A. Ferendeles – “Tdo - Typed Data Object
1.0”, VBJ n.62.
[3] A. Ferendeles – “Performance con GAC
e NGEN in ASP.NET”, VBJ n.64.
[2] A. Ferendeles – “Tdo - Typed Data Object
2.0”, VBJ n.67.
Riferimenti
[3] Tdo home site: http://tdo.sourceforge.net
(documentazione e quickstart).
[4] Sito NetSqlAzMan:
http://netsqlazman.sourceforge.net
(sorgenti, installer, documentazione).
45N. 70 - Luglio/Agosto 2006 VBJ
Generics in C# 2.0
di Gian Maria Ricci
L a programmazione generica espande for-
temente le possibilità offerte dai normali linguaggi,
permettendo la creazione di codice “generico”, ov-
vero non vincolato ad uno specifico tipo di dato. Il
primo esempio di rilievo di programmazione gene-
rica si ha con i template del C++, sui quali è inte-
ramente basata la libreria STL. Il framework .NET
2.0 introduce in maniera analoga il concetto di ge-nerics, un estensione disponibile in tutti i linguag-
gi .NET, perché propria del framework. In questo
articolo l’argomento verrà affrontato nell’ottica del
C#, ma i concetti esposti sono naturalmente vali-
di anche per Visual Basic e per qualsiasi altro lin-
guaggio .NET 2.0 compatibile.
GenericsIl meccanismo dei generics è simile a quello dei
templates in C++, sebbene presenti alcune diffe-
renze più o meno marcate. Lo scopo finale è comun-
que lo stesso, scrivere codice che
non opera su un tipo particolare
di dato e che incapsula un set di
operazioni standard.
Nel .NET 1.1 il massimo del-
la genericità si ottiene facendo
discendere tutti gli oggetti dal
tipo base object, un approccio uti-
lizzato anche da altri linguaggi
moderni come il java. Sebbene
questa tecnica permetta un cer-
to livello di astrazione dal tipo
di dato, non è sicuramente pa-
ragonabile a quello che si può
ottenere con un generics o con
un template.
L’esempio classico è quello dei
contenitori: in .NET 1.1 è possi-
bile creare un contenitore gene-
rico, come un arraylist, sempli-
cemente indicando che gli og-
getti al suo interno sono di tipo
object; così facendo si può in-
serire al suo interno qualsiasi
dato e si può quindi dire di ave-
re creato un contenitore “generi-
co”. Purtroppo in questo modo la
L’introduzione della programmazione generica è
sicuramente la novità più interessante del .NET 2.0,
scopriamone le caratteristiche principali.
Gian Maria Ricci è laureato in Ingegneria Elettronica presso
la facoltà di Ancona. Si interessa di computer graphics 3D
(DirectX e Playstation2) e di programmazione in ambiente
Windows. Collabora attualmente con la ActValue consulting
(www.actvalue.com) nella realizzazione di prodotti software
legati al mondo RfID.
C#
Generics
46 VBJ N. 70 - Liglio/Agosto 2006
Media += (int) list[I];
}
Come si può vedere è necessario un cast
per informare il compilatore che i dati pre-
senti nella lista sono di tipo int e se per sba-
glio al suo interno si trovano altri tipi di dato
il cast naturalmente fallisce generando un’ec-
cezione.
Per ripararci da errori di questo tipo bisogne-
rebbe quindi racchiudere in un try catch ogni
parte di codice che accede al contenuto di un
arraylist, operazione che è assolutamente im-
proponibile per non ridurre drasticamente la
leggibilità del codice. Con il .NET 1.1 l’unica
soluzione era far derivare una propria clas-
se da ArrayList o da CollectionBase e fare il
wrapping dei metodi Add(), Index(), etc per ot-
tenere una collection strongly typed. In pro-
getti di grande dimensione questo porta ine-
vitabilmente ad avere una collection specializ-
zata per quasi tutti i tipi di dato definito dal-
l’utente, perdendo così in parte il vantaggio
della genericità e tornando alla vecchia pra-
tica del copia ed incolla, la cui eliminazione
è lo scopo principale della programmazione
generica. Questa pratica inoltre è altamente
inefficiente, se si ha la necessità di aggiungere
un nuovo metodo alle collection così genera-
te è necessario modificare file per file, con il
rischio di dimenticarne alcuni ed avere quin-
di comportamenti incoerenti.
Con il .NET 2.0 le classi generiche risolvono
il problema in maniera decisamente più effi-
ciente, ecco ad esempio come dichiarare una
lista di interi:
genericità è eccessiva, il non sapere con cer-
tezza cosa è contenuto obbliga ad effettuare
un cast al tipo corretto durante l’accesso, ma
il problema maggiore è comunque la possi-
bilità di inserire dati eterogenei e quindi lo-
gicamente incorrelati. Con questo approccio
avere classi generiche significa rinunciare alla
tipizzazione dei dati, limitazione che spesso
non è accettabile.
Come esempio si consideri un semplice pro-
gramma in cui si chiede all’utente di inserire
una serie di numeri interi e di calcolarne poi
la media. L’esempio è contenuto nella funzione
Main1() del progetto Generics accluso, è scritto
in C# 2.0, ma non fa uso di generics, bensì di
un normale contenitore. Il ciclo di lettura può
essere fatto in questo semplice modo
while (InsertLine != “” ) {
if (Int32.TryParse(InsertLine, out InsertValue))
list.Add(InsertValue);
InsertLine = Console.ReadLine();
}
Una nota va fatta riguardo al metodo TryPar-se(), nuova aggiunta del framework 2.0 presen-
te in tutti i tipi base di dato e che risolve un
problema spinoso presente nella vecchia ver-
sione. Con il .NET 1.1 infatti tutti i tipi hanno
il metodo Parse() che permette di convertire un
valore stringa nel tipo di dato richiesto lan-
ciando un eccezione se la stringa non è in un
formato corretto. Questo approccio costringe
ad utilizzare blocchi try-catch per intercetta-
re eventuali errori di formato, operazione che
rende il codice meno leggibile e che diminui-
sce seriamente le performance. In .NET 2.0
tutti i tipi hanno invece il metodo TryParse() che effettua la conversione richiesta inseren-
do il risultato nel secondo parametro (che è
passato come ref out) restituendo contempo-
raneamente un bool che indica se la conver-
sione è riuscita o meno. Quello che interessa
però è il ciclo che esegue la media
int Media = 0;
for (int I = 0; I < list.Count; ++I){
C #
La programmazione
generica riduce
drasticamente la procedura
del copia ed incolla
47N. 70 - Luglio/Agosto 2006 VBJ
System.Collections.Generic.List<int> list = new System.Collections.Generic.List<int>();
Una classe generica incapsula infatti una se-
rie di operazioni che non dipendono dal tipo
di dato permettendo quindi la creazione di
codice che fornisce un set di operazioni stan-
dard altamente riutilizzabile. Un contenitore
è l’esempio più chiaro di codice non legato
ad un tipo di dato specifico che offre metodi
di inserimento, rimozione, ricerca, ecc., il cui
comportamento è assolutamente indipenden-
temente dagli oggetti trattati.
Il tipo di dato su cui si deve operare vie-
ne comunque specificato al momento della
creazione di un’istanza, con la stessa sintassi
del C++ ovvero racchiudendolo tra parentesi
angolari. Ogni istanza di una classe generica
opera quindi su un tipo ben determinato che
viene specificato in maniera esplicita o im-
plicita al momento della sua creazione. Nel-
l’esempio precedente si è quindi ottenuta una
collezione generica di oggetti interi. La diffe-
renza dall’utilizzo di un arraylist standard è
che in questo caso la lista accetta solamente
interi e non è necessario effettuare operazio-
ni di casting durante la lettura del suo con-
tenuto. In questo modo si possono utilizza-
re collection strongly typed in maniera vera-
mente efficiente.
Creare una classe generic Per comprendere meglio il funzionamento è
interessante mostrare come si scrive codice
generico realizzando una rudimentale classe
che implementa uno stack. Il codice completo
è mostrato nel listato1 ed ha solamente uno
scopo esemplificativo, dato che nel framework
è già contenuta una classe generica stack per-
fettamente funzionante. La sintassi è sempli-
ce da ricordare, basta indicare il nome del tipo
generico su cui la classe opera, in questo caso
T ed utilizzarlo internamente alla classe come
se fosse un tipo vero e proprio.
Come si è visto nell’esempio precedente il
tipo di dato viene specificato solamente in fase
di definizione ed è in questo momento che vie-
ne generata nell’assembly la classe specifica.
Per comprendere meglio il processo si può im-
maginare che il compilatore, quando incontra
un oggetto di tipo MyStack<int>, prenda il co-
C #
Listato 1 Dichiarazione della classe
generica MyStack
namespace Generics { class MyStack<T> { T[] basearray = new T[3]; int stackPos = 0;
public T Pop() { if (stackPos >= 0){ T element = basearray[--stackPos]; return element; } throw new ArgumentOutOfRangeException(“ Stack is empty”) ; }
public void Push(T element) { //controllo se c’è abbastanza spazio if (stackPos >= basearray.Length) { T[] newarray = new T[basearray.Length * 2]; basearray.CopyTo(newarray, 0); basearray = newarray; } basearray[stackPos++] = element; }
public bool Peek() { return stackPos > 0; }
public int Count() { return stackPos; }
}
}
Il supporto ai generics è
dato dal framework ed è
quindi standard per ogni
linguaggio
48 VBJ N. 70 - Liglio/Agosto 2006
dice della classe generica, sostituisca ad ogni
occorrenza di T il tipo int, dia alla classe un
nome tipo MyStak_Int ed infine la compili
assieme alle altre. Il processo vero e proprio
è differente, ma il concetto base è che viene
comunque generata una classe specifica per
gestire ogni tipo di dato.
Per chi fosse abituato ai template del C++
la più grande differenza che si incontra è si-
curamente l’impossibilità di scrivere codice
che potenzialmente non compila durante la
fase di istanziazione. Si supponga ad esem-
pio di volere aggiungere alla classe Stack un
metodo PopCopy() che ritorna una copia del-
l’oggetto in cima allo stack senza rimuover-
lo dallo stack stesso. In questo modo il chia-
mante può utilizzare la copia senza andare a
modificare l’istanza originaria. Una prima im-
plementazione potrebbe essere:
public T PopCopy() {
if (Peek()) return (T)basearray[stackPos-1].Clone();
throw new IndexOutOfRangeException(“Stack is empty”);
}
Questa funzione semplicemente chiama il
metodo Clone() del tipo generico T per ottene-
re una sua copia, ma in fase di compilazione
si genera un errore perché il tipo generico T
non ha una definizione per il metodo Clone().
Questo può apparire ragionevole per chi non
conosce il C++, anche perché la programma-
zione generica dovrebbe essere appunto “ge-
nerica” e non basarsi su metodi che sono in-
vece specifici di alcuni oggetti.
In C++ invece un codice analogo è perfetta-
mente legale e gli eventuali errori sono posti-
cipati al momento in cui si istanzia il template.
Se anche in C# fosse valido questo approccio,
si avrebbe la seguente situazione: MyStack<int> non compila perché il tipo int non ha il meto-
do Clone(), ma un MyStack<System.Array> compi-
lerebbe senza problemi perchè gli array sup-
portano l’interfaccia ICloneable.
C #
Naturalmente il framework.NET prevede ne-
cessità simili e il codice precedente può esse-
re utilizzato corettamente a patto che venga
rassicurato il compilatore sull’esistenza del
metodo T.Clone(). Con il .NET infatti un tipo
generico T dichiarato come nel Listato1 viene
chiamato Unbounded type parameter ad indicare
che non sono state specificate restrizioni. In
pratica si può pensare che sia lecito utilizzare
il tipo T in ogni situazione in cui sarebbe leci-
to utilizzare un generico object, ma non oltre,
è per questo che non si può assumere che il
tipo T supporti il metodo Clone(). Questa li-
mitazione può essere superata introducendo
delle restrizioni, ad esempio dichiarando la
classe in questo modo:
class MyStack2<T> where T:ICloneable {
La clausola where serve per aggiungere delle
restrizioni al tipo T; in questo esempio si ri-
chiede di implementare l’interfaccia ICloneable.
Con questa modifica il metodo PopCopy() vie-
ne compilato correttamente, dato che il com-
pilatore è ora certo che il tipo T possieda il
metodo Clone().
Le limitazioni che si possono imporre sono
di cinque tipi. Si può richiedere che il tipo T
sia una classe o una struct, utile ad esempio
per evitare operazioni eccessive di boxing ed
unboxing o comunque per capire come ge-
stire le copie degli oggetti. Un’altra restrizio-
ne è richiedere invece che l’oggetto abbia un
costruttore di default, utile se la classe deve
creare istanze di un tipo generico. Infine si
può richiedere che il tipo erediti da una par-
Non solo le classi, ma
anche le interfacce ed i
delegate possono essere
resi generici
49N. 70 - Luglio/Agosto 2006 VBJ
ticolare classe o implementi una data inter-
faccia, l’esempio appena mostrato ricade in
questo ultimo caso.
La programmazione generica non si limita
però alle classi, anche le interfacce possono
infatti essere rese generiche in modo da spe-
cificare più efficacemente alcune particolari
capacità di un oggetto, come ad esempio il fat-
to di essere una lista. Con il .NET 1.1 l’inter-
faccia IList racchiude una serie di metodi che
identificano un oggetto di tipo lista, con l’in-
troduzione dei generics è ora presente anche
la controparte IList<T> che identifica invece
una generica lista di oggetti T. Questa funzio-
nalità è assolutamente necessaria, alcune vol-
te infatti si deve iterare su di un contenito-
re di cui non si conosce il tipo esatto. Se non
si avesse a disposizione un interfaccia gene-
rica, si dovrebbe trattare l’oggetto come una
IList perdendo i vantaggi della programma-
zione generica.
Metodi genericiLa programmazione generica può essere
adottata anche nei singoli metodi di una clas-
se, ad esempio per dichiarare parametri gene-
rici anche quando la classe non è essa stessa
generica. Si supponga ad esempio di estende-
re la classe MyStack, fornendo all’utente un
metodo con cui riversare il contenuto di uno
stack in un altro stack. Una prima implemen-
tazione potrebbe essere la seguente:
public void PushStack(MyStack<T> stack) {
while (stack.Peek()) {
this.Push(stack.Pop());
}
}
Questo metodo, sebbene sembri corretto ad
un primo esame, non gestisce correttamente
l’ereditarietà. Si supponga di creare una classe
MyString da cui si fa ereditare una seconda clas-
se MyString2. Se si crea un MyStack<MyString> è
possibile passare nel metodo Push() un ogget-
to di tipo MyString2, dato che ereditando da
MyString ne mantiene la sua interfaccia. Pur-
troppo questo comportamento non è mante-
nuto dal metodo PushStack(), si potrebbe in-
fatti rimanere stupiti del fatto che il compila-
tore non permette di passare a questo metodo
un parametro di tipo MyStack<MyString2>.
Analizzando attentamente la situazione que-
sto comportamento è indubbiamente corretto,
per una classe MyStack<MyString> il meto-
do PushStack() accetta infatti un parametro di
tipo MyStack<MyString> che è sicuramente
differente da MyStack<MyString2>.
Il problema deriva dal fatto che, sebbene sia
possibile utilizzare un oggetto MyString2 al
posto di un MyString a causa della relazione
di ereditarietà, le due differenti istanze dello
stack non sono legate da nessuna relazione. Il
fatto che MyString2 erediti da MyString non
implica infatti che MyStack<MyString2> ere-
diti da MyStack<MyString> e neppure che
sia ammissibile una conversione implicita.
La soluzione a questo problema è rendere
il metodo Push2() generico facendolo dipen-
dere da un altro tipo chiamato U, imponendo
come constraint la derivazione dal tipo base
T. La dichiarazione corretta è pertanto la se-
guente.
public void PushMyStack<U>(MyStack2<U> stack) where U :
T {
while (stack.Peek()) {
this.Push(stack.Pop());
}
}
In questo modo la dichiarazione indica che il
C #
La programmazione
“generica”, a dispetto del
suo nome, rinforza la
tipizzazione
50 VBJ N. 70 - Liglio/Agosto 2006
C #
metodo PushMyStack() dipende dal tipo gene-
rico U, il quale ha come restrizione la discen-
denza dal tipo T, ovvero il tipo base generico
della classe MyStack. Il parametro accettato
da PushMyStack () è dichiarato ora come un
oggetto di tipo MyStack2 parametrizzato sul
tipo generico U. In questo modo si dichiara
in pratica che il metodo PushMyStack () ac-
cetta come parametro un MyStack tipizzato
su un oggetto che eredita dal tipo T.
Quando si chiama un metodo generico è pos-
sibile infine specificare al compilatore il tipo
in maniera esplicita, oppure affidarsi alla de-
duzione automatica o inferenza. Se ad esempio
si crea un metodo Swap() generico in grado
di invertire il contenuto di due variabili ge-
neriche:
Public static void Swap<T>(ref T par1, ref T par2) {
T temp = par1;
Par1 = par2;
Par2 = temp;
}
Lo si può indifferente invocare in uno dei
due modi.
Int var1 = +1;
Int var2 = -1;
Swap(ref var1, ref var2); //1
Swap<int>(ref var1, ref var2); //2
Altre particolaritàAnche un delegate può essere generico, l’uti-
lità più grande è il poter finalmente definire
in maniera più semplice eventi strongly typed
seguendo il pattern consigliato nel .NET fra-
mework. Questo tipo di pattern consiste nel-
l’utilizzare delegate in cui il primo parame-
tro è un riferimento all’oggetto che genera
l’evento stesso, mentre il secondo argomen-
to è un oggetto che contiene tutti i parametri
necessari per la gestione dell’evento e deve
sempre discendere dalla classe base EventAr-
gs. In .NET 1.1 questo fa si che ogni tipo di
evento ha potenzialmente un argomento dif-
ferente e quindi si vengono a creare un nume-
ro molto elevato di delegate. Con il .NET 2.0
è possibile invece utilizzare il delegate base
di nome System.EventHandler<TEventArgs>. Cosi
facendo il framework può gestire ogni even-
to con un singolo tipo di delegate.
Naturalmente l’introduzione dei generics
porta molte aggiunte alla reflection. Il tipo
System.type ha infatti una serie di metodi
dedicati alla gestione dei tipi generici tra cui
ricordiamo IsGenericType() che serve per de-
terminare a runtime se un tipo è generico o
meno oppure il GetGenericArguments() che recu-
pera un array di oggetti type utilizzati come
parametri generici. Addentrarsi nella reflec-
tion sui tipi generici è però argomento com-
plesso che esula da una panoramica introdut-
tiva e può essere approfondito efficacemen-
te nell’msdn.
ConclusioniL’introduzione dei generics è sicuramen-
te una delle innovazioni più importanti del
.NET 2.0 perché rende possibile l’utilizzo del-
le tecniche di programmazione generica che
portano a scrivere codice più leggibile con
una drastica riduzione del numero di cast,
di classi contenitore strongly typed e di co-
pia e incolla.
Il supporto alla programmazione generica è
fornito direttamente dal framework e per que-
sto è disponibile per tutti i linguaggi, sebbe-
ne ognuno di essi possa comunque adottare
una sua sintassi specifica. I concetti base sono
inoltre universali e quanto visto in questo ar-
ticolo riguardo al C# si adatta naturalmente
anche al Visual Basic e a qualsiasi altro lin-
guaggio managed che decida di supportare la
programmazione generica.
52 VBJ N. 70 - Luglio/Agosto 2006
Common Time mSuite Security
Creare applicativi sicuri per dispositivi
mobile non è così facile.
L’afflusso di tali dispositivi non di pro-
prietà dell’azienda è causa di preoccupazione per
tre aree distinte: per la proprietà dell’azienda, per
il meccanismo di supporto, e in definitiva per gli
utenti stessi.
Perché ciò rappresenta un problema?
Perché i dispositivi hanno, e avranno in un pros-
simo futuro, uno storage locale.
Una possibile risposta a questo problema di sicu-
rezza potrebbe essere: “Non abbiamo necessità di
uno storage locale. Le reti wireless hanno una am-
pia larghezza di banda, non sono soggette a inter-
ruzioni di rete, hanno una copertura mondiale del
100%, e non sono costose.
Tuttavia, questa risposta non è corretta. La realtà
non è affatto quella descritta.
I dispositivi client dovranno semplicemente man-
tenere i dati localmente, e gli sviluppatori di appli-
cazioni devono continuare a supportare gli scenari
talvolta online, talvolta offline. Finché l’utopia di
un dispositivo mobile “stupido”, di una copertura
di rete del 100%, e di una infrastruttura a basso co-
sto non è una realtà, continueremo ad avere questi
rischi nella sicurezza.
La “trinità della sicurezza” riguarda la protezione
dei dati e dei dispositivi in tre aree: nel dispositi-
vo, nella trasmissione dei dati, e infine nei sistemi
business della sede aziendale.
Qualsiasi azienda che conside-
ra seriamente la propria strate-
gia di sicurezza deve rispondere
alle seguenti domande:
• Protezione dei dispositivi
Chi è autorizzato a utilizzare il
dispositivo?
È disponibile la versione più
recente dell’applicazione?
Le firme dell’antivirus sono ag-
giornate e l’applicazione antivi-
rus è in esecuzione?
I dati sono memorizzati sul di-
spositivo in un formato sicuro?
Se un dispositivo viene perso
o sottratto, i dati memorizzati
sono accessibili?
Se un dispositivo viene sottrat-
to, o in caso di tentativi di lo-
gin non autorizzati, si possono
rimuovere i dati sicuri?
• Protezione durante il
transito
Come sono protetti i dati du-
rante il transito tra l’utente e
l’azienda?
• Protezione aziendale
Se un dispositivo viene perso,
qualcuno può utilizzarlo per in-
trodursi nei sistemi aziendali?
Come si può essere certi di chi
I principali elementi funzionali e operativi di mSuite Security, prodotto dalla
CommonTime, con particolare attenzione alla sicurezza
© 2006 CommonTime Limited
MOBILE
53N. 70 - Luglio/Agosto 2006 VBJ
mondo esterno”, dovrà essere più che certa
di chi si connette all’infrastruttura, e di qua-
li servizi sono accessibili. L’autenticazione dei
dispositivi client permette al server di veri-
ficare l’utente, e di autorizzarlo ad un parti-
colare servizio di rete, prima di continuare a
instradare la sessione.
AutenticazioneConnection Manager Server: Il processo prin-
cipale di autenticazione avverrà nel Connec-
tion Manager Server (CMS). Questo compo-
nente server fornisce 5 funzioni in mSuite:
• Autenticazione
• Autorizzazione
• Routing del processo server
• Comunicazione client
• Crittografia “over the air”
Con crittografia (Standard): La suite di codi-
ci crittografici (AES 128,192,256) disponibile
si sta connettendo alla propria infrastruttu-
ra?
Come si può fornire una sicurezza diretta
o delle patch di fix, senza alcun intervento
dell’utente?
Come si può essere certi che un dispositivo
sia abbastanza sicuro per permettergli di con-
nettersi alla rete?
Il dispositivo sta introducendo virus nell’am-
biente aziendale?
mSuite Security è un prodotto concepito
per fornire le risposte proprio a queste do-
mande.
Funzionalità
Gestione dell’identità del client: protezione dell’azienda
Poiché un’azienda cercherà spesso di po-
sizionare la propria rete dietro i confini del
firewall proteggendosi dall’insicuro “sporco
MOBILE
Fi gu ra 1 Architettura di mSuite Security
54 VBJ N. 70 - Luglio/Agosto 2006
MOBILE
I moduli di mSuite
mSuite Mobility FrameworkIl framework offre una base sicura per l’ambiente mSuite, incorporando alcuni dei componenti di comunicazione e
configurazione modulare elencati di seguito.
mSuite Administration Console
Fornisce un punto centrale di gestione attraverso uno snap-in Microsoft Management Console (MMC). Garantisce una
semplice configurazione attraverso l’ereditarietà di oggetti gruppi e utenti.
La complessità di impostazione viene minimizzata grazie a un Configuration Wizard e all’Help contestuale.
Configuration Server
Fornisce l’accesso al database mSuite di tutti i prodotti mSuite. Questo database contiene la configurazione, i report e le
politiche richieste per eseguire un ambiente mSuite.
Connection Manager Server (CMS)
Il CMS funge da servizio principale di comunicazione per mSuite. Fornisce cinque funzioni:
• Autenticazione client
• Instradamento del servizio
• Ottimizzazione della comunicazione
• Comunicazioni con mSuite Server
• Crittografia AES “over the air”
mNotes Server
Fornisce la sincronizzazione desktop, server e wireless delle email, dei calendari, dei task, dei contatti e del journaling Lotus
Notes/Domino compreso il supporto completo della funzionalità di calendario e dio scheduling per i gruppi di utenti.
mForms Server
Fornisce un sistema RAD di progettazione, testing, implementazione, deployment e gestione delle applicazioni business
per i dispositivi portatili. Attualmente, mForms funziona con l’ambiente CE/Windows Mobile, ma è prevista l’estensione del
supporto ad altri sistemi operativi per dispositivi come Palm e Symbian.
mControl
Fornisce il deployment dell’applicazione, la manutenzione continua e la gestione di politiche per singolo utente di dispositivi.
mSecure PDA
Fornisce la sicurezza fisica delle informazioni memorizzate sul dispositivo. I dati salvati sul dispositivo possono essere
crittografati e il dispositivo può essere protetto dall’utilizzo non autorizzato. Inoltre, l’utilizzo delle applicazioni può essere
autorizzato per un particolare dispositivo, o essere protetto da password.
mNotes Adapter for Thin Clients
Il modulo mNotes Adapter for Thin Clients fornisce all’utente un’esperienza migliorata, spostando sul server alcuni compiti
CPU-intensivi, piuttosto che tentando di svolgerli lato client. L’Adapter viene utilizzato sia con client Palm sia Symbian.
Notification Server
Il Notification Server fornisce le interfacce UDP o SMS a un dispositivo remoto per la trasmissione di piccoli pacchetti di dati
asincroni (datagram) utilizzati per avviare la connessione ai server mSuite per poi procedere alla trasmissione delle ulteriori
informazioni. Ciò può accadere in conseguenza a un processo business, all’arrivo delle email, o a un processo reattivo, o per
fornire l’infrastruttura di “azzeramento dati” nel caso un dispositivo fosse sottratto. In caso di spegnimento del dispositivo,
la richiesta di notifica verrà accodata, e attenderà il dispositivo, o nel caso un SMS “svegli” il dispositivo per processare il
datagram.
55N. 70 - Luglio/Agosto 2006 VBJ
per le aziende che desiderano rendere sicura
la connessione client/CMS di tutto il traffico
mSuite. Se già si gestisce un’infrastruttura
VPN idonea per l’utilizzo dei PDA, si può di-
sabilitare la suite di codici crittografici sup-
portata dal Connection Manager
Autenticazione CMS (Standard)Utilizzando l’autenticazione standard in Con-
nection Manager Server, l’autenticazione vie-
ne richiesta alla connessione della sessione,
viene passata a CMS utilizzando un mecca-
nismo “shared-secret” e viene confrontata ri-
spetto a una combinazione nota nome utente/
MOBILE
password presente nel database mSuite. Que-
sto processo avviene nel tunnel protetto da
AES (a meno che la crittografia non sia disa-
bilitata), fornendo un secondo livello di crit-
tografia per queste credenziali. La password
è memorizzata nel database mSuite in un for-
mato irreversibile.
Autenticazione CMS (RADIUS)In alternativa all’autenticazione mCenter, il
CMS permetterà che l’autenticazione sia ese-
guita rispetto a un database esistente di cre-
denziali. In tal caso, il CMS funge da client
RADIUS e inoltra le richieste di autenticazio-
ne per la verifica esterna.
Remote Authentication Dial-In User Service
(RADIUS) è un protocollo standard che abilita
i server di accesso remoto a comunicare con
un server centrale per autenticare gli utenti
dial-in e ad autorizzarne l’accesso al sistema
o al servizio richiesto. Internet Authentica-
tion Service (IAS) è l’implementazione Mi-
crosoft di RADIUS, e offre attualmente il sup-
porto per NTLM o per AD (Active Directory).
Inoltre, IAS presenta delle estensioni (IASE)
per permettere agli sviluppatori di estende-
re ulteriormente IAS. Un tipico server RA-
DIUS opererà utilizzando i metodi descritti
qui di seguito:
o PAP funziona allo stesso modo di una
normale procedura di login. Il client si auten-
tica inviando al server un nome utente e una
password (opzionalmente crittografata), che il
server confronta con quella presente nel pro-
prio database. Questa tecnica è vulnerabile
agli attacchi di “eavesdropping” (ossia di chi
può cercare di ottenere la password ponendo-
si in ascolto sulla riga seriale o sulla connes-
sione IP) e anche ad attacchi iterati per ten-
tativi.
o A differenza dell’autenticazione PAP,
il protocollo CHAP (Challenge Handshake Au-
thentication Protocol), invia al client una strin-
ga di “challenge” generata in modo random,
unitamente al nome dell’host. Il client utiliz-
za il nome dell’host per ricercare il secret ap-
propriato, la unisce alla parte “challenge”, e
codifica l’intera stringa utilizzando una fun-
I moduli di mSuite
Componenti mControl Tutti gli aspetti di mControl (sicurezza centralizzata,
policy di deployment e gestione della configurazione
dell’applicazione) sono relativi ai seguenti servizi:
Device Management Server
Funziona in combinazione con il Client Agent Proxy (CAP)
per fornire al dispositivo l’accesso al server. È utilizzato
dal prodotto mControl per eseguire il deployment delle
policy dell’applicazione. Il Device
Management Server fornisce anche tutte le funzionalità
di controllo dell’applicazione mControl e del dispositivo.
Client Agent Proxy (CAP)
Il Client Agent Proxy fornisce l’accesso al Device
Resident Agent (DRA), permettendo la manipolazione
del registry del dispositivo, del filesystem e object
store. Qualsiasi applicazione mSuite che richiede queste
modifiche o il deployment delle policy utilizzerà il Client
Agent Proxy per ottenere ciò.
Piattaforme supportate
Server
Windows 2000
Windows 2003
Windows NT4.0
Client
Pocket PC
Pocket PC 2002
Windows Mobile 2003
Pocket PC 2002 Phone Edition
Pocket PC 2003 Phone Edition
Windows Mobile Smartphone 2002
Windows Mobile Smartphone 2003
Palm OS 3.5 e versioni successive
56 VBJ N. 70 - Luglio/Agosto 2006
zione hash non invertibile. Il risultato viene
restituito al server unitamente al nome del
client. A questo punto, il server esegue lo stes-
so calcolo, e riconosce il client se giunge allo
stesso risultato. Inoltre, CHAP non richiede
al client di autenticarsi solo alla prima con-
nessione, ma invia le stringhe “challenge” ad
intervalli regolari per esser certo che il client
non sia stato sostituito da un utente non au-
torizzato.
Perché il CMS si comporti da client RADIUS
nell’ambito della propria funzione di provider
di autenticazione, il client RADIUS deve es-
sere registrato sul server RADIUS.
Parte di questa procedura riguarda l’inseri-
mento di un secret condiviso sia sul server RA-
DIUS sia sul CMS. In genere, si raccomanda
che ciascun secret condiviso sia una sequenza
aleatoria, lunga almeno 22 caratteri, di lette-
re maiuscole e minuscole, numeri e caratteri
di punteggiatura. Per assicurare l’aleatorie-
tà si utilizza un programma di generazione
random dei caratteri per creare i secret condivi-si. Un secret condiviso è case-sensitive. Ulteriori
informazioni su RADIUS sono reperibili nei
documenti RFC 2865 e 2866 dell’Internet En-
gineering Task Force (IETF)
Compromesso tra usabilità e funzionalità
Le aziende si trovano ad affrontare diversi
problemi specifici con la sicurezza mobile. Un
motivo principale del fallimento di un pro-
getto è la mancanza di interesse da parte de-
gli utente poiché si tratta di una applicazio-
ne tediosa con cui lavorare. Tuttavia, a causa
della natura dei dispositivi mobile, è necessa-
rio un maggior livello di protezione rispetto
a un dispositivo fisicamente protetto presen-
te nella sede dell’azienda.
Il ticketing allevia il processo di riautentica-
zione permettendo a un dispositivo di connet-
tersi per un certo periodo di tempo dopo che
è stata stabilita l’identità dell’utente, permet-
tendo all’utente di lavorare indisturbato per
un certo periodo, pur mantenendo una comu-
nicazione di autenticazione sicura.
Il ticketing elimina anche il vincolo che sia
memorizzata una password su un dispositi-
vo.
Un ticket CMS assume la forma di token sicu-
ro basato sul client con diversi attributi, com-
presa una chiave di sessione e un periodo di
validità (scadenza). Un ticket sarà valido per
una particolare community di autenticazione,
permettendo a più credenziali di esistere sul
client sotto forma di multi-ticket.
Questi gli attributi del ticket:
o Ticket opaco (opaque ticket): Si trat-
ta di una credenziale pass-through, non com-
prese dal PDA. Permette alle informazioni di
autenticazione di essere trasferite in modo si-
curo dal server di autenticazione ad altri ser-
vizi che autorizzeranno l’utente.
o Chiave di sessione (session key): È una
chiave univoca generata dal server. Piuttosto
che memorizzare le credenziali del client, la
chiave di sessione è un puntatore “all’indie-
tro” alle credenziali memorizzate sul server,
impedendo il reverse engineering delle cre-
denziali del client. Il client deve presentare
questa chiave nel riconnettersi al Connection
Manager Server (CMS). Altre infrastrutture
mobile operano in base al concetto di chiave
una tantum assegnata a un dispositivo, chia-
ve che rimarrà valida sul dispositivo per l’in-
tero ciclo di vita. Implementando una chiave
di sessione invece di questa “chiave di dispo-
sitivo”, il CMS permette a una chiave critto-
grafica che cambia di frequente di assicura-
re una sicurezza estesa.
o Periodo di validità del ticket (ticket va-
lidity period): Il periodo di tempo durante il
quale a una combinazione utente/dispositivo
è permesso accedere ai servizi di una com-
munity di autenticazione senza riautenticar-
si. Questo valore è configurabile sul server,
ma tipicamente varia da un’ora a un giorno.
o Processo di autenticazione: Quando
MOBILE
57N. 70 - Luglio/Agosto 2006 VBJ
MOBILE
un client richiede una sessione al Connection
Manager Server (CMS), il CMS passa prima
questa richiesta a un server di autenticazio-
ne, definito nella configurazione del CMS. Si
tenga presente che potrebbe trattarsi di un
processo nello stesso CMS o che risiede su
un server remoto, in base alle impostazioni.
A questo punto al client viene uno dei se-
guenti attributi:
• Combinazione Username/Password
• Username/Ticket di autenticazione
valido
Una volta avvenuta la presentazione corret-
ta di uno di questi attributi, il CMS procede-
rà ad eseguire l’instradamento al servizio ri-
chiesto.
Crittografia dei dati: proteggere i dati in transito
Qualsiasi azienda è alle prese con la sfida di
fornire un’infrastruttura mobile che sia pron-
tamente disponibile e che tuttavia garantisca
dei costi accessibili. Per questi motivi molti
utilizzano Internet come mezzo di comunica-
zione. Implementando una soluzione Internet,
la connettività può essere raggiunta da più
Internet provider, dalle stanze di un hotel via
GPRS o GSM. Questa flessibilità ha un prezzo
per ciò che concerne lo spostamento dei dati
su una rete non protetta, e di conseguenza non
andrebbe considerata senza aver predisposto
una infrastruttura di crittografia.
Molte aziende stanno installando una solu-
zione VPN (Virtual Private Network) per più
aree della propria attività, permettendo l’ac-
cesso a reti protette da IPSec da qualsiasi di-
spositivo.
Per le aziende che desiderano adottare una
infrastruttura di messagistica protetta e di ge-
stione senza dover investire nelle comunica-
zioni VPN, mSuite Mobility Framework forni-
sce l’autenticazione, l’autorizzazione e la crit-
tografia AES tra il client e il Communication
Manager Server (CMS)
CMS: crittografia AES Lo standard Advanced Encryption Standard
(AES) è stato determinato in base a un’analisi
dei formati crittografici effettuata da 15 orga-
nizzazioni participanti. Il NIST (National In-
stitute of Standards and Technology) america-
no ha scelto l’algoritmo Rijndael come formato
AES. A differenza di DES, lo standard AES
non espone alcun punto di debolezza noto del
codice di cifratura. I confronti del NIST rispet-
to a DES dimostrano che se un cracker DES
via hardware può “craccare” una chiave DES
in un secondo, sarebbero necessari 149 “tri-
lioni” di anni per il crack di una chiave AES
a 128 bit. L’implementazione AES della Com-
monTime si basa sul Security Builder di Cer-
ticom, e la crittografia AES si attiene al docu-
mento Federal Information Processing Stan-
dard (FIPS) 197.
CertificatiCome si è discusso precedentemente, uno dei
punti di forza del CMS è la capacità di gene-
rare una nuova chiave AES per ogni sessio-
ne, piuttosto che riutilizzare una chiave ge-
nerata una tantum.
A causa della frequente generazione di que-
ste chiavi, va considerata la protezione nello
scambio della chiave Diffie–Hellman dagli at-
tacchi di tipo “Man in the Middle”. Una cop-
pia costituita da una chiave server e da una
corrispondente chiave client elimina questo
rischio.
Questo certificato server deve essere disponi-
bile nell’account di memorizzazione del certi-
ficato sulla macchina locale, la macchina su
cui è in esecuzione il Connection Manager
Server (CMS).
I certificati vengono inviati ai singoli e alle
aziende da organizzazioni riconosciute e fida-
te, dette Certificate Authority (CA)
La mSuite Console e il CMS devono avere
accesso a un certificato che abbia una chia-
ve privata accessibile dal server (non necessa-
riamente una chiave esportabile). Per la ver-
58 VBJ N. 70 - Luglio/Agosto 2006
MOBILE
sione corrente, si deve trattare di certificati
RSA MD5.
Sicurezza del dispositivo: protezione dei dati (lato dispositivo)
Il furto e lo smarrimento rappresentano del-
le minacce associate all’adozione di disposi-
tivi enterprise sul campo. L’attrazione spesso
scintillante di un PDA o di uno Smartphone
ha un effetto “gazza ladra” sugli opportuni-
sti, e benché ci sia ben poco da fare a parte
il senso comune per ciò che concerne il fur-
to del dispositivo, va data considerazione al
reale valore del dispositivo: i dati in esso me-
morizzati.
Queste precauzioni devono essere tenute
presenti:
• Adottare una password “forte” per ese-
guire il login al dispositivo
• Assicurare la protezione contro la sin-
cronizzazione non autorizzata
• Assicurare che i dati siano memoriz-
zati in formato crittografato su tutti i dispo-
sitivi di memorizzazione
• Garantire che i dati siano azzerati in
caso di furto o smarrimento
• Assicurare che il dispositivo sia sicu-
ro da attacchi di rete
• Assicurare le applicazioni possano es-
sere protette
• Assicurare che il dispositivo non con-
tenga codice subdolo, che impatti la rete.
Benché i meccanismi di autenticazione di
mSuite Connection Manager proteggano
l’azienda dall’accesso non autorizzato e veri-
fichino l’identità, una password personale sarà
necessaria per proteggere il dispositivo.
Il vantaggio di una mSecure PDA Password
è che questa viene definita dall’utente, ma la
policy viene imposta centralmente.
Attraverso la mSuite Administration Con-
sole, è disponibile il controllo centrale del-
la policy per i seguenti attributi della policy
di sicurezza:
Politica di distruzione dei dati
Se un dispositivo viene sottratto, un’azienda
può dover considerare come il dispositivo si
comporterà nelle mani di un utente non au-
torizzato. Le applicazioni in esecuzione nel
mobility framework, possono essere suppor-
tate da funzionalità di azzeramento dei dati
in due possibili scenari:
Azzeramento in caso di login fallitoLa procedura di azzeramento assicura che
i dati sul dispositivo vengano resi irrecupe-
rabili, azzerando le aree crittografate defini-
te, tra cui:
• Storage esterno
• Qualsiasi storage interno non-volatile
(come il File Store dell’IPAQ)
E infine restituendo un dispositivo nello sta-
to delle impostazioni di fabbrica.
“Pillola letale”, azzeramento remoto, blacklist
mControl offre la possibilità di utilizzare i
servizi di Notification del mobility framework
per assicurare che un dispositivo sia sempre
contattabile, via TCP/IP su GPRS/Wi-Fi ecc.
o via messaggi SMS per dispositivi che chiu-
dono la connessione IP.
Questa caratteristica permette un pronto
hard reset da remoto del dispositivo, spe-
cie nel caso di smarrimento o sottrazione del
dispositivo. Altri meccanismi di protezione
come le blacklist forniscono una protezione
contro la rimozione intenzionale della scheda
SIM. Se il dispositivo si riconnette all’infra-
struttura, l’ID del dispositivo resta in blacklist,
e il PDA verrà immediatamente sottoposto ad
un hard reset.
59N. 70 - Luglio/Agsoto 2006 VBJ
Crittografia dei dati: protezione dei dati sul dispositivo
La protezione dall’accesso ai dispositivi mo-bile è sufficiente solo fino a un certo punto.
Gran parte dei PDA hanno una modalità di
manutenzione o la possibilità di eseguire il
dump dell’intero dispositivo su un singolo
file per mezzo dell’interfaccia seriale. Ciò ha
il vantaggio di rendere il dispositivo facilmen-
te flash-aggiornabile, ma comporta l’introdu-
zione di una breccia nella sicurezza.
Molti dispositivi hanno anche supporti di sto-
rage removibili preferiti a causa della natura
non volatile. Questi dispositivi di storage re-
movibili presentano anche un rischio consi-
derevole a causa della limitate dimensioni e
quindi della agevole portabilità.
È proprio tenendo conto di questi punti che
la crittografia dei dati locali va considerata
essenziale.
Crittografia rapida vs. crittografia sicura
Uno degli errori più comuni che si commette
nell’utilizzo delle applicazioni di crittografia è
“attivare tutto”, senza rendersi conto di ciò che
esattamente significa crittografare tutto.
La crittografia non è mai senza costo, par-
ticolarmente nei dispositivi di calcolo limi-
tati. Questo sovraccarico delle prestazioni
può essere significativo se non ci si attiene
al buon senso.
La prima fase di implementazione della crit-
tografia locale è comprendere quali dati sono
da ritenersi “necessari da proteggere”. Dopo
aver definito i dati protetti, vanno fatte delle
considerazioni sul se seguire un approccio che
fornisce una completa crittografia AES a 256
bit o se richiedono un algoritmo crittografico
ad alte prestazioni che funziona rapidamente
pur garantendo un livello di sicurezza.
Proteggere il dispositivo: applicazioni
Poiché un’azienda può aver necessità di li-
mitare le applicazioni che possono essere ese-
guite sul dispositivo, mSecure PDA mantiene
facoltativamente un elenco centralizzato del-
le applicazioni non autorizzate ad essere ese-
guite sul dispositivo.
Questo meccanismo funziona intercettando
qualsiasi tentativo di eseguire file eseguibili
attraverso le scorciatoie o attraverso un file
explorer, e utilizzando una tabella di lookup di
autorizzazione per determinare se a un uten-
te è permesso eseguire questo file.
Qualsiasi tentativo di accesso a una appli-
cazione non approvata presenterà un dialogo
che spiega che l’applicazione non è autoriz-
zata, e richiederà a un amministratore il per-
messo di utilizzo dell’applicazione.
Questa tecnica è stata utilizzata ad esempio
per impedire ai dipendenti di accedere ai gio-
chi, alla configurazione o anche a Internet, di-
sabilitando Internet Explorer.
Come tutti i componenti mSuite, questo uti-
lizzo può essere implementato a livello di root,
di gruppo o di utente.
Anche gli aggiornamenti del Registry o del
MOBILE
Fi gu ra 2 Autorizzazione fallita di esecuzione
applicazione
60 VBJ N. 68 - Marzo/Aprile 2006
database di configurazione possono essere
gestiti da una policy centralizzata, così come
gran parte degli aggiornamenti delle policy
vengono memorizzati in queste aree.
mControlLa sicurezza condivide una relazione sim-
biotica con la gestione del dispositivo. Non si
può realmente imporre la sicurezza senza es-
sere in grado di installare, controllare e ma-
nutenere il dispositivo. È anche vero che la
gestione ha pochissimo effetto se il disposi-
tivo non viene mantenuto in uno stato sicu-
ro. Il componente mControl di mSuite ha lo
scopo di mantenere il dispositivo in uno sta-
to valido noto e in definitiva di assicurare che
l’utente mantenga la propria concentrazione
sulle funzioni business senza dover preoccu-
parsi della tecnologia.
I compiti tipici che ostacolano la possibilità
di un utente di lavorare comprendono:
o Perdita di produttività quando si sca-
rica la batteria del dispositivo
o Perdita di produttività nel cercare di
scaricare la recente patch di una applicazio-
ne
o Perdita di produttività dovuta all’in-
troduzione di codice subdolo
o Perdita di produttività dovuta alla ve-
locità con cui un’azienda richiede il cambio
dell’applicazione – la forza lavoro distaccata
può avere necessità di visitare molto raramen-
te la sede centrale, perché ciò dovrebbe cam-
biare a causa della distribuzione o dell’aggior-
namento di un nuovo sistema mobile?
mControl permette una distribuzione gesti-
ta centralmente delle policy di antivirus ai di-
spositivi mobile. Il motore antivirus in genere
viene scelto dall’azienda, e sul server viene
generato un pacchetto software di configura-
zione. Questo pacchetto può essere distribuito
a livello di server o di gruppo, ma può anche
essere abbastanza specifico da essere adatta-
to alle necessità di singoli utenti.
In base al produttore dell’antivirus, il de-
ployment della policy può avvenire in diver-
MOBILE
si modi, tra i quali quello di gran lunga più
semplice è l’ utilizzo dell’opzione “show me” di
mControl dello snapshot dell’applicazione.
Questo approccio permette sia al motore
antivirus sia alla configurazione di essere di-
stribuiti in un unico pacchetto. Una opziona-
le definizione di virus può essere distribuita
a questo punto o essere mantenuta come en-
tità separata.
Le future versioni previste di mControl for-
niranno ai “connettori” antivirus la possibi-
lità di scaricare e installare automaticamente
le definizioni aggiornate direttamente dal sito
Web di un produttore o via FTP e di mante-
nere il controllo e il logging da un unico cen-
tro di gestione.
Come accade per i firewall personali e i pro-
duttori di antivirus, un’azienda ha spesso del-
le preferenze sui fornitori. È perciò importan-
te mantenere un approccio agnostico alla ge-
stione, piuttosto che fornire l’opportunità di
gestire più applicazioni di sicurezza e busi-
ness dalla stessa locazione centrale.
Ogni qualvolta un dispositivo viene presen-
tato a un mSuite Connection Manager Servi-
ce, il primo “servizio dati” a cui si connette-
rà sarà mControl. Ciò permette immediati ag-
giornamenti delle policy e delle impostazioni
prima che al dispositivo sia permesso conti-
nuare con gli altri task e servizi mSuite.
Ciò assicura che un dispositivo abbia una
sufficiente sicurezza prima che gli sia per-
messo di continuare.
Le blacklist sono un metodo di protezione
di un’infrastruttura dall’accesso non autoriz-
zato. Il processo di disabilitare un particola-
re dispositivo, anche se le credenziali utente
sono corrette, permette a un amministrato-
re di bloccare i dispositivi smarriti o sottrat-
ti, o anche di inviare da remoto un comando
di azzeramento per mezzo di una rete wire-
less o via SMS.
.NET TO OLS
61N. 70 - Luglio/Agosto 2006 VBJ
NDocdi Raffaele Di Natale
Il tool più utilizzato (ed atteso) per la
produzione di documentazione del codice
negli standard più diffusi
NDoc si è affermato negli ultimi anni come
uno dei tool più diffusi per la produzione di
documentazione automatica del codice. Ciò
è accaduto non solo perché è gratuito, ma
soprattutto per la sua efficienza, stabilità
e capacità di produrre una completa
documentazione basata su HtmlHelp, piuttosto
che Html 2.0 o in formato Latex. Purtroppo
l’ultima release risale al gennaio del 2005 e con
l’uscita di Visual Studio 2005 (e l’incremento
di applicazioni basate sul .NetFramework
2.0) sono venuti alla luce tutti i limiti di
un’applicazione ferma ormai al capolinea da
troppo tempo.
Scopo dell’applicazioneNDoc [1] genera la documentazione riguardante
librerie di classi utilizzando essenzialmente
gli assembly .NET e i file XML prodotti
automaticamente dall’ambiente Visual Studio
(già a partire dalla versione 2003). Inizialmente
il supporto XML era previsto solo per progetti
in C# e per VB .NET era necessario installare
un tool aggiuntivo denominato VBCommenter
[2]. Con la versione 2005 anche questo gap è
stato superato.
PrerequisitiNDoc richiede il .NET Framework 1.0 o 1.1. In
un successivo paragrafo si proporranno alcuni
workaround per eseguire NDoc, con alcune
limitazioni, anche in ambito .NET Framework
2.0.
Tag per la documentazione XML
Per poter utilizzare la documentazione XML
di una libreria di classi bisogna rispettare
la sintassi prevista: in C# il commento deve
essere del tipo:
/// <tag> testo </tag>
mentre in VB .NET sarà:
’’’ <tag> testo </tag>
In C# potremmo, per esempio, documentare
così il codice di una particolare classe:
using System;
namespace mynamespace
{
/// <summary>
/// Classe d’esempio con documentazione XML per NDoc
/// </summary>
public class myClass
{
/// <summary>
/// L’entry point dell’applicazione
/// </summary>
public static void Main()
{
int a = 2;
Fi gu ra 1 Documentazione in formato HmlHelp della classe myClass
62
.NET TOOLS
VBJ N. 70 - Luglio/Agosto 2006
int b = 3;
int c = myFunc(a, b);
Console.WriteLine(“il prodotto è: “ + c);
}
/// <summary>
/// MyFunc effettua il prodotto tra a e b
/// </summary>
/// <param name=”a”>primo parametro</param>
/// <param name=”b”>secondo parametro</param>
/// <returns>In risultato dell’operazione</returns>
/// <example>
/// <code>
/// int a = 2;
/// int b = 3;
/// int c = myFunc(a, b);
/// Console.WriteLine(“il prodotto è: “ + c);
/// </code>
/// </example>
public static int myFunc(int a, int b)
{
return a * b;
}
}
}
Nel codice d’esempio sono evidenziati
alcuni tag significativi, quali <summary> per il
sommario, <param> per l’elenco dei parametri
della funzione e <code> per descrivere un
blocco di codice da fornire come esempio nella
documentazione. La Figura 1 rappresenta
l’output in formato MSDN (HtmlHelp) di
NDoc ottenuto importando l’assembly e il file
XML corrispondenti al progetto di cui sopra.
All’indirizzo [3] è possibile ottenere l’elenco
completo di tutti i tag XML che possono essere
utilizzati per la documentazione del codice.
Configurazione dell’ambiente Visual Studio 2003 e 2005 per
progetti in C#Per entrambi gli ambienti di sviluppo è
necessario configurare le caratteristiche
del progetto corrente affinché possa
essere generato il file XML relativo alla
documentazione. In VS2005 è sufficiente
accedere al menu “Project” e successivamente
cliccare alla voce “Properties…”. A questo
punto non resta che selezionare la voce
“XML documentation file”, come evidenziato
in Figura 2. In VS2003 si accederà sempre
alla finestra di dialogo relativa alle proprietà
del progetto e, dopo aver selezionato “Tutte
le configurazioni” in corrispondenza di
“Configurazione”, bisognerà accedere alla
pagina “Generazioni” della voce “Proprietà di
configurazione “ e qui inserire percorso e nome
del file XML da produrre. Rigenerare sempre
la soluzione dopo aver effettuato le precedenti
modifiche delle impostazioni del progetto al
fine di aggiornare la coppia di file assembly/
file-XML. Verificare infine l’effettiva presenza
di tali file nella cartella /bin del progetto prima
di importarli dall’ambiente NDoc.
Descrizione delle funzionalità principali
Dopo aver creato un nuovo progetto in
ambiente NDoc sarà sufficiente premere
sul pulsante “Add” per aggiungere la coppia
assembly/file XML e produrre successivamente
la relativa documentazione. Ulteriori
parametri di configurazione, elencati nella
finestra principale dell’applicazione, possono
essere utilizzati per personalizzare l’output
dell’applicazione. Tra questi segnaliamo:
• HtmlHelpName, il nome del file chm
finale;
• OutputDirectory, la cartella in cui
verranno salvati i file di help generati
ProdottoNDoc
Url di riferimento http://www.sourceforge.net/projects/ndoc
Versione Release1.3.1
Semplicità d’uso �����Se i commenti al codice sono stati inseriti correttamente, con NDoc basterà premere un pulsante per avere una documenta-zione completa e pronta all’suo.
Utilità �����Le lamentele (tantissime) circa il mancato rilascio della nuova ver-sione palesano la diffusione e l’utilità di questa applicazione. Solo a pagamento si trovano tool confrontabili con questo prodotto.
Qualità prodotto ����� Si tratta di un tool efficiente e stabile
Qualità documentazione �����La documentazione, disponibile solo in lingua inglese, è chiara ed esaustiva e sono forniti anche esempi sull’uso dei tag XML.
63
.NET TOOLS
N. 70 - Luglio/Agosto 2006 VBJ
da NDoc;
• OutputTarget, lo standard di output;
• ShowVisualBasic, se si vuole supportare
anche la sintassi in VB per tipi e
membri.
Per quanto riguarda il campo OutputTarget, NDoc
consente la generazione di documentazione
basata sui più diffusi standard di help
authoring, tra questi:
• LateX (beta)
• HtmlHelp
• Help 2.0
Altre impostazioni riguardano direttamente le
modalità di produzione della documentazione,
le eventuali estensioni mediante fogli di stile
proprietari ed il supporto alla localizzazione.
Infine NDoc mette a disposizione
un’applicazione console denominata
“NDocConsole.exe” che risulta
particolarmente utile nella produzione batch
della documentazione.
NDoc e il .NETFramework 2.0
Come anticipato in precedenza, un grave
limite della versione corrente NDoc è quella
di non supportare il .NET Framework 2.0.
Negli ultimi mesi c’è stato un certo fermento
intorno ad un nuovo progetto, sempre sotto
licenza GPL, denominato NDoc 2005 [4] e che
rappresenta un fork del progetto NDoc tuttora
in versione beta. I lunghi tempi impiegati
dall’autore di NDoc per rilasciare la nuova
versione, con il supporto al .NET Framework
2.0, ha provocato un proliferare di simili
soluzioni. Una seconda soluzione al problema
potrebbe essere quella proposta da [5], anche
se l’affidabilità è tutta da verificare. Un’ultima
possibilità, per consentire a NDoc di interagire
con il .NET Framework 2.0 e che
funziona con le dovute limitazioni,
è quella suggerita in [6]: dopo aver
copiato il contenuto della cartella
/bin/1.1 (percorso di installazione di
NDoc) in /bin 2.0, basterà aggiungere
un nuovo file denominandolo
“NDocGui.exe.config” e contenente
il seguente codice:
<?xml version=”1.0” ?>
<configuration>
<startup>
<supportedRuntime version=”v2.0.50727” />
<supportedRuntime version=”v1.1.4322” />
<requiredRuntime version=”v1.1.4322” />
</startup>
</configuration>
Con questa semplice modifica è possibile
utilizzare NDoc anche sugli assembly
prodotti con VS 2005. È un workaround e non
rappresenta chiaramente una soluzione al
problema, ma consente di produrre comunque
un output accettabile.
E la Microsoft?Il responsabile del progetto NDoc ha
motivato nei forum il perché del mancato
aggiornamento del tool e l’intenzione di
rilasciare la nuova versione entro il 2006.
Il vuoto che si è venuto a creare ha però
indotto molti utilizzatori di NDoc a rivolgere
la propria attenzione verso altre soluzioni
presenti sul mercato, anche a pagamento. La
Microsoft come ha risposto a tutto questo?
Inizialmente non è sembrata preoccupata dai
risvolti: in tanti si sono domandati perplessi
come mai tanto ritardo ad integrare un simile
tool direttamente in ambiente Visual Studio.
A tal proposito consigliamo di leggere [7] in
cui Microsoft chiarisce la propria posizione
rispetto al problema.
ConclusioniCapita spesso di sentire che la migliore
documentazione del codice è rappresentata
dal codice stesso. A questa conclusione si
giunge dopo aver utilizzato uno strumento
avulso dal codice stesso o quanto meno non
perfettamente integrato. Dopo aver provato
Fi gu ra 2 Finestra di configurazione progetto C# in Vs 2005
64
.NET TOOLS
VBJ N. 70 - Luglio/Agosto 2006
ProdottoCodus versione 1.3.1
Url di riferimento http://www.adapdev.com/codus
Sta to ReleaseStabile
Semplicità d’uso �����Non è stata riscontrata alcuna difficoltà nell’utilizzo della sempli-ce, anche se un po’ spartana, interfaccia utente.
Utilità �����L’idea è buona: permette di ridurre drasticamente i tempi di svi-luppo; è necessario adattarlo però alle proprie esigenze
Qualità prodotto ����� Affidabile, nei test sul prodotto eseguiti non ha mai mostrato par-ticolari problemi.
Qualità documentazione �����L’applicazione e la documentazione sono interamente in lingua in-glese; quest’ultima è solo disponibile on line.
tere i parametri della connessione (quali il nome
del database, l’utenza e la password) e (opziona-
le) testare se la connessione ha avuto successo.
A questo punto si caricano tutte le tabelle del da-
tabase tramite l’apposito bottone “Load Tables”
presente sulla maschera quindi ha inizio la scelta
dei parametri per la creazione del codice.
La scheda “Templates” presenta le possibilità di
scelta per la creazione del codice ma purtroppo qui
si denotano i limiti di questa applicazione: i tem-
plate disponibili sono DAO e NHibernate e il lin-
guaggio con cui viene generato il codice è il solo
C#. Come è noto a tutti, purtroppo DAO è una tec-
nologia obsoleta di accesso ai dati, mentre NHi-
bernate è il porting di un tool scritto nativamente
per Java per generare SQL per caricare e salvare
oggetti che si mappano ad una base dati.
Un’ulteriore pecca è rappresentata dal fatto che
è possibile selezionare la creazione di una nuo-
va soluzione, ma quest’ultima verrà creata solo
in Visual Studio 2003, ed essendo la versione da
noi provata di aprile 2006, ciò risulta senza dub-
bio uno svantaggio per chi utilizza già Visual Stu-
dio 2005.
Passiamo ora agli aspetti positivi della maschera
NDoc difficilmente rinunceremo ad esso.
Infatti, se da un lato il programmatore continua
ad accedere direttamente alla documentazione
del codice tramite i commenti al codice stesso,
la stessa documentazione può essere resa
disponibile nel formato help che preferiamo
senza ulteriori passaggi o integrazioni.
Riferimenti[1] http://sourceforge.net/projects/ndoc/
[2] http://msdn.microsoft.com/library/
default.asp?url=/library/en-us/dv_vstechart/
html/VBGeneratingDocs.asp
[3] http://msdn.microsoft.com/library/en-us/
csref/html/vclrfTagsForDocumentationComm
ents.asp
[4] http://sourceforge.net/projects/ndoc05
[5] http://jonas.lagerblad.com/blog/?p=4
[6] http://dougrohm.com/cs/archive/2006/01/06/
36.aspx
[7] http://connect.microsoft.com/VisualStudio/
feedback/ViewFeedback.aspx?FeedbackID=9
3842
Codus Generazione automatica di codice
di Fabio Perrone
Uno strumento gratuito per generare codice
in automatico
Quando è necessario scrivere delle applicazioni,
ogni buon sviluppatore dispone di proprie libre-
rie che riutilizza oppure sfrutta librerie scritte da
terzi. Tuttavia, scrivere codice per gestire la ban-
ca dati (quindi gli eventuali inserimenti, cancel-
lazioni, modifiche, ecc.) può essere un’operazio-
ne noiosa e ripetitiva. A questo punto è possibile
scrivere da soli un tool per la generazione auto-
matica di codice o usarne uno già esistente, qua-
le il protagonista di questo articolo.
Codus permette di gestire database Access, My-
Sql, Oracle e SQL Server. L’aspetto del program-
ma è un’interfaccia classica con un elemento ta-
bstrip in alto, un treeview a sinistra ed una serie
di pannelli centrali che permettono l’esecuzione
di una serie di operazioni. Come prima attività è
necessario impostare il tipo di database, immet-
65
.NET TOOLS
N. 70 - Luglio/Agosto 2006 VBJ
di scelta dei template: sono presenti alcuni flag,
uno per la creazione di un file di build di NAnt
ed un altro per la creazione di test di NUnit al-
l’interno del codice creato in automatico, un altro
ancora per la creazione in automatico di Stored
Procedure (ovviamente attivo solo per i databa-
se che lo permettono) ed infine uno per la crea-
zione in automatico di Web Service per esporre i
dati tramite questa tecnologia.
Il tab “Tables” permette di scegliere quali tabel-
le e viste si desiderano per la creazione del codi-
ce, nonchè arrivare a scegliere a livello di singo-
lo campo con possibilità di cambiare il nome del
campo stesso nella classe business.
Una volta impostate tutte le opzioni, è possi-
bile generare le classi business, cui ora daremo
una breve occhiata. Per ogni tabella selezionata,
vengono create tre collection: una ordinabile, un
dictionary ed una che implementa IEnumerator,
così da poter utilizzare i suoi elementi in un ciclo
for each. Per ogni tabella o vista vengono quindi
scritte le classi astratte con metodi che creano i
command per l’inserimento, la cancellazione e la
modifica; è ovvio che queste classi rappresentano
il “core” di qualsiasi applicazione che debba effet-
tuare l’accesso ai dati. Inoltre, vengono create le
classi di Business Logic che si mappano uno ad
uno con le tabelle selezionate che rappresentano
le entità che verranno usate dall’interfaccia uten-
te per la convalida dei dati. Oltre a tutto ciò ven-
gono creati anche dei cosiddetti “Mock Objects”,
particolarmente utili per la creazione dei test da
eseguire poi con NUnit.
Il secondo progetto che viene creato è totalmen-
te dedicato ai test: per ogni classe vengono crea-
ti in automatico test per l’inserimento, la cancel-
lazione, la modifica, la selezione di tutti i record,
la serializzazione degli oggetti business.
La documentazione del prodotto è disponibile
solo on line e purtroppo non è completamente sod-
disfacente, anche se vengono comunque spiegate
le funzionalità di base del programma.
Da ciò che abbiamo scritto, si evince quindi che
Codus è un prodotto senza dubbio valido ma al-
trettanto migliorabile per quanto riguarda alcu-
ni aspetti leggermente obsoleti; controllando sul
sito del produttore è tuttavia già stata pianifica-
ta la versione 1.4 del prodotto con supporto per
.NET 2.0 e per nuovi database, quali Firebird e
PostgreSQL.
Aspetto non trascurabile è la possibilità di ave-
re a propria disposizione tutti i codici sorgenti
dell’applicazione, così da poterne fare oggetto di
studio e anche per eventualmente personalizzare
a proprio piacere il programma, estendendolo in
base alle proprie necessità.
2 AN
NI