v2006 04 vbj70

68

Upload: turing-club

Post on 07-Jun-2015

522 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: v2006 04 vbj70
Page 2: v2006 04 vbj70
Page 3: v2006 04 vbj70
Page 4: v2006 04 vbj70
Page 5: v2006 04 vbj70
Page 6: v2006 04 vbj70

VBJ 70

Scrivi a

[email protected]

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

Page 7: v2006 04 vbj70

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

[email protected]

AmministrazioneSara Mattei

([email protected])

Grafica([email protected])

Technical BookLisa Vanni ([email protected])

Segreteria Enrica Nassi

([email protected])

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

Page 8: v2006 04 vbj70
Page 9: v2006 04 vbj70

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

Page 10: v2006 04 vbj70
Page 11: v2006 04 vbj70

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

Page 12: v2006 04 vbj70

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

Page 13: v2006 04 vbj70

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

Page 14: v2006 04 vbj70

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

Page 15: v2006 04 vbj70

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

Page 16: v2006 04 vbj70

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-

Page 17: v2006 04 vbj70

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

Page 18: v2006 04 vbj70
Page 19: v2006 04 vbj70

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

Page 20: v2006 04 vbj70

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

Page 21: v2006 04 vbj70

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

Page 22: v2006 04 vbj70

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

Page 23: v2006 04 vbj70

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

Page 24: v2006 04 vbj70

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)

Page 25: v2006 04 vbj70

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

Page 26: v2006 04 vbj70

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; } }}

Page 27: v2006 04 vbj70

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

Page 28: v2006 04 vbj70

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

Page 29: v2006 04 vbj70

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.

Page 30: v2006 04 vbj70

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

Page 31: v2006 04 vbj70

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

Page 32: v2006 04 vbj70

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

Page 33: v2006 04 vbj70

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

Page 34: v2006 04 vbj70

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

Page 35: v2006 04 vbj70

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

Page 36: v2006 04 vbj70

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

Page 37: v2006 04 vbj70

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

Page 38: v2006 04 vbj70

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

Page 39: v2006 04 vbj70

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;”;

Page 40: v2006 04 vbj70

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

Page 41: v2006 04 vbj70

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

Page 42: v2006 04 vbj70

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

Page 43: v2006 04 vbj70

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).

Page 44: v2006 04 vbj70
Page 45: v2006 04 vbj70

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

Page 46: v2006 04 vbj70

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

Page 47: v2006 04 vbj70

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

Page 48: v2006 04 vbj70

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

Page 49: v2006 04 vbj70

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

Page 50: v2006 04 vbj70

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.

Page 51: v2006 04 vbj70
Page 52: v2006 04 vbj70

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

Page 53: v2006 04 vbj70

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

Page 54: v2006 04 vbj70

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.

Page 55: v2006 04 vbj70

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

Page 56: v2006 04 vbj70

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

Page 57: v2006 04 vbj70

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-

Page 58: v2006 04 vbj70

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.

Page 59: v2006 04 vbj70

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

Page 60: v2006 04 vbj70

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.

Page 61: v2006 04 vbj70

.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

Page 62: v2006 04 vbj70

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.

Page 63: v2006 04 vbj70

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

Page 64: v2006 04 vbj70

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-

Page 65: v2006 04 vbj70

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à.

Page 66: v2006 04 vbj70

2 AN

NI

Page 67: v2006 04 vbj70
Page 68: v2006 04 vbj70