acegi.xml 261 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
  4. <!--
  5. * ========================================================================
  6. *
  7. * Copyright 2004 Acegi Technology Pty Limited
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License");
  10. * you may not use this file except in compliance with the License.
  11. * You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing, software
  16. * distributed under the License is distributed on an "AS IS" BASIS,
  17. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. *
  21. * ========================================================================
  22. -->
  23. <book>
  24. <bookinfo>
  25. <title>Acegi Security System for Spring</title>
  26. <subtitle>Reference Documentation</subtitle>
  27. <releaseinfo>0.9.0</releaseinfo>
  28. <authorgroup>
  29. <author>
  30. <firstname>Ben</firstname>
  31. <surname>Alex</surname>
  32. </author>
  33. </authorgroup>
  34. </bookinfo>
  35. <toc></toc>
  36. <preface id="preface">
  37. <title>Preface</title>
  38. <para>This document provides a reference guide to the Acegi Security
  39. System for Spring, which is a series of classes that deliver
  40. authentication and authorization services within the Spring
  41. Framework.</para>
  42. <para>I would like to acknowledge this reference was prepared using the
  43. DocBook configuration included with the Spring Framework. The Spring team
  44. in turn acknowledge Chris Bauer (Hibernate) for his assistance with their
  45. DocBook.</para>
  46. </preface>
  47. <chapter id="security">
  48. <title>Security</title>
  49. <sect1 id="security-before-you-begin">
  50. <title>Before You Begin</title>
  51. <para>For your security, each official release JAR of Acegi Security has
  52. been signed by the project leader. This does not in any way alter the
  53. liability disclaimer contained in the License, but it does ensure you
  54. are using a properly reviewed, official build of Acegi Security. Please
  55. refer to the <literal>readme.txt</literal> file in the root of the
  56. release distribution for instructions on how to validate the JARs are
  57. correctly signed, and which certificate has been used to sign
  58. them.</para>
  59. </sect1>
  60. <sect1 id="security-introduction">
  61. <title>Introduction</title>
  62. <para>The Acegi Security System for Spring provides authentication and
  63. authorization capabilities for Spring-powered projects, with optional
  64. integration with popular web containers. The security architecture was
  65. designed from the ground up using "The Spring Way" of development, which
  66. includes using bean contexts, interceptors and interface-driven
  67. programming. As a consequence, the Acegi Security System for Spring is
  68. useful out-of-the-box for those seeking to secure their Spring-based
  69. applications, and can be easily adapted to complex customized
  70. requirements.</para>
  71. <para>Security involves two distinct operations, authentication and
  72. authorization. The former relates to resolving whether or not a caller
  73. is who they claim to be. Authorization on the other hand relates to
  74. determining whether or not an authenticated caller is permitted to
  75. perform a given operation.</para>
  76. <para>Throughout the Acegi Security System for Spring, the user, system
  77. or agent that needs to be authenticated is referred to as a "principal".
  78. The security architecture does not have a notion of roles or groups,
  79. which you may be familiar with from other security implementations,
  80. although equivalent functionality is fully accommodated by Acegi
  81. Security.</para>
  82. <sect2 id="security-introduction-status">
  83. <title>Current Status</title>
  84. <para>The Acegi Security System for Spring is widely used by members
  85. of the Spring Community. The APIs are considered stable and only minor
  86. changes are expected. Having said that, like many other projects we
  87. need to strike a balance between backward compatibility and
  88. improvement. Effective version 0.6.1, Acegi Security uses the Apache
  89. Portable Runtime Project versioning guidelines, available from
  90. <literal>http://apr.apache.org/versioning.html</literal>.</para>
  91. <para>Some minor improvements are currently intended prior to the
  92. 1.0.0 release, although each of these represent additional
  93. functionality that will in no way modify the project's central
  94. interfaces or classes. Users of Acegi Security System for Spring
  95. should therefore be comfortable depending on the current version of
  96. the project in their applications.</para>
  97. </sect2>
  98. </sect1>
  99. <sect1 id="security-high-level-design">
  100. <title>High Level Design</title>
  101. <sect2 id="security-high-level-design-key-components">
  102. <title>Key Components</title>
  103. <para>Most enterprise applications have four basic security
  104. requirements. First, they need to be able to authenticate a principal.
  105. Second, they need to be able to secure web requests. Third, enterprise
  106. applications need to be able to secure services layer methods.
  107. Finally, quite often an enterprise application will need to secure
  108. domain object instances. Acegi Security provides a comprehensive
  109. framework for achieving all of these four common enterprise
  110. application security requirements.</para>
  111. <para>The Acegi Security System for Spring essentially comprises eight
  112. key functional parts:</para>
  113. <itemizedlist spacing="compact">
  114. <listitem>
  115. <para>An <literal>Authentication</literal> object which holds the
  116. principal, credentials and the authorities granted to the
  117. principal. The object can also store additional information
  118. associated with an authentication request, such as the source
  119. TCP/IP address.</para>
  120. </listitem>
  121. <listitem>
  122. <para>A <literal>ContextHolder</literal> which holds the
  123. <literal>Authentication</literal> object in a
  124. <literal>ThreadLocal</literal>-bound object.</para>
  125. </listitem>
  126. <listitem>
  127. <para>An <literal>AuthenticationManager</literal> to authenticate
  128. the <literal>Authentication</literal> object presented via the
  129. <literal>ContextHolder</literal>.</para>
  130. </listitem>
  131. <listitem>
  132. <para>An <literal>AccessDecisionManager</literal> to authorize a
  133. given operation.</para>
  134. </listitem>
  135. <listitem>
  136. <para>A <literal>RunAsManager</literal> to optionally replace the
  137. <literal>Authentication</literal> object whilst a given operation
  138. is being executed.</para>
  139. </listitem>
  140. <listitem>
  141. <para>A "secure object" interceptor, which coordinates the
  142. authentication, authorization, run-as replacement, after
  143. invocation handling and execution of a given operation.</para>
  144. </listitem>
  145. <listitem>
  146. <para>An <literal>AfterInvocationManager</literal> which can
  147. modify an <literal>Object</literal> returned from a "secure
  148. object" invocation, such as removing <literal>Collection</literal>
  149. elements a principal does not have authority to access.</para>
  150. </listitem>
  151. <listitem>
  152. <para>An acess control list (ACL) management package, which can be
  153. used to obtain the ACLs applicable for domain object
  154. instances.</para>
  155. </listitem>
  156. </itemizedlist>
  157. <para>A "secure object" interceptor executes most of the Acegi
  158. Security key classes and in doing so delivers the framework's major
  159. features. Given its importance, Figure 1 shows the key relationships
  160. and concrete implementations of
  161. <literal>AbstractSecurityInterceptor</literal>.</para>
  162. <para><mediaobject>
  163. <imageobject role="html">
  164. <imagedata align="center"
  165. fileref="images/SecurityInterception.gif"
  166. format="GIF" />
  167. </imageobject>
  168. <caption>
  169. <para>Figure 1: The key "secure object" model</para>
  170. </caption>
  171. </mediaobject></para>
  172. <para>Each "secure object" interceptor (hereinafter called a "security
  173. interceptor") works with a particular type of "secure object". So,
  174. what is a secure object? Secure objects refer to any type of object
  175. that can have security applied to it. A secure object must provide
  176. some form of callback, so that the security interceptor can
  177. transparently do its work as required, and callback the object when it
  178. is time for it to proceed with the requested operation. If secure
  179. objects cannot provide a native callback approach, a wrapper needs to
  180. be written so this becomes possible.</para>
  181. <para>Each secure object has its own package under
  182. <literal>net.sf.acegisecurity.intercept</literal>. Every other package
  183. in the security system is secure object independent, in that it can
  184. support any type of secure object presented.</para>
  185. <para>Only developers contemplating an entirely new way of
  186. intercepting and authorizing requests would need to use secure objects
  187. directly. For example, it would be possible to build a new secure
  188. object to secure calls to a messaging system that does not use
  189. <literal>MethodInvocation</literal>s. Most Spring applications will
  190. simply use the three currently supported secure object types (AOP
  191. Alliance <literal>MethodInvocation</literal>, AspectJ
  192. <literal>JoinPoint</literal> and web request
  193. <literal>FilterInterceptor</literal>) with complete
  194. transparency.</para>
  195. <para>Each of the eight key parts of Acegi Security are discussed in
  196. detail throughout this document.</para>
  197. </sect2>
  198. <sect2 id="security-high-level-design-supported-secure-objects">
  199. <title>Supported Secure Objects</title>
  200. <para>As shown in the base of Figure 1, the Acegi Security System for
  201. Spring currently supports three secure objects.</para>
  202. <para>The first handles an AOP Alliance
  203. <literal>MethodInvocation</literal>. This is the secure object type
  204. used to protect Spring beans. Developers will generally use this
  205. secure object type to secure their business objects. To make a
  206. standard Spring-hosted bean available as a
  207. <literal>MethodInvocation</literal>, the bean is simply published
  208. through a <literal>ProxyFactoryBean</literal> or
  209. <literal>BeanNameAutoProxyCreator</literal> or
  210. <literal>DefaultAdvisorAutoProxyCreator</literal>. Most Spring
  211. developers would already be familiar with these due to their use in
  212. transactions and other areas of Spring.</para>
  213. <para>The second type is an AspectJ <literal>JoinPoint</literal>.
  214. AspectJ has a particular use in securing domain object instances, as
  215. these are most often managed outside the Spring bean container. By
  216. using AspectJ, standard constructs such as <literal>new
  217. Person();</literal> can be used and full security will be applied to
  218. them by Acegi Security. The
  219. <literal>AspectJSecurityInterceptor</literal> is still managed by
  220. Spring, which creates the aspect singleton and wires it with the
  221. appropriate authentication managers, access decision managers and so
  222. on.</para>
  223. <para>The third type is a <literal>FilterInvocation</literal>. This is
  224. an object included with the Acegi Security System for Spring. It is
  225. created by an included filter and simply wraps the HTTP
  226. <literal>ServletRequest</literal>, <literal>ServletResponse</literal>
  227. and <literal>FilterChain</literal>. The
  228. <literal>FilterInvocation</literal> enables HTTP resources to be
  229. secured. Developers do not usually need to understand the mechanics of
  230. how this works, because they just add the filters to their
  231. <literal>web.xml</literal> and let the security system do its
  232. work.</para>
  233. </sect2>
  234. <sect2 id="security-high-level-design-configuration-attributes">
  235. <title>Configuration Attributes</title>
  236. <para>Every secure object can represent an infinite number of
  237. individual requests. For example, a
  238. <literal>MethodInvocation</literal> can represent the invocation of
  239. any method with any arguments, whilst a
  240. <literal>FilterInvocation</literal> can represent any HTTP URL.</para>
  241. <para>The Acegi Security System for Spring needs to record the
  242. configuration that applies to each of these possible requests. The
  243. security configuration of a request to
  244. <literal>BankManager.getBalance(int accountNumber)</literal> needs to
  245. be very different from the security configuration of a request to
  246. <literal>BankManager.approveLoan(int applicationNumber)</literal>.
  247. Similarly, the security configuration of a request to
  248. <literal>http://some.bank.com/index.htm</literal> needs to be very
  249. different from the security configuration of
  250. <literal>http://some.bank.com/manage/timesheet.jsp</literal>.</para>
  251. <para>To store the various security configurations associated with
  252. different requests, a configuration attribute is used. At an
  253. implementation level a configuration attribute is represented by the
  254. <literal>ConfigAttribute</literal> interface. One concrete
  255. implementation of <literal>ConfigAttribute</literal> is provided,
  256. <literal>SecurityConfig</literal>, which simply stores a configuration
  257. attribute as a <literal>String</literal>.</para>
  258. <para>The collection of <literal>ConfigAttribute</literal>s associated
  259. with a particular request is held in a
  260. <literal>ConfigAttributeDefinition</literal>. This concrete class is
  261. simply a holder of <literal>ConfigAttribute</literal>s and does
  262. nothing special.</para>
  263. <para>When a request is received by the security interceptor, it needs
  264. to determine which configuration attributes apply. In other words, it
  265. needs to find the <literal>ConfigAttributeDefinition</literal> which
  266. applies to the request. This decision is handled by the
  267. <literal>ObjectDefinitionSource</literal> interface. The main method
  268. provided by this interface is <literal>public
  269. ConfigAttributeDefinition getAttributes(Object object)</literal>, with
  270. the <literal>Object</literal> being the secure object. Recall the
  271. secure object contains details of the request, so the
  272. <literal>ObjectDefinitionSource</literal> implementation will be able
  273. to extract the details it requires to lookup the relevant
  274. <literal>ConfigAttributeDefinition</literal>.</para>
  275. </sect2>
  276. </sect1>
  277. <sect1 id="security-request-contexts">
  278. <title>Request Contexts</title>
  279. <sect2 id="security-contexts">
  280. <title>Contexts</title>
  281. <para>Many applications require a way of sharing objects between
  282. classes, but without resorting to passing them in method signatures.
  283. This is commonly achieved by using a <literal>ThreadLocal</literal>.
  284. The Acegi Security System for Spring uses
  285. <literal>ThreadLocal</literal> functionality and introduces the
  286. concept of "request contexts".</para>
  287. <para>By placing an object into a request context, that object becomes
  288. available to any other object on the current thread of execution. The
  289. request context is not passed around as a method parameter, but is
  290. held in a <literal>ThreadLocal</literal>. The Acegi Security System
  291. for Spring uses the request context to pass around the authentication
  292. request and response.</para>
  293. <para><mediaobject>
  294. <imageobject role="html">
  295. <imagedata align="center" fileref="images/Context.gif"
  296. format="GIF" />
  297. </imageobject>
  298. <caption>
  299. <para>Figure 2: The ContextHolder</para>
  300. </caption>
  301. </mediaobject></para>
  302. <para>A request context is a concrete implementation of the
  303. <literal>Context</literal> interface, which exposes a single
  304. method:</para>
  305. <programlisting>public void validate() throws ContextInvalidException;</programlisting>
  306. <para>This <literal>validate()</literal> method is called to confirm
  307. the <literal>Context</literal> is properly setup. An implementation
  308. will typically use this method to check that the objects it holds are
  309. properly setup.</para>
  310. <para>The <literal>ContextHolder</literal> class makes the
  311. <literal>Context</literal> available to the current thread of
  312. execution using a <literal>ThreadLocal</literal>. A
  313. <literal>ContextInterceptor</literal> is also provided, which is
  314. intended to be chained into the bean context using
  315. <literal>ProxyFactoryBean</literal>. The
  316. <literal>ContextInterceptor</literal> simply calls
  317. <literal>Context.validate()</literal>, which guarantees to business
  318. methods that a valid <literal>Context</literal> is available from the
  319. <literal>ContextHolder</literal>.</para>
  320. </sect2>
  321. <sect2 id="security-contexts-secure-contexts">
  322. <title>Secure Contexts</title>
  323. <para>The Acegi Security System for Spring requires the
  324. <literal>ContextHolder</literal> to contain a request context that
  325. implements the <literal>SecureContext</literal> interface. An
  326. implementation is provided named <literal>SecureContextImpl</literal>.
  327. The <literal>SecureContext</literal> simply extends the
  328. <literal>Context</literal> discussed above and adds a holder and
  329. validation for an <literal>Authentication</literal> object.</para>
  330. </sect2>
  331. <sect2 id="security-contexts-custom-contexts">
  332. <title>Custom Contexts</title>
  333. <para>Developers can create their own request context classes to store
  334. application-specific objects. Such request context classes will need
  335. to implement the <literal>Context</literal> interface. If the Acegi
  336. Security System for Spring is to be used, developers must ensure any
  337. custom request contexts implement the <literal>SecureContext</literal>
  338. interface.</para>
  339. </sect2>
  340. <sect2 id="security-contexts-storage">
  341. <title>Context Storage</title>
  342. <para>Central to Acegi Security's design is that the contents of the
  343. <literal>ContextHolder</literal> (ie the <literal>Context</literal>)
  344. can be stored between web requests. This is so that a successfully
  345. authenticated principal can be identified on subsequent requests
  346. through the <literal>Authentication</literal> stored inside a
  347. <literal>SecureContext</literal> implementation. The
  348. <literal>HttpSessionContextIntegrationFilter</literal> exists to
  349. automatically copy the contents of a well-defined
  350. <literal>HttpSession</literal> attribute into the
  351. <literal>ContextHolder</literal>, then at the end of each request,
  352. copy the <literal>ContextHolder</literal> contents back into the
  353. <literal>HttpSession</literal> ready for next request.</para>
  354. <para>It is essential - and an extremely common error of end users -
  355. that <literal>HttpSessionContextIntegrationFilter</literal> appears
  356. before any other Acegi Security filter. This is because other Acegi
  357. Security filters (along with all Acegi Security classes) expect the
  358. <literal>ContextHolder</literal> to contain a valid
  359. <literal>SecureContext</literal> by the time they are called. Acegi
  360. Security filters also expect to be able to modify the
  361. <literal>ContextHolder</literal> contents as they see fit, and
  362. something else will store those between requests if necessary. This is
  363. why <literal>HttpSessionContextIntegrationFilter</literal> must be the
  364. first filter used.</para>
  365. <para>The <literal>HttpSessionContextIntegrationFilter</literal> has
  366. been designed to store all types of <literal>Context</literal> objects
  367. - not merely Acegi Security related contexts. This means, for example,
  368. that you can extend <literal>SecureContextImpl</literal> to store a
  369. locale or some other parameter, and
  370. <literal>HttpSessionContextIntegrationFilter</literal> will
  371. automatically manage it between web requests.</para>
  372. </sect2>
  373. </sect1>
  374. <sect1 id="security-interception">
  375. <title>Security Interception</title>
  376. <sect2 id="security-interception-all-secure-objects">
  377. <title>All Secure Objects</title>
  378. <para>As described in the High Level Design section, each secure
  379. object has its own security interceptor which is responsible for
  380. handling each request. Handling involves a number of
  381. operations:</para>
  382. <orderedlist>
  383. <listitem>
  384. <para>Store the configuration attributes that are associated with
  385. each secure request.</para>
  386. </listitem>
  387. <listitem>
  388. <para>Extract the <literal>ConfigAttributeDefinition</literal>
  389. that applies to the request from the relevant
  390. <literal>ObjectDefinitionSource</literal>.</para>
  391. </listitem>
  392. <listitem>
  393. <para>Obtain the <literal>Authentication</literal> object from the
  394. <literal>SecureContext</literal>, which is held in the
  395. <literal>ContextHolder</literal>.</para>
  396. </listitem>
  397. <listitem>
  398. <para>Pass the <literal>Authentication</literal> object to the
  399. <literal>AuthenticationManager</literal>, update the
  400. <literal>ContextHolder</literal> with the response.</para>
  401. </listitem>
  402. <listitem>
  403. <para>Pass the <literal>Authentication</literal> object, the
  404. <literal>ConfigAttributeDefinition</literal>, and the secure
  405. object to the <literal>AccessDecisionManager</literal>.</para>
  406. </listitem>
  407. <listitem>
  408. <para>Pass the <literal>Authentication</literal> object, the
  409. <literal>ConfigAttributeDefinition</literal>, and the secure
  410. object to the <literal>RunAsManager</literal>.</para>
  411. </listitem>
  412. <listitem>
  413. <para>If the <literal>RunAsManager</literal> returns a new
  414. <literal>Authentication</literal> object, update the
  415. <literal>ContextHolder</literal> with it.</para>
  416. </listitem>
  417. <listitem>
  418. <para>Proceed with the request execution of the secure
  419. object.</para>
  420. </listitem>
  421. <listitem>
  422. <para>If the <literal>RunAsManager</literal> earlier returned a
  423. new <literal>Authentication</literal> object, update the
  424. <literal>ContextHolder</literal> with the
  425. <literal>Authentication</literal> object that was previously
  426. returned by the <literal>AuthenticationManager</literal>.</para>
  427. </listitem>
  428. <listitem>
  429. <para>If an <literal>AfterInvocationManager</literal> is defined,
  430. pass it the result of the secure object execution so that it may
  431. throw an <literal>AccessDeniedException</literal> or mutate the
  432. returned object if required.</para>
  433. </listitem>
  434. <listitem>
  435. <para>Return any result received from the
  436. <literal>AfterInvocationManager</literal>, or if no
  437. <literal>AfterInvocationManager</literal> is defined, simply
  438. return the result provided by the secure object execution.</para>
  439. </listitem>
  440. </orderedlist>
  441. <para>Whilst this may seem quite involved, don't worry. Developers
  442. interact with the security process by simply implementing basic
  443. interfaces (such as <literal>AccessDecisionManager</literal>), which
  444. are fully discussed below.</para>
  445. <para>The <literal>AbstractSecurityInterceptor</literal> handles the
  446. majority of the flow listed above. As shown in Figure 1, each secure
  447. object has its own security interceptor which subclasses
  448. <literal>AbstractSecurityInterceptor</literal>. Each of these secure
  449. object-specific security interceptors are discussed below.</para>
  450. </sect2>
  451. <sect2 id="security-interception-aopalliance">
  452. <title>AOP Alliance (MethodInvocation) Security Interceptor</title>
  453. <para>To secure <literal>MethodInvocation</literal>s, developers
  454. simply add a properly configured
  455. <literal>MethodSecurityInterceptor</literal> into the application
  456. context. Next the beans requiring security are chained into the
  457. interceptor. This chaining is accomplished using Spring’s
  458. <literal>ProxyFactoryBean</literal> or
  459. <literal>BeanNameAutoProxyCreator</literal>, as commonly used by many
  460. other parts of Spring (refer to the sample application for examples).
  461. Alternatively, Acegi Security provides a
  462. <literal>MethodDefinitionSourceAdvisor</literal> which may be used
  463. with Spring's <literal>DefaultAdvisorAutoProxyCreator</literal> to
  464. automatically chain the security interceptor in front of any beans
  465. defined against the <literal>MethodSecurityInterceptor</literal>. The
  466. <literal>MethodSecurityInterceptor</literal> itself is configured as
  467. follows:</para>
  468. <para><programlisting>&lt;bean id="bankManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;
  469. &lt;property name="validateConfigAttributes"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
  470. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  471. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  472. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  473. &lt;property name="afterInvocationManager"&gt;&lt;ref bean="afterInvocationManager"/&gt;&lt;/property&gt;
  474. &lt;property name="objectDefinitionSource"&gt;
  475. &lt;value&gt;
  476. net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER
  477. net.sf.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
  478. &lt;/value&gt;
  479. &lt;/property&gt;
  480. &lt;/bean&gt;</programlisting></para>
  481. <para>As shown above, the <literal>MethodSecurityInterceptor</literal>
  482. is configured with a reference to an
  483. <literal>AuthenticationManager</literal>,
  484. <literal>AccessDecisionManager</literal> and
  485. <literal>RunAsManager</literal>, which are each discussed in separate
  486. sections below. In this case we've also defined an
  487. <literal>AfterInvocationManager</literal>, although this is entirely
  488. optional. The <literal>MethodSecurityInterceptor</literal> is also
  489. configured with configuration attributes that apply to different
  490. method signatures. A full discussion of configuration attributes is
  491. provided in the High Level Design section of this document.</para>
  492. <para>The <literal>MethodSecurityInterceptor</literal> can be
  493. configured with configuration attributes in three ways. The first is
  494. via a property editor and the application context, which is shown
  495. above. The second is via defining the configuration attributes in your
  496. source code using Jakarta Commons Attributes. The third is via writing
  497. your own <literal>ObjectDefinitionSource</literal>, although this is
  498. beyond the scope of this document. Irrespective of the approach used,
  499. the <literal>ObjectDefinitionSource</literal> is responsible for
  500. returning a <literal>ConfigAttributeDefinition</literal> object that
  501. contains all of the configuration attributes associated with a single
  502. secure method.</para>
  503. <para>It should be noted that the
  504. <literal>MethodSecurityInterceptor.setObjectDefinitionSource()</literal>
  505. method actually expects an instance of
  506. <literal>MethodDefinitionSource</literal>. This is a marker interface
  507. which subclasses <literal>ObjectDefinitionSource</literal>. It simply
  508. denotes the <literal>ObjectDefinitionSource</literal> understands
  509. <literal>MethodInvocation</literal>s. In the interests of simplicity
  510. we'll continue to refer to the
  511. <literal>MethodDefinitionSource</literal> as an
  512. <literal>ObjectDefinitionSource</literal>, as the distinction is of
  513. little relevance to most users of the
  514. <literal>MethodSecurityInterceptor</literal>.</para>
  515. <para>If using the application context property editor approach (as
  516. shown above), commas are used to delimit the different configuration
  517. attributes that apply to a given method pattern. Each configuration
  518. attribute is assigned into its own <literal>SecurityConfig</literal>
  519. object. The <literal>SecurityConfig</literal> object is discussed in
  520. the High Level Design section.</para>
  521. <para>If using the Jakarta Commons Attributes approach, your bean
  522. context will be configured differently:</para>
  523. <para><programlisting>&lt;bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/&gt;
  524. &lt;bean id="objectDefinitionSource" class="net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes"&gt;
  525. &lt;property name="attributes"&gt;&lt;ref local="attributes"/&gt;&lt;/property&gt;
  526. &lt;/bean&gt;
  527. &lt;bean id="bankManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor"&gt;
  528. &lt;property name="validateConfigAttributes"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  529. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  530. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  531. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  532. &lt;property name="objectDefinitionSource"&gt;&lt;ref bean="objectDefinitionSource"/&gt;&lt;/property&gt;
  533. &lt;/bean&gt;</programlisting></para>
  534. <para>In addition, your source code will contain Jakarta Commons
  535. Attributes tags that refer to a concrete implementation of
  536. <literal>ConfigAttribute</literal>. The following example uses the
  537. <literal>SecurityConfig</literal> implementation to represent the
  538. configuration attributes, and results in the same security
  539. configuration as provided by the property editor approach
  540. above:</para>
  541. <para><programlisting>public interface BankManager {
  542. /**
  543. * @@SecurityConfig("ROLE_SUPERVISOR")
  544. * @@SecurityConfig("RUN_AS_SERVER")
  545. */
  546. public void deleteSomething(int id);
  547. /**
  548. * @@SecurityConfig("ROLE_SUPERVISOR")
  549. * @@SecurityConfig("RUN_AS_SERVER")
  550. */
  551. public void deleteAnother(int id);
  552. /**
  553. * @@SecurityConfig("ROLE_TELLER")
  554. * @@SecurityConfig("ROLE_SUPERVISOR")
  555. * @@SecurityConfig("BANKSECURITY_CUSTOMER")
  556. * @@SecurityConfig("RUN_AS_SERVER")
  557. */
  558. public float getBalance(int id);
  559. }</programlisting></para>
  560. <para>You might have noticed the
  561. <literal>validateConfigAttributes</literal> property in the above
  562. <literal>MethodSecurityInterceptor</literal> examples. When set to
  563. <literal>true</literal> (the default), at startup time the
  564. <literal>MethodSecurityInterceptor</literal> will evaluate if the
  565. provided configuration attributes are valid. It does this by checking
  566. each configuration attribute can be processed by either the
  567. <literal>AccessDecisionManager</literal> or the
  568. <literal>RunAsManager</literal>. If neither of these can process a
  569. given configuration attribute, an exception is thrown. If using the
  570. Jakarta Commons Attributes method of configuration, you should set
  571. <literal>validateConfigAttributes</literal> to
  572. <literal>false</literal>.</para>
  573. </sect2>
  574. <sect2 id="security-interception-aspectj">
  575. <title>AspectJ (JoinPoint) Security Interceptor</title>
  576. <para>The AspectJ security interceptor is very similar to the AOP
  577. Alliance security interceptor discussed in the previous section.
  578. Indeed we will only discuss the differences in this section.</para>
  579. <para>The AspectJ interceptor is named
  580. <literal>AspectJSecurityInterceptor</literal>. Unlike the AOP Alliance
  581. security interceptor, which relies on the Spring application context
  582. to weave in the security interceptor via proxying, the
  583. <literal>AspectJSecurityInterceptor</literal> is weaved in via the
  584. AspectJ compiler. It would not be uncommon to use both types of
  585. security interceptors in the same application, with
  586. <literal>AspectJSecurityInterceptor</literal> being used for domain
  587. object instance security and the AOP Alliance
  588. <literal>MethodSecurityInterceptor</literal> being used for services
  589. layer security.</para>
  590. <para>Let's first consider how the
  591. <literal>AspectJSecurityInterceptor</literal> is configured in the
  592. Spring application context:</para>
  593. <para><programlisting>&lt;bean id="bankManagerSecurity" class="net.sf.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor"&gt;
  594. &lt;property name="validateConfigAttributes"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
  595. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  596. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  597. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  598. &lt;property name="afterInvocationManager"&gt;&lt;ref bean="afterInvocationManager"/&gt;&lt;/property&gt;
  599. &lt;property name="objectDefinitionSource"&gt;
  600. &lt;value&gt;
  601. net.sf.acegisecurity.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER
  602. net.sf.acegisecurity.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
  603. &lt;/value&gt;
  604. &lt;/property&gt;
  605. &lt;/bean&gt;</programlisting></para>
  606. <para>As you can see, aside from the class name, the
  607. <literal>AspectJSecurityInterceptor</literal> is exactly the same as
  608. the AOP Alliance security interceptor. Indeed the two interceptors can
  609. share the same <literal>objectDefinitionSource</literal>, as the
  610. <literal>ObjectDefinitionSource</literal> works with
  611. <literal>java.lang.reflect.Method</literal>s rather than an AOP
  612. library-specific class. Of course, your access decisions have access
  613. to the relevant AOP library-specific invocation (ie
  614. <literal>MethodInvocation</literal> or <literal>JoinPoint</literal>)
  615. and as such can consider a range of addition criteria when making
  616. access decisions (such as method arguments).</para>
  617. <para>Next you'll need to define an AspectJ <literal>aspect</literal>.
  618. For example:</para>
  619. <para><programlisting>package net.sf.acegisecurity.samples.aspectj;
  620. import net.sf.acegisecurity.intercept.method.aspectj.AspectJSecurityInterceptor;
  621. import net.sf.acegisecurity.intercept.method.aspectj.AspectJCallback;
  622. import org.springframework.beans.factory.InitializingBean;
  623. public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
  624. private AspectJSecurityInterceptor securityInterceptor;
  625. pointcut domainObjectInstanceExecution(): target(PersistableEntity)
  626. &amp;&amp; execution(public * *(..)) &amp;&amp; !within(DomainObjectInstanceSecurityAspect);
  627. Object around(): domainObjectInstanceExecution() {
  628. if (this.securityInterceptor != null) {
  629. AspectJCallback callback = new AspectJCallback() {
  630. public Object proceedWithObject() {
  631. return proceed();
  632. }
  633. };
  634. return this.securityInterceptor.invoke(thisJoinPoint, callback);
  635. } else {
  636. return proceed();
  637. }
  638. }
  639. public AspectJSecurityInterceptor getSecurityInterceptor() {
  640. return securityInterceptor;
  641. }
  642. public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
  643. this.securityInterceptor = securityInterceptor;
  644. }
  645. public void afterPropertiesSet() throws Exception {
  646. if (this.securityInterceptor == null)
  647. throw new IllegalArgumentException("securityInterceptor required");
  648. }
  649. }</programlisting></para>
  650. <para>In the above example, the security interceptor will be applied
  651. to every instance of <literal>PersistableEntity</literal>, which is an
  652. abstract class not shown (you can use any other class or
  653. <literal>pointcut</literal> expression you like). For those curious,
  654. <literal>AspectJCallback</literal> is needed because the
  655. <literal>proceed();</literal> statement has special meaning only
  656. within an <literal>around()</literal> body. The
  657. <literal>AspectJSecurityInterceptor</literal> calls this anonymous
  658. <literal>AspectJCallback</literal> class when it wants the target
  659. object to continue.</para>
  660. <para>You will need to configure Spring to load the aspect and wire it
  661. with the <literal>AspectJSecurityInterceptor</literal>. A bean
  662. declaration which achieves this is shown below:</para>
  663. <para><programlisting>&lt;bean id="domainObjectInstanceSecurityAspect"
  664. class="net.sf.acegisecurity.samples.aspectj.DomainObjectInstanceSecurityAspect"
  665. factory-method="aspectOf"&gt;
  666. &lt;property name="securityInterceptor"&gt;&lt;ref bean="aspectJSecurityInterceptor"/&gt;&lt;/property&gt;
  667. &lt;/bean&gt;</programlisting></para>
  668. <para>That's it! Now you can create your beans from anywhere within
  669. your application, using whatever means you think fit (eg <literal>new
  670. Person();</literal>) and they will have the security interceptor
  671. applied.</para>
  672. </sect2>
  673. <sect2 id="security-interception-filterinvocation">
  674. <title>FilterInvocation Security Interceptor</title>
  675. <para>To secure <literal>FilterInvocation</literal>s, developers need
  676. to add a filter to their <literal>web.xml</literal> that delegates to
  677. the <literal>SecurityEnforcementFilter</literal>. A typical
  678. configuration example is provided below: <programlisting>&lt;filter&gt;
  679. &lt;filter-name&gt;Acegi HTTP Request Security Filter&lt;/filter-name&gt;
  680. &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
  681. &lt;init-param&gt;
  682. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  683. &lt;param-value&gt;net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter&lt;/param-value&gt;
  684. &lt;/init-param&gt;
  685. &lt;/filter&gt;
  686. &lt;filter-mapping&gt;
  687. &lt;filter-name&gt;Acegi HTTP Request Security Filter&lt;/filter-name&gt;
  688. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  689. &lt;/filter-mapping&gt;</programlisting></para>
  690. <para>Notice that the filter is actually a
  691. <literal>FilterToBeanProxy</literal>. Most of the filters used by the
  692. Acegi Security System for Spring use this class. Refer to the Filters
  693. section to learn more about this bean.</para>
  694. <para>In the application context you will need to configure three
  695. beans:</para>
  696. <programlisting>&lt;bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"&gt;
  697. &lt;property name="filterSecurityInterceptor"&gt;&lt;ref bean="filterInvocationInterceptor"/&gt;&lt;/property&gt;
  698. &lt;property name="authenticationEntryPoint"&gt;&lt;ref bean="authenticationEntryPoint"/&gt;&lt;/property&gt;
  699. &lt;/bean&gt;
  700. &lt;bean id="authenticationEntryPoint" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint"&gt;
  701. &lt;property name="loginFormUrl"&gt;&lt;value&gt;/acegilogin.jsp&lt;/value&gt;&lt;/property&gt;
  702. &lt;property name="forceHttps"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  703. &lt;/bean&gt;
  704. &lt;bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;
  705. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  706. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  707. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  708. &lt;property name="objectDefinitionSource"&gt;
  709. &lt;value&gt;
  710. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  711. \A/secure/super/.*\Z=ROLE_WE_DONT_HAVE
  712. \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER
  713. &lt;/value&gt;
  714. &lt;/property&gt;
  715. &lt;/bean&gt;</programlisting>
  716. <para>The <literal>AuthenticationEntryPoint</literal> will be called
  717. if the user requests a secure HTTP resource but they are not
  718. authenticated. The class handles presenting the appropriate response
  719. to the user so that authentication can begin. Three concrete
  720. implementations are provided with the Acegi Security System for
  721. Spring: <literal>AuthenticationProcessingFilterEntryPoint</literal>
  722. for commencing a form-based authentication,
  723. <literal>BasicProcessingFilterEntryPoint</literal> for commencing a
  724. HTTP Basic authentication process, and
  725. <literal>CasProcessingFilterEntryPoint</literal> for commencing a Yale
  726. Central Authentication Service (CAS) login. The
  727. <literal>AuthenticationProcessingFilterEntryPoint</literal> and
  728. <literal>CasProcessingFilterEntryPoint</literal> have optional
  729. properties related to forcing the use of HTTPS, so please refer to the
  730. JavaDocs if you require this.</para>
  731. <para>The <literal>PortMapper</literal> provides information on which
  732. HTTPS ports correspond to which HTTP ports. This is used by the
  733. <literal>AuthenticationProcessingFilterEntryPoint</literal> and
  734. several other beans. The default implementation,
  735. <literal>PortMapperImpl</literal>, knows the common HTTP ports 80 and
  736. 8080 map to HTTPS ports 443 and 8443 respectively. You can customise
  737. this mapping if desired.</para>
  738. <para>The <literal>SecurityEnforcementFilter</literal> primarily
  739. provides session management support and initiates authentication when
  740. required. It delegates actual <literal>FilterInvocation</literal>
  741. security decisions to the configured
  742. <literal>FilterSecurityInterceptor</literal>.</para>
  743. <para>Like any other security interceptor, the
  744. <literal>FilterSecurityInterceptor</literal> requires a reference to
  745. an <literal>AuthenticationManager</literal>,
  746. <literal>AccessDecisionManager</literal> and
  747. <literal>RunAsManager</literal>, which are each discussed in separate
  748. sections below. The <literal>FilterSecurityInterceptor</literal> is
  749. also configured with configuration attributes that apply to different
  750. HTTP URL requests. A full discussion of configuration attributes is
  751. provided in the High Level Design section of this document.</para>
  752. <para>The <literal>FilterSecurityInterceptor</literal> can be
  753. configured with configuration attributes in two ways. The first is via
  754. a property editor and the application context, which is shown above.
  755. The second is via writing your own
  756. <literal>ObjectDefinitionSource</literal>, although this is beyond the
  757. scope of this document. Irrespective of the approach used, the
  758. <literal>ObjectDefinitionSource</literal> is responsible for returning
  759. a <literal>ConfigAttributeDefinition</literal> object that contains
  760. all of the configuration attributes associated with a single secure
  761. HTTP URL.</para>
  762. <para>It should be noted that the
  763. <literal>FilterSecurityInterceptor.setObjectDefinitionSource()</literal>
  764. method actually expects an instance of
  765. <literal>FilterInvocationDefinitionSource</literal>. This is a marker
  766. interface which subclasses <literal>ObjectDefinitionSource</literal>.
  767. It simply denotes the <literal>ObjectDefinitionSource</literal>
  768. understands <literal>FilterInvocation</literal>s. In the interests of
  769. simplicity we'll continue to refer to the
  770. <literal>FilterInvocationDefinitionSource</literal> as an
  771. <literal>ObjectDefinitionSource</literal>, as the distinction is of
  772. little relevance to most users of the
  773. <literal>FilterSecurityInterceptor</literal>.</para>
  774. <para>If using the application context property editor approach (as
  775. shown above), commas are used to delimit the different configuration
  776. attributes that apply to each HTTP URL. Each configuration attribute
  777. is assigned into its own <literal>SecurityConfig</literal> object. The
  778. <literal>SecurityConfig</literal> object is discussed in the High
  779. Level Design section. The <literal>ObjectDefinitionSource</literal>
  780. created by the property editor,
  781. <literal>FilterInvocationDefinitionSource</literal>, matches
  782. configuration attributes against <literal>FilterInvocations</literal>
  783. based on expression evaluation of the request URL. Two standard
  784. expression syntaxes are supported. The default is to treat all
  785. expressions as regular expressions. Alternatively, the presence of a
  786. <literal>PATTERN_TYPE_APACHE_ANT</literal> directive will cause all
  787. expressions to be treated as Apache Ant paths. It is not possible to
  788. mix expression syntaxes within the same definition. For example, the
  789. earlier configuration could be generated using Apache Ant paths as
  790. follows:</para>
  791. <para><programlisting>&lt;bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;
  792. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  793. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  794. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  795. &lt;property name="objectDefinitionSource"&gt;
  796. &lt;value&gt;
  797. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  798. PATTERN_TYPE_APACHE_ANT
  799. /secure/super/**=ROLE_WE_DONT_HAVE
  800. /secure/**=ROLE_SUPERVISOR,ROLE_TELLER
  801. &lt;/value&gt;
  802. &lt;/property&gt;
  803. &lt;/bean&gt;</programlisting></para>
  804. <para>Irrespective of the type of expression syntax used, expressions
  805. are always evaluated in the order they are defined. Thus it is
  806. important that more specific expressions are defined higher in the
  807. list than less specific expressions. This is reflected in our example
  808. above, where the more specific <literal>/secure/super/</literal>
  809. pattern appears higher than the less specific
  810. <literal>/secure/</literal> pattern. If they were reversed, the
  811. <literal>/secure/</literal> pattern would always match and the
  812. <literal>/secure/super/</literal> pattern would never be
  813. evaluated.</para>
  814. <para>The special keyword
  815. <literal>CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</literal> causes
  816. the <literal>FilterInvocationDefinitionSource</literal> to
  817. automatically convert a request URL to lowercase before comparison
  818. against the expressions. Whilst by default the case of the request URL
  819. is not converted, it is generally recommended to use
  820. <literal>CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</literal> and
  821. write each expression assuming lowercase.</para>
  822. <para>As with other security interceptors, the
  823. <literal>validateConfigAttributes</literal> property is observed. When
  824. set to <literal>true</literal> (the default), at startup time the
  825. <literal>FilterSecurityInterceptor</literal> will evaluate if the
  826. provided configuration attributes are valid. It does this by checking
  827. each configuration attribute can be processed by either the
  828. <literal>AccessDecisionManager</literal> or the
  829. <literal>RunAsManager</literal>. If neither of these can process a
  830. given configuration attribute, an exception is thrown.</para>
  831. </sect2>
  832. </sect1>
  833. <sect1 id="security-authentication">
  834. <title>Authentication</title>
  835. <sect2 id="security-authentication-requests">
  836. <title>Authentication Requests</title>
  837. <para>Authentication requires a way for client code to present its
  838. security identification to the Acegi Security System for Spring. This
  839. is the role of the <literal>Authentication</literal> interface. The
  840. <literal>Authentication</literal> interface holds three important
  841. objects: the principal (the identity of the caller), the credentials
  842. (the proof of the identity of the caller, such as a password), and the
  843. authorities that have been granted to the principal. The principal and
  844. its credentials are populated by the client code, whilst the granted
  845. authorities are populated by the
  846. <literal>AuthenticationManager</literal>.</para>
  847. <para><mediaobject>
  848. <imageobject role="html">
  849. <imagedata align="center" fileref="images/Authentication.gif"
  850. format="GIF" />
  851. </imageobject>
  852. <caption>
  853. <para>Figure 3: Key Authentication Architecture</para>
  854. </caption>
  855. </mediaobject></para>
  856. <para>As shown in Figure 3, the Acegi Security System for Spring
  857. includes several concrete <literal>Authentication</literal>
  858. implementations:</para>
  859. <itemizedlist spacing="compact">
  860. <listitem>
  861. <para><literal>UsernamePasswordAuthenticationToken</literal>
  862. allows a username and password to be presented as the principal
  863. and credentials respectively. It is also what is created by the
  864. HTTP Session Authentication system.</para>
  865. </listitem>
  866. <listitem>
  867. <para><literal>TestingAuthenticationToken</literal> facilitates
  868. unit testing by automatically being considered an authenticated
  869. object by its associated
  870. <literal>AuthenticationProvider</literal>.</para>
  871. </listitem>
  872. <listitem>
  873. <para><literal>RunAsUserToken</literal> is used by the default
  874. run-as authentication replacement implementation. This is
  875. discussed further in the Run-As Authentication Replacement
  876. section.</para>
  877. </listitem>
  878. <listitem>
  879. <para><literal>CasAuthenticationToken</literal> is used to
  880. represent a successful Yale Central Authentication Service (CAS)
  881. authentication. This is discussed further in the CAS
  882. section.</para>
  883. </listitem>
  884. <listitem>
  885. <para><literal>PrincipalAcegiUserToken</literal> and
  886. <literal>JettyAcegiUserToken</literal> implement
  887. <literal>AuthByAdapter</literal> (a subclass of
  888. <literal>Authentication</literal>) and are used whenever
  889. authentication is completed by Acegi Security System for Spring
  890. container adapters. This is discussed further in the Container
  891. Adapters section.</para>
  892. </listitem>
  893. </itemizedlist>
  894. <para>The authorities granted to a principal are represented by the
  895. <literal>GrantedAuthority</literal> interface. The
  896. <literal>GrantedAuthority</literal> interface is discussed at length
  897. in the Authorization section.</para>
  898. </sect2>
  899. <sect2 id="security-authentication-manager">
  900. <title>Authentication Manager</title>
  901. <para>As discussed in the Security Interception section, the
  902. <literal>AbstractSecurityInterceptor</literal> extracts the
  903. <literal>Authentication</literal> object from the
  904. <literal>SecureContext</literal> in the
  905. <literal>ContextHolder</literal>. This is then passed to an
  906. <literal>AuthenticationManager</literal>. The
  907. <literal>AuthenticationManager</literal> interface is very
  908. simple:</para>
  909. <programlisting>public Authentication authenticate(Authentication authentication) throws AuthenticationException;</programlisting>
  910. <para>Implementations of <literal>AuthenticationManager</literal> are
  911. required to throw an <literal>AuthenticationException</literal> should
  912. authentication fail, or return a fully populated
  913. <literal>Authentication</literal> object. In particular, the returned
  914. <literal>Authentication</literal> object should contain an array of
  915. <literal>GrantedAuthority</literal> objects. The
  916. <literal>SecurityInterceptor</literal> places the populated
  917. <literal>Authentication</literal> object back in the
  918. <literal>SecureContext</literal> in the
  919. <literal>ContextHolder</literal>, overwriting the original
  920. <literal>Authentication</literal> object.</para>
  921. <para>The <literal>AuthenticationException</literal> has a number of
  922. subclasses. The most important are
  923. <literal>BadCredentialsException</literal> (an incorrect principal or
  924. credentials), <literal>DisabledException</literal> and
  925. <literal>LockedException</literal>. The latter two exceptions indicate
  926. the principal was found, but the credentials were not checked and
  927. authentication is denied. An
  928. <literal>AuthenticationServiceException</literal> is also provided,
  929. which indicates the authentication system could not process the
  930. request (eg a database was unavailable).
  931. <literal>AuthenticationException</literal> also has a
  932. <literal>CredentialsExpiredException</literal> and
  933. <literal>AccoungtExpiredException</literal> subclass, although these
  934. are less commonly used.</para>
  935. </sect2>
  936. <sect2 id="security-authentication-provider">
  937. <title>Provider-Based Authentication</title>
  938. <para>Whilst the basic <literal>Authentication</literal> and
  939. <literal>AuthenticationManager</literal> interfaces enable users to
  940. develop their own authentication systems, users should consider using
  941. the provider-based authentication packages provided by the Acegi
  942. Security System for Spring. The key class,
  943. <literal>ProviderManager</literal>, is configured via the bean context
  944. with a list of <literal>AuthenticationProvider</literal>s:</para>
  945. <para><programlisting>&lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt;
  946. &lt;property name="providers"&gt;
  947. &lt;list&gt;
  948. &lt;ref bean="daoAuthenticationProvider"/&gt;
  949. &lt;ref bean="someOtherAuthenticationProvider"/&gt;
  950. &lt;/list&gt;
  951. &lt;/property&gt;
  952. &lt;/bean&gt;</programlisting></para>
  953. <para><literal>ProviderManager</literal> calls a series of registered
  954. <literal>AuthenticationProvider</literal> implementations, until one
  955. is found that indicates it is able to authenticate a given
  956. <literal>Authentication</literal> class. When the first compatible
  957. <literal>AuthenticationProvider</literal> is located, it is passed the
  958. authentication request. The <literal>AuthenticationProvider</literal>
  959. will then either throw an <literal>AuthenticationException</literal>
  960. or return a fully populated <literal>Authentication</literal>
  961. object.</para>
  962. <para>Note the <literal>ProviderManager</literal> may throw a
  963. <literal>ProviderNotFoundException</literal> (a subclass of
  964. <literal>AuthenticationException</literal>) if it none of the
  965. registered <literal>AuthenticationProviders</literal> can validate the
  966. <literal>Authentication</literal> object.</para>
  967. <para>Several <literal>AuthenticationProvider</literal>
  968. implementations are provided with the Acegi Security System for
  969. Spring:</para>
  970. <para><itemizedlist spacing="compact">
  971. <listitem>
  972. <para><literal>TestingAuthenticationProvider</literal> is able
  973. to authenticate a <literal>TestingAuthenticationToken</literal>.
  974. The limit of its authentication is simply to treat whatever is
  975. contained in the <literal>TestingAuthenticationToken</literal>
  976. as valid. This makes it ideal for use during unit testing, as
  977. you can create an <literal>Authentication</literal> object with
  978. precisely the <literal>GrantedAuthority</literal> objects
  979. required for calling a given method. You definitely would not
  980. register this <literal>AuthenticationProvider</literal> on a
  981. production system.</para>
  982. </listitem>
  983. <listitem>
  984. <para><literal>DaoAuthenticationProvider</literal> is able to
  985. authenticate a
  986. <literal>UsernamePasswordAuthenticationToken</literal> by
  987. accessing an authentication respository via a data access
  988. object. This is discussed further below, as it is the main way
  989. authentication is initially handled.</para>
  990. </listitem>
  991. <listitem>
  992. <para><literal>RunAsImplAuthenticationToken</literal> is able to
  993. authenticate a <literal>RunAsUserToken</literal>. This is
  994. discussed further in the Run-As Authentication Replacement
  995. section. You would not register this
  996. <literal>AuthenticationProvider</literal> if you were not using
  997. run-as replacement.</para>
  998. </listitem>
  999. <listitem>
  1000. <para><literal>AuthByAdapterProvider</literal> is able to
  1001. authenticate any <literal>AuthByAdapter</literal> (a subclass of
  1002. <literal>Authentication</literal> used with container adapters).
  1003. This is discussed further in the Container Adapters section. You
  1004. would not register this
  1005. <literal>AuthenticationProvider</literal> if you were not using
  1006. container adapters.</para>
  1007. </listitem>
  1008. <listitem>
  1009. <para><literal>CasAuthenticationProvider</literal> is able to
  1010. authenticate Yale Central Authentication Service (CAS) tickets.
  1011. This is discussed further in the CAS Single Sign On
  1012. section.</para>
  1013. </listitem>
  1014. <listitem>
  1015. <para><literal>JaasAuthenticationProvider</literal> is able to
  1016. delegate authentication requests to a JAAS
  1017. <literal>LoginModule</literal>. This is discussed further
  1018. below.</para>
  1019. </listitem>
  1020. </itemizedlist></para>
  1021. </sect2>
  1022. <sect2 id="security-authentication-provider-dao">
  1023. <title>Data Access Object Authentication Provider</title>
  1024. <para>The Acegi Security System for Spring includes a
  1025. production-quality <literal>AuthenticationProvider</literal>
  1026. implementation called <literal>DaoAuthenticationProvider</literal>.
  1027. This authentication provider is able to authenticate a
  1028. <literal>UsernamePasswordAuthenticationToken</literal> by obtaining
  1029. authentication details from a data access object configured at bean
  1030. creation time:</para>
  1031. <para><programlisting>&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;
  1032. &lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
  1033. &lt;property name="saltSource"&gt;&lt;ref bean="saltSource"/&gt;&lt;/property&gt;
  1034. &lt;property name="passwordEncoder"&gt;&lt;ref bean="passwordEncoder"/&gt;&lt;/property&gt;
  1035. &lt;/bean&gt;</programlisting></para>
  1036. <para>The <literal>PasswordEncoder</literal> and
  1037. <literal>SaltSource</literal> are optional. A
  1038. <literal>PasswordEncoder</literal> provides encoding and decoding of
  1039. passwords obtained from the authentication repository. A
  1040. <literal>SaltSource</literal> enables the passwords to be populated
  1041. with a "salt", which enhances the security of the passwords in the
  1042. authentication repository. <literal>PasswordEncoder</literal>
  1043. implementations are provided with the Acegi Security System for Spring
  1044. covering MD5, SHA and cleartext encodings. Two
  1045. <literal>SaltSource</literal> implementations are also provided:
  1046. <literal>SystemWideSaltSource</literal> which encodes all passwords
  1047. with the same salt, and <literal>ReflectionSaltSource</literal>, which
  1048. inspects a given property of the returned
  1049. <literal>UserDetails</literal> object to obtain the salt. Please refer
  1050. to the JavaDocs for further details on these optional features.</para>
  1051. <para>In addition to the properties above, the
  1052. <literal>DaoAuthenticationProvider</literal> supports optional caching
  1053. of <literal>UserDetails</literal> objects. The
  1054. <literal>UserCache</literal> interface enables the
  1055. <literal>DaoAuthenticationProvider</literal> to place a
  1056. <literal>UserDetails</literal> object into the cache, and retrieve it
  1057. from the cache upon subsequent authentication attempts for the same
  1058. username. By default the <literal>DaoAuthenticationProvider</literal>
  1059. uses the <literal>NullUserCache</literal>, which performs no caching.
  1060. A usable caching implementation is also provided,
  1061. <literal>EhCacheBasedUserCache</literal>, which is configured as
  1062. follows:</para>
  1063. <para><programlisting>&lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;
  1064. &lt;property name="authenticationDao"&gt;&lt;ref bean="authenticationDao"/&gt;&lt;/property&gt;
  1065. &lt;property name="userCache"&gt;&lt;ref bean="userCache"/&gt;&lt;/property&gt;
  1066. &lt;/bean&gt;
  1067. &lt;bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"&gt;
  1068. &lt;property name="configLocation"&gt;
  1069. &lt;value&gt;classpath:/ehcache-failsafe.xml&lt;/value&gt;
  1070. &lt;/property&gt;
  1071. &lt;/bean&gt;
  1072. &lt;bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;
  1073. &lt;property name="cacheManager"&gt;
  1074. &lt;ref local="cacheManager"/&gt;
  1075. &lt;/property&gt;
  1076. &lt;property name="cacheName"&gt;
  1077. &lt;value&gt;userCache&lt;/value&gt;
  1078. &lt;/property&gt;
  1079. &lt;/bean&gt;
  1080. &lt;bean id="userCache" class="net.sf.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"&gt;
  1081. &lt;property name="cache"&gt;&lt;ref local="userCacheBackend"/&gt;&lt;/property&gt;
  1082. &lt;/bean&gt;</programlisting></para>
  1083. <para>All Acegi Security EH-CACHE implementations (including
  1084. <literal>EhCacheBasedUserCache</literal>) require an EH-CACHE
  1085. <literal>Cache</literal> object. The <literal>Cache</literal> object
  1086. can be obtained from wherever you like, although we recommend you use
  1087. Spring's factory classes as shown in the above configuration. If using
  1088. Spring's factory classes, please refer to the Spring documentation for
  1089. further details on how to optimise the cache storage location, memory
  1090. usage, eviction policies, timeouts etc.</para>
  1091. <para>For a class to be able to provide the
  1092. <literal>DaoAuthenticationProvider</literal> with access to an
  1093. authentication repository, it must implement the
  1094. <literal>AuthenticationDao</literal> interface:</para>
  1095. <para><programlisting>public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;</programlisting></para>
  1096. <para>The <literal>UserDetails</literal> is an interface that provides
  1097. getters that guarantee non-null provision of basic authentication
  1098. information such as the username, password, granted authorities and
  1099. whether the user is enabled or disabled. A concrete implementation,
  1100. <literal>User</literal>, is also provided. Acegi Security users will
  1101. need to decide when writing their <literal>AuthenticationDao</literal>
  1102. what type of <literal>UserDetails</literal> to return. In most cases
  1103. <literal>User</literal> will be used directly or subclassed, although
  1104. special circumstances (such as object relational mappers) may require
  1105. users to write their own <literal>UserDetails</literal> implementation
  1106. from scratch. <literal>UserDetails</literal> is often used to store
  1107. additional principal-related properties (such as their telephone
  1108. number and email address), so they can be easily used by web
  1109. views.</para>
  1110. <para>Given <literal>AuthenticationDao</literal> is so simple to
  1111. implement, it should be easy for users to retrieve authentication
  1112. information using a persistence strategy of their choice.</para>
  1113. <para>A design decision was made not to support account locking in the
  1114. <literal>DaoAuthenticationProvider</literal>, as doing so would have
  1115. increased the complexity of the <literal>AuthenticationDao</literal>
  1116. interface. For instance, a method would be required to increase the
  1117. count of unsuccessful authentication attempts. Such functionality
  1118. could be easily provided by leveraging the application event
  1119. publishing features discussed below.</para>
  1120. <para><literal>DaoAuthenticationProvider</literal> returns an
  1121. <literal>Authentication</literal> object which in turn has its
  1122. <literal>principal</literal> property set. The principal will be
  1123. either a <literal>String</literal> (which is essentially the username)
  1124. or a <literal>UserDetails</literal> object (which was looked up from
  1125. the <literal>AuthenticationDao</literal>). By default the
  1126. <literal>UserDetails</literal> is returned, as this enables
  1127. applications to add extra properties potentially of use in
  1128. applications, such as the user's full name, email address etc. If
  1129. using container adapters, or if your applications were written to
  1130. operate with <literal>String</literal>s (as was the case for releases
  1131. prior to Acegi Security 0.6), you should set the
  1132. <literal>DaoAuthenticationProvider.forcePrincipalAsString</literal>
  1133. property to <literal>true</literal> in your application
  1134. context.</para>
  1135. </sect2>
  1136. <sect2 id="security-authentication-provider-events">
  1137. <title>Event Publishing</title>
  1138. <para>The <literal>DaoAuthenticationProvider</literal> automatically
  1139. obtains the <literal>ApplicationContext</literal> it is running in at
  1140. startup time. This allows the provider to publish events through the
  1141. standard Spring event framework. Three types of event messages are
  1142. published:</para>
  1143. <itemizedlist spacing="compact">
  1144. <listitem>
  1145. <para><literal>AuthenticationSuccessEvent</literal> is published
  1146. when an authentication request is successful.</para>
  1147. </listitem>
  1148. <listitem>
  1149. <para><literal>AuthenticationFailureDisabledEvent</literal> is
  1150. published when an authentication request is unsuccessful because
  1151. the returned <literal>UserDetails</literal> is disabled. This is
  1152. normally the case when an account is locked.</para>
  1153. </listitem>
  1154. <listitem>
  1155. <para><literal>AuthenticationFailureAccountExpiredEvent</literal>
  1156. is published when an authentication request is unsuccessful
  1157. because the returned <literal>UserDetails</literal> indicates the
  1158. account has expired. Some applications may wish to distinguish
  1159. between an account being disabled and expired.</para>
  1160. </listitem>
  1161. <listitem>
  1162. <para><literal>AuthenticationFailureCredentialsExpiredEvent</literal>
  1163. is published when an authentication request is unsuccessful
  1164. because the returned <literal>UserDetails</literal> indicates the
  1165. account's credentials have expired. Some applications may wish to
  1166. expire the credentials if, for example, a password is not changed
  1167. with sufficient regularity.</para>
  1168. </listitem>
  1169. <listitem>
  1170. <para><literal>AuthenticationFailureUsernameNotFoundEvent</literal>
  1171. is published when an authentication request is unsuccessful
  1172. because the <literal>AuthenticationDao</literal> could not locate
  1173. the <literal>UserDetails</literal>.</para>
  1174. </listitem>
  1175. <listitem>
  1176. <para><literal>AuthenticationFailurePasswordEvent</literal> is
  1177. published when an authentication request is unsuccessful because
  1178. the presented password did not match that in the
  1179. <literal>UserDetails</literal>.</para>
  1180. </listitem>
  1181. </itemizedlist>
  1182. <para>Each event contains two objects: the
  1183. <literal>Authentication</literal> object that represented the
  1184. authentication request, and the <literal>UserDetails</literal> object
  1185. that was found in response to the authentication request (clearly the
  1186. latter will be a dummy object in the case of
  1187. <literal>AuthenticationFailureUsernameNotFoundEvent</literal>). The
  1188. <literal>Authentication</literal> interface provides a
  1189. <literal>getDetails()</literal> method which often includes
  1190. information that event consumers may find useful (eg the TCP/IP
  1191. address that the authentication request originated from).</para>
  1192. <para>As per standard Spring event handling, you can receive these
  1193. events by adding a bean to the application context which implements
  1194. the <literal>ApplicationListener</literal> interface. Included with
  1195. Acegi Security is a <literal>LoggerListener</literal> class which
  1196. receives these events and publishes their details to Commons Logging.
  1197. Refer to the JavaDocs for <literal>LoggerListener</literal> for
  1198. details on the logging priorities used for different message
  1199. types.</para>
  1200. <para>This event publishing system enables you to implement account
  1201. locking and record authentication event history. This might be of
  1202. interest to application users, who can be advised of the times and
  1203. source IP address of all unsuccessful password attempts (and account
  1204. lockouts) since their last successful login. Such capabilities are
  1205. simple to implement and greatly improve the security of your
  1206. application.</para>
  1207. </sect2>
  1208. <sect2 id="security-authentication-provider-in-memory">
  1209. <title>In-Memory Authentication</title>
  1210. <para>Whilst it is easy to use the
  1211. <literal>DaoAuthenticationProvider</literal> and create a custom
  1212. <literal>AuthenticationDao</literal> implementation that extracts
  1213. information from a persistence engine of choice, many applications do
  1214. not require such complexity. One alternative is to configure an
  1215. authentication repository in the application context itself using the
  1216. <literal>InMemoryDaoImpl</literal>:</para>
  1217. <para><programlisting>&lt;bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl"&gt;
  1218. &lt;property name="userMap"&gt;
  1219. &lt;value&gt;
  1220. marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR
  1221. dianne=emu,ROLE_TELLER
  1222. scott=wombat,ROLE_TELLER
  1223. peter=opal,disabled,ROLE_TELLER
  1224. &lt;/value&gt;
  1225. &lt;/property&gt;
  1226. &lt;/bean&gt;</programlisting></para>
  1227. <para>The <literal>userMap</literal> property contains each of the
  1228. usernames, passwords, a list of granted authorities and an optional
  1229. enabled/disabled keyword. Commas delimit each token. The username must
  1230. appear to the left of the equals sign, and the password must be the
  1231. first token to the right of the equals sign. The
  1232. <literal>enabled</literal> and <literal>disabled</literal> keywords
  1233. (case insensitive) may appear in the second or any subsequent token.
  1234. Any remaining tokens are treated as granted authorities, which are
  1235. created as <literal>GrantedAuthorityImpl</literal> objects (refer to
  1236. the Authorization section for further discussion on granted
  1237. authorities). Note that if a user has no password and/or no granted
  1238. authorities, the user will not be created in the in-memory
  1239. authentication repository.</para>
  1240. </sect2>
  1241. <sect2 id="security-authentication-provider-jdbc">
  1242. <title>JDBC Authentication</title>
  1243. <para>The Acegi Security System for Spring also includes an
  1244. authentication provider that can obtain authentication information
  1245. from a JDBC data source. The typical configuration for the
  1246. <literal>JdbcDaoImpl</literal> is shown below:</para>
  1247. <para><programlisting>&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
  1248. &lt;property name="driverClassName"&gt;&lt;value&gt;org.hsqldb.jdbcDriver&lt;/value&gt;&lt;/property&gt;
  1249. &lt;property name="url"&gt;&lt;value&gt;jdbc:hsqldb:hsql://localhost:9001&lt;/value&gt;&lt;/property&gt;
  1250. &lt;property name="username"&gt;&lt;value&gt;sa&lt;/value&gt;&lt;/property&gt;
  1251. &lt;property name="password"&gt;&lt;value&gt;&lt;/value&gt;&lt;/property&gt;
  1252. &lt;/bean&gt;
  1253. &lt;bean id="jdbcDaoImpl" class="net.sf.acegisecurity.providers.dao.jdbc.JdbcDaoImpl"&gt;
  1254. &lt;property name="dataSource"&gt;&lt;ref bean="dataSource"/&gt;&lt;/property&gt;
  1255. &lt;/bean&gt;</programlisting></para>
  1256. <para>You can use different relational database management systems by
  1257. modifying the <literal>DriverManagerDataSource</literal> shown above.
  1258. Irrespective of the database used, a standard schema must be used as
  1259. indicated in <literal>dbinit.txt</literal>.</para>
  1260. <para>If you default schema is unsuitable for your needs,
  1261. <literal>JdbcDaoImpl</literal> provides two properties that allow
  1262. customisation of the SQL statements. You may also subclass the
  1263. <literal>JdbcDaoImpl</literal> if further customisation is necessary.
  1264. Please refer to the JavaDocs for details.</para>
  1265. <para>The Acegi Security System for Spring ships with a Hypersonic SQL
  1266. instance that has the required authentication information and sample
  1267. data already populated. To use this server, simply execute the
  1268. <literal>server.bat</literal> or <literal>server.sh</literal> script
  1269. included in the distribution. This will load a new database server
  1270. instance that will service requests made to the URL indicated in the
  1271. bean context configuration shown above.</para>
  1272. </sect2>
  1273. <sect2 id="security-authentication-concurrent-login">
  1274. <title>Concurrent Session Support</title>
  1275. <para>Acegi Security is able to stop the same principal authenticating
  1276. to the same web application multiple times concurrently. Put
  1277. differently, you can stop user "Batman" from logging into a web
  1278. application twice at the same time.</para>
  1279. <para>To use concurrent session support, you'll need to add the
  1280. following to web.xml:</para>
  1281. <para><programlisting>&lt;listener&gt;
  1282. &lt;listener-class&gt;net.sf.acegisecurity.ui.session.HttpSessionEventPublisher&lt;/listener-class&gt;
  1283. &lt;/listener&gt;</programlisting></para>
  1284. <para>The above code causes an <literal>ApplicationEvent</literal> to
  1285. be published to the Spring <literal>ApplicationContext</literal> every
  1286. time a <literal>HttpSession</literal> commences or terminates. This is
  1287. critical, as it allows the
  1288. <literal>ConcurrentSessionControllerImpl</literal> to be notified when
  1289. a session ends. Next up you'll need to wire the
  1290. <literal>ConcurrentSessionControllerImpl</literal> into your existing
  1291. <literal>ProviderManager</literal>:</para>
  1292. <para><programlisting>&lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt;
  1293. &lt;property name="providers"&gt;
  1294. &lt;!-- your providers go here --&gt;
  1295. &lt;/property&gt;
  1296. &lt;property name="sessionController"&gt;&lt;ref bean="concurrentSessionController"/&gt;&lt;/property&gt;
  1297. &lt;/bean&gt;
  1298. &lt;bean id="concurrentSessionController" class="net.sf.acegisecurity.providers.ConcurrentSessionControllerImpl"&gt;
  1299. &lt;property name="maxSessions"&gt;&lt;value&gt;1&lt;/value&gt;&lt;/property&gt;
  1300. &lt;/bean&gt;</programlisting></para>
  1301. <para>Ensure you do not in-line the
  1302. <literal>ConcurrentSessionControllerImpl</literal> when declaring it
  1303. in your XML. This is important, as it appears that in-lined bean
  1304. declarations do not receive ApplicationEvents.</para>
  1305. <para>The <literal>ConcurrentSessionControllerImpl</literal> relies
  1306. heavily on the
  1307. <literal>Authentication.getPrincipal().equals()</literal> method. If
  1308. you are using a custom <literal>Authentication</literal> object,
  1309. please keep this in mind. In order for the
  1310. <literal>ConcurrentSessionControllerImpl</literal> to release a given
  1311. <literal>HttpSession</literal>, and thus let the user log in to a new
  1312. <literal>HttpSession</literal>, the existing
  1313. <literal>HttpSession</literal> must be invalidated. For example, if
  1314. "Batman" logs into the web application, checks for crimes being
  1315. commited, and the just closes his browser with out "logging out", he
  1316. will not be able to log back in until his
  1317. <literal>HttpSession</literal> is timed out by the server (and a
  1318. corresponding <literal>ApplicationEvent</literal> is published via
  1319. <literal>HttpSessionEventPublisher</literal> to the
  1320. <literal>ConcurrentSessionControllerImpl</literal>). You would have to
  1321. look at your container's documentation to determine the default
  1322. timeout period. You can also configure the session timeout in your
  1323. <literal>web.xml</literal>:<programlisting>&lt;session-config&gt;
  1324. &lt;session-timeout&gt;30&lt;/session-timeout&gt;
  1325. &lt;/session-config&gt;</programlisting></para>
  1326. </sect2>
  1327. <sect2 id="security-authentication-provider-jaas">
  1328. <title>JAAS Authentication</title>
  1329. <para>Acegi Security provides a package able to delegate
  1330. authentication requests to the Java Authentication and Authorization
  1331. Service (JAAS). This package is discussed in detail below.</para>
  1332. <para>Central to JAAS operation are login configuration files. To
  1333. learn more about JAAS login configuration files, consult the JAAS
  1334. reference documentation available from Sun Microsystems. We expect you
  1335. to have a basic understanding of JAAS and its login configuration file
  1336. syntax in order to understand this section.</para>
  1337. <sect3>
  1338. <title>JaasAuthenticationProvider</title>
  1339. <para>The <literal>JaasAuthenticationProvider</literal> attempts to
  1340. authenticate a user’s principal and credentials through JAAS.</para>
  1341. <para>Let’s assume we have a JAAS login configuration file,
  1342. <literal>/WEB-INF/login.conf</literal>, with the following
  1343. contents:</para>
  1344. <para><programlisting>JAASTest {
  1345. sample.SampleLoginModule required;
  1346. };</programlisting></para>
  1347. <para>Like all Acegi Security beans, the
  1348. <literal>JaasAuthenticationProvider</literal> is configured via the
  1349. application context. The following definitions would correspond to
  1350. the above JAAS login configuration file:</para>
  1351. <para><programlisting>&lt;bean id="jaasAuthenticationProvider" class="net.sf.acegisecurity.providers.jaas.JaasAuthenticationProvider"&gt;
  1352. &lt;property name="loginConfig"&gt;
  1353. &lt;value&gt;/WEB-INF/login.conf&lt;/value&gt;
  1354. &lt;/property&gt;
  1355. &lt;property name="loginContextName"&gt;
  1356. &lt;value&gt;JAASTest&lt;/value&gt;
  1357. &lt;/property&gt;
  1358. &lt;property name="callbackHandlers"&gt;
  1359. &lt;list&gt;
  1360. &lt;bean class="net.sf.acegisecurity.providers.jaas.JaasNameCallbackHandler"/&gt;
  1361. &lt;bean class="net.sf.acegisecurity.providers.jaas.JaasPasswordCallbackHandler"/&gt;
  1362. &lt;/list&gt;
  1363. &lt;/property&gt;
  1364. &lt;property name="authorityGranters"&gt;
  1365. &lt;list&gt;
  1366. &lt;bean class="net.sf.acegisecurity.providers.jaas.TestAuthorityGranter"/&gt;
  1367. &lt;/list&gt;
  1368. &lt;/property&gt;
  1369. &lt;/bean&gt;</programlisting></para>
  1370. <para>The <literal>CallbackHandler</literal>s and
  1371. <literal>AuthorityGranter</literal>s are discussed below.</para>
  1372. </sect3>
  1373. <sect3>
  1374. <title>Callbacks</title>
  1375. <para>Most JAAS <literal>LoginModule</literal>s require a callback
  1376. of some sort. These callbacks are usually used to obtain the
  1377. username and password from the user. In an Acegi Security
  1378. deployment, Acegi Security is responsible for this user interaction
  1379. (typically via a reference to a
  1380. <literal>ContextHolder</literal>-managed
  1381. <literal>Authentication</literal> object). The JAAS package for
  1382. Acegi Security provides two default callback handlers,
  1383. <literal>JaasNameCallbackHandler</literal> and
  1384. <literal>JaasPasswordCallbackHandler</literal>. Each of these
  1385. callback handlers implement
  1386. <literal>JaasAuthenticationCallbackHandler</literal>. In most cases
  1387. these callback handlers can simply be used without understanding the
  1388. internal mechanics. For those needing full control over the callback
  1389. behavior, internally <literal>JaasAutheticationProvider</literal>
  1390. wraps these <literal>JaasAuthenticationCallbackHandler</literal>s
  1391. with an <literal>InternalCallbackHandler</literal>. The
  1392. <literal>InternalCallbackHandler</literal> is the class that
  1393. actually implements JAAS’ normal <literal>CallbackHandler</literal>
  1394. interface. Any time that the JAAS <literal>LoginModule</literal> is
  1395. used, it is passed a list of application context configured
  1396. <literal>InternalCallbackHandler</literal>s. If the
  1397. <literal>LoginModule</literal> requests a callback against the
  1398. <literal>InternalCallbackHandler</literal>s, the callback is in-turn
  1399. passed to the <literal>JaasAuthenticationCallbackHandler</literal>s
  1400. being wrapped.</para>
  1401. </sect3>
  1402. <sect3>
  1403. <title>AuthorityGranters</title>
  1404. <para>JAAS works with principals. Even “roles” are represented as
  1405. principals in JAAS. Acegi Security, on the other hand, works with
  1406. <literal>Authentication</literal> objects. Each
  1407. <literal>Authentication</literal> object contains a single
  1408. principal, and multiple <literal>GrantedAuthority</literal>[]s. To
  1409. facilitate mapping between these different concepts, the Acegi
  1410. Security JAAS package includes an
  1411. <literal>AuthorityGranter</literal> interface. An
  1412. <literal>AuthorityGranter</literal> is responsible for inspecting a
  1413. JAAS principal and returning a <literal>String</literal>. The
  1414. <literal>JaasAuthenticationProvider</literal> then creates a
  1415. <literal>JaasGrantedAuthority</literal> (which implements Acegi
  1416. Security’s <literal>GrantedAuthority</literal> interface) containing
  1417. both the <literal>AuthorityGranter</literal>-returned
  1418. <literal>String</literal> and the JAAS principal that the
  1419. <literal>AuthorityGranter</literal> was passed. The
  1420. <literal>JaasAuthenticationProvider</literal> obtains the JAAS
  1421. principals by firstly successfully authenticating the user’s
  1422. credentials using the JAAS <literal>LoginModule</literal>, and then
  1423. accessing the <literal>LoginContext</literal> it returns. A call to
  1424. <literal>LoginContext.getSubject().getPrincipals()</literal> is
  1425. made, with each resulting principal passed to each
  1426. <literal>AuthorityGranter</literal> defined against the
  1427. <literal>JaasAuthenticationProvider.setAuthorityGranters(List)</literal>
  1428. property. Acegi Security does not include any production
  1429. <literal>AuthorityGranter</literal>s given every JAAS principal has
  1430. an implementation-specific meaning. However, there is a
  1431. <literal>TestAuthorityGranter</literal> in the unit tests that
  1432. demonstrates a simple <literal>AuthorityGranter</literal>
  1433. implementation.</para>
  1434. </sect3>
  1435. </sect2>
  1436. <sect2 id="security-authentication-recommendations">
  1437. <title>Authentication Recommendations</title>
  1438. <para>With the heavy use of interfaces throughout the authentication
  1439. system (<literal>Authentication</literal>,
  1440. <literal>AuthenticationManager</literal>,
  1441. <literal>AuthenticationProvider</literal> and
  1442. <literal>AuthenticationDao</literal>) it might be confusing to a new
  1443. user to know which part of the authentication system to customize. In
  1444. general, the following is recommended:</para>
  1445. <itemizedlist>
  1446. <listitem>
  1447. <para>Use the
  1448. <literal>UsernamePasswordAuthenticationToken</literal>
  1449. implementation where possible.</para>
  1450. </listitem>
  1451. <listitem>
  1452. <para>If you simply need to implement a new authentication
  1453. repository (eg to obtain user details from your application’s
  1454. existing database), use the
  1455. <literal>DaoAuthenticationProvider</literal> along with the
  1456. <literal>AuthenticationDao</literal>. It is the fastest and safest
  1457. way to integrate an external database.</para>
  1458. </listitem>
  1459. <listitem>
  1460. <para>If you're using Container Adapters or a
  1461. <literal>RunAsManager</literal> that replaces the
  1462. <literal>Authentication</literal> object, ensure you have
  1463. registered the <literal>AuthByAdapterProvider</literal> and
  1464. <literal>RunAsManagerImplProvider</literal> respectively with your
  1465. <literal>ProviderManager</literal>.</para>
  1466. </listitem>
  1467. <listitem>
  1468. <para>Never enable the
  1469. <literal>TestingAuthenticationProvider</literal> on a production
  1470. system. Doing so will allow any client to simply present a
  1471. <literal>TestingAuthenticationToken</literal> and obtain whatever
  1472. access they request.</para>
  1473. </listitem>
  1474. <listitem>
  1475. <para>Adding a new <literal>AuthenticationProvider</literal> is
  1476. sufficient to support most custom authentication requirements.
  1477. Only unusual requirements would require the
  1478. <literal>ProviderManager</literal> to be replaced with a different
  1479. <literal>AuthenticationManager</literal>.</para>
  1480. </listitem>
  1481. </itemizedlist>
  1482. </sect2>
  1483. </sect1>
  1484. <sect1 id="security-authorization">
  1485. <title>Authorization</title>
  1486. <sect2 id="security-authorization-granted-authorities">
  1487. <title>Granted Authorities</title>
  1488. <para>As briefly mentioned in the Authentication section, all
  1489. <literal>Authentication</literal> implementations are required to
  1490. store an array of <literal>GrantedAuthority</literal> objects. These
  1491. represent the authorities that have been granted to the principal. The
  1492. <literal>GrantedAuthority</literal> objects are inserted into the
  1493. <literal>Authentication</literal> object by the
  1494. <literal>AuthenticationManager</literal> and are later read by
  1495. <literal>AccessDecisionManager</literal>s when making authorization
  1496. decisions.</para>
  1497. <para><literal>GrantedAuthority</literal> is an interface with only
  1498. one method:</para>
  1499. <para><programlisting>public String getAuthority();</programlisting></para>
  1500. <para>This method allows <literal>AccessDecisionManager</literal>s to
  1501. obtain a precise <literal>String</literal> representation of the
  1502. <literal>GrantedAuthority</literal>. By returning a representation as
  1503. a <literal>String</literal>, a <literal>GrantedAuthority</literal> can
  1504. be easily "read" by most <literal>AccessDecisionManager</literal>s. If
  1505. a <literal>GrantedAuthority</literal> cannot be precisely represented
  1506. as a <literal>String</literal>, the
  1507. <literal>GrantedAuthority</literal> is considered "complex" and
  1508. <literal>getAuthority()</literal> must return
  1509. <literal>null</literal>.</para>
  1510. <para>An example of a "complex" <literal>GrantedAuthority</literal>
  1511. would be an implementation that stores a list of operations and
  1512. authority thresholds that apply to different customer account numbers.
  1513. Representing this complex <literal>GrantedAuthority</literal> as a
  1514. <literal>String</literal> would be quite complex, and as a result the
  1515. <literal>getAuthority()</literal> method should return
  1516. <literal>null</literal>. This will indicate to any
  1517. <literal>AccessDecisionManager</literal> that it will need to
  1518. specifically support the <literal>GrantedAuthority</literal>
  1519. implementation in order to understand its contents.</para>
  1520. <para>The Acegi Security System for Spring includes one concrete
  1521. <literal>GrantedAuthority</literal> implementation,
  1522. <literal>GrantedAuthorityImpl</literal>. This allows any
  1523. user-specified <literal>String</literal> to be converted into a
  1524. <literal>GrantedAuthority</literal>. All
  1525. <literal>AuthenticationProvider</literal>s included with the security
  1526. architecture use <literal>GrantedAuthorityImpl</literal> to populate
  1527. the <literal>Authentication</literal> object.</para>
  1528. </sect2>
  1529. <sect2 id="security-authorization-access-decision-managers">
  1530. <title>Access Decision Managers</title>
  1531. <para>The <literal>AccessDecisionManager</literal> is called by the
  1532. <literal>AbstractSecurityInterceptor</literal> and is responsible for
  1533. making final access control decisions. The
  1534. <literal>AccessDecisionManager</literal> interface contains three
  1535. methods:</para>
  1536. <para><programlisting>public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException;
  1537. public boolean supports(ConfigAttribute attribute);
  1538. public boolean supports(Class clazz);</programlisting></para>
  1539. <para>As can be seen from the first method, the
  1540. <literal>AccessDecisionManager</literal> is passed via method
  1541. parameters all information that is likely to be of value in assessing
  1542. an authorization decision. In particular, passing the secure
  1543. <literal>Object</literal> enables those arguments contained in the
  1544. actual secure object invocation to be inspected. For example, let's
  1545. assume the secure object was a <literal>MethodInvocation</literal>. It
  1546. would be easy to query the <literal>MethodInvocation</literal> for any
  1547. <literal>Customer</literal> argument, and then implement some sort of
  1548. security logic in the <literal>AccessDecisionManager</literal> to
  1549. ensure the principal is permitted to operate on that customer.
  1550. Implementations are expected to throw an
  1551. <literal>AccessDeniedException</literal> if access is denied.</para>
  1552. <para>The <literal>supports(ConfigAttribute)</literal> method is
  1553. called by the <literal>AbstractSecurityInterceptor</literal> at
  1554. startup time to determine if the
  1555. <literal>AccessDecisionManager</literal> can process the passed
  1556. <literal>ConfigAttribute</literal>. The
  1557. <literal>supports(Class)</literal> method is called by a security
  1558. interceptor implementation to ensure the configured
  1559. <literal>AccessDecisionManager</literal> supports the type of secure
  1560. object that the security interceptor will present.</para>
  1561. </sect2>
  1562. <sect2 id="security-authorization-voting-decision-manager">
  1563. <title>Voting Decision Manager</title>
  1564. <para>Whilst users can implement their own
  1565. <literal>AccessDecisionManager</literal> to control all aspects of
  1566. authorization, the Acegi Security System for Spring includes several
  1567. <literal>AccessDecisionManager</literal> implementations that are
  1568. based on voting. Figure 4 illustrates the relevant classes.</para>
  1569. <para><mediaobject>
  1570. <imageobject role="html">
  1571. <imagedata align="center"
  1572. fileref="images/AccessDecisionVoting.gif"
  1573. format="GIF" />
  1574. </imageobject>
  1575. <caption>
  1576. <para>Figure 4: Voting Decision Manager</para>
  1577. </caption>
  1578. </mediaobject></para>
  1579. <para>Using this approach, a series of
  1580. <literal>AccessDecisionVoter</literal> implementations are polled on
  1581. an authorization decision. The
  1582. <literal>AccessDecisionManager</literal> then decides whether or not
  1583. to throw an <literal>AccessDeniedException</literal> based on its
  1584. assessment of the votes.</para>
  1585. <para>The <literal>AccessDecisionVoter</literal> interface has three
  1586. methods:</para>
  1587. <para><programlisting>public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
  1588. public boolean supports(ConfigAttribute attribute);
  1589. public boolean supports(Class clazz);</programlisting></para>
  1590. <para>Concrete implementations return an <literal>int</literal>, with
  1591. possible values being reflected in the
  1592. <literal>AccessDecisionVoter</literal> static fields
  1593. <literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal>
  1594. and <literal>ACCESS_GRANTED</literal>. A voting implementation will
  1595. return <literal>ACCESS_ABSTAIN</literal> if it has no opinion on an
  1596. authorization decision. If it does have an opinion, it must return
  1597. either <literal>ACCESS_DENIED</literal> or
  1598. <literal>ACCESS_GRANTED</literal>.</para>
  1599. <para>There are three concrete
  1600. <literal>AccessDecisionManager</literal>s provided with the Acegi
  1601. Security System for Spring that tally the votes. The
  1602. <literal>ConsensusBased</literal> implementation will grant or deny
  1603. access based on the consensus of non-abstain votes. Properties are
  1604. provided to control behavior in the event of an equality of votes or
  1605. if all votes are abstain. The <literal>AffirmativeBased</literal>
  1606. implementation will grant access if one or more
  1607. <literal>ACCESS_GRANTED</literal> votes were received (ie a deny vote
  1608. will be ignored, provided there was at least one grant vote). Like the
  1609. <literal>ConsensusBased</literal> implementation, there is a parameter
  1610. that controls the behavior if all voters abstain. The
  1611. <literal>UnanimousBased</literal> provider expects unanimous
  1612. <literal>ACCESS_GRANTED</literal> votes in order to grant access,
  1613. ignoring abstains. It will deny access if there is any
  1614. <literal>ACCESS_DENIED</literal> vote. Like the other implementations,
  1615. there is a parameter that controls the behaviour if all voters
  1616. abstain.</para>
  1617. <para>It is possible to implement a custom
  1618. <literal>AccessDecisionManager</literal> that tallies votes
  1619. differently. For example, votes from a particular
  1620. <literal>AccessDecisionVoter</literal> might receive additional
  1621. weighting, whilst a deny vote from a particular voter may have a veto
  1622. effect.</para>
  1623. <para>There are two concrete <literal>AccessDecisionVoter</literal>
  1624. implementations provided with the Acegi Security System for Spring.
  1625. The <literal>RoleVoter</literal> class will vote if any
  1626. ConfigAttribute begins with <literal>ROLE_</literal>. It will vote to
  1627. grant access if there is a <literal>GrantedAuthority</literal> which
  1628. returns a <literal>String</literal> representation (via the
  1629. <literal>getAuthority()</literal> method) exactly equal to one or more
  1630. <literal>ConfigAttributes</literal> starting with
  1631. <literal>ROLE_</literal>. If there is no exact match of any
  1632. <literal>ConfigAttribute</literal> starting with
  1633. <literal>ROLE_</literal>, the <literal>RoleVoter</literal> will vote
  1634. to deny access. If no <literal>ConfigAttribute</literal> begins with
  1635. <literal>ROLE_</literal>, the voter will abstain.
  1636. <literal>RoleVoter</literal> is case sensitive on comparisons as well
  1637. as the <literal>ROLE_</literal> prefix.</para>
  1638. <para>BasicAclEntryVoter is the other concrete voter included with
  1639. Acegi Security. It integrates with Acegi Security's
  1640. <literal>AclManager</literal> (discussed later). This voter is
  1641. designed to have multiple instances in the same application context,
  1642. such as:</para>
  1643. <para><programlisting>&lt;bean id="aclContactReadVoter" class="net.sf.acegisecurity.vote.BasicAclEntryVoter"&gt;
  1644. &lt;property name="processConfigAttribute"&gt;&lt;value&gt;ACL_CONTACT_READ&lt;/value&gt;&lt;/property&gt;
  1645. &lt;property name="processDomainObjectClass"&gt;&lt;value&gt;sample.contact.Contact&lt;/value&gt;&lt;/property&gt;
  1646. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  1647. &lt;property name="requirePermission"&gt;
  1648. &lt;list&gt;
  1649. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  1650. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.READ"/&gt;
  1651. &lt;/list&gt;
  1652. &lt;/property&gt;
  1653. &lt;/bean&gt;
  1654. &lt;bean id="aclContactDeleteVoter" class="net.sf.acegisecurity.vote.BasicAclEntryVoter"&gt;
  1655. &lt;property name="processConfigAttribute"&gt;&lt;value&gt;ACL_CONTACT_DELETE&lt;/value&gt;&lt;/property&gt;
  1656. &lt;property name="processDomainObjectClass"&gt;&lt;value&gt;sample.contact.Contact&lt;/value&gt;&lt;/property&gt;
  1657. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  1658. &lt;property name="requirePermission"&gt;
  1659. &lt;list&gt;
  1660. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  1661. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.DELETE"/&gt;
  1662. &lt;/list&gt;
  1663. &lt;/property&gt;
  1664. &lt;/bean&gt;</programlisting></para>
  1665. <para>In the above example, you'd define
  1666. <literal>ACL_CONTACT_READ</literal> or
  1667. <literal>ACL_CONTACT_DELETE</literal> against some methods on a
  1668. <literal>MethodSecurityInterceptor</literal> or
  1669. <literal>AspectJSecurityInterceptor</literal>. When those methods are
  1670. invoked, the above applicable voter defined above would vote to grant
  1671. or deny access. The voter would look at the method invocation to
  1672. locate the first argument of type
  1673. <literal>sample.contact.Contact</literal>, and then pass that
  1674. <literal>Contact</literal> to the <literal>AclManager</literal>. The
  1675. <literal>AclManager</literal> will then return an access control list
  1676. (ACL) that applies to the current <literal>Authentication</literal>.
  1677. Assuming that ACL contains one of the listed
  1678. <literal>requirePermission</literal>s, the voter will vote to grant
  1679. access. If the ACL does not contain one of the permissions defined
  1680. against the voter, the voter will vote to deny access.
  1681. <literal>BasicAclEntryVoter</literal> is an important class as it
  1682. allows you to build truly complex applications with domain object
  1683. security entirely defined in the application context. If you're
  1684. interested in learning more about Acegi Security's ACL capabilities
  1685. and how best to apply them, please see the ACL and "After Invocation"
  1686. sections of this reference guide, and the Contacts sample
  1687. application.</para>
  1688. <para>It is also possible to implement a custom
  1689. <literal>AccessDecisionVoter</literal>. Several examples are provided
  1690. in the Acegi Security System for Spring unit tests, including
  1691. <literal>ContactSecurityVoter</literal> and
  1692. <literal>DenyVoter</literal>. The
  1693. <literal>ContactSecurityVoter</literal> abstains from voting decisions
  1694. where a <literal>CONTACT_OWNED_BY_CURRENT_USER</literal>
  1695. <literal>ConfigAttribute</literal> is not found. If voting, it queries
  1696. the <literal>MethodInvocation</literal> to extract the owner of the
  1697. <literal>Contact</literal> object that is subject of the method call.
  1698. It votes to grant access if the <literal>Contact</literal> owner
  1699. matches the principal presented in the
  1700. <literal>Authentication</literal> object. It could have just as easily
  1701. compared the <literal>Contact</literal> owner with some
  1702. <literal>GrantedAuthority</literal> the
  1703. <literal>Authentication</literal> object presented. All of this is
  1704. achieved with relatively few lines of code and demonstrates the
  1705. flexibility of the authorization model.</para>
  1706. </sect2>
  1707. <sect2 id="security-authorization-taglib">
  1708. <title>Authorization-Related Tag Libraries</title>
  1709. <para>The Acegi Security System for Spring comes bundled with several
  1710. JSP tag libraries that eases JSP writing. The tag libraries are known
  1711. as <literal>authz</literal> and provide a range of different
  1712. services.</para>
  1713. <para>All taglib classes are included in the core
  1714. <literal>acegi-security-xx.jar</literal> file, with the
  1715. <literal>authz.tld</literal> located in the JAR's
  1716. <literal>META-INF</literal> directory. This means for JSP 1.2+ web
  1717. containers you can simply include the JAR in the WAR's
  1718. <literal>WEB-INF/lib</literal> directory and it will be available. If
  1719. you're using a JSP 1.1 container, you'll need to declare the JSP
  1720. taglib in your <literal>web.xml file</literal>, and include
  1721. <literal>authz.tld</literal> in the <literal>WEB-INF/lib</literal>
  1722. directory. The following fragment is added to
  1723. <literal>web.xml</literal>:</para>
  1724. <para><programlisting>&lt;taglib&gt;
  1725. &lt;taglib-uri&gt;http://acegisecurity.sf.net/authz&lt;/taglib-uri&gt;
  1726. &lt;taglib-location&gt;/WEB-INF/authz.tld&lt;/taglib-location&gt;
  1727. &lt;/taglib&gt;</programlisting></para>
  1728. <sect3>
  1729. <title>AuthorizeTag</title>
  1730. <para><literal>AuthorizeTag</literal> is used to include content if
  1731. the current principal holds certain
  1732. <literal>GrantedAuthority</literal>s.</para>
  1733. <para>The following JSP fragment illustrates how to use the
  1734. <literal>AuthorizeTag</literal>:</para>
  1735. <para><programlisting>&lt;authz:authorize ifAllGranted="ROLE_SUPERVISOR"&gt;
  1736. &lt;td&gt;
  1737. &lt;A HREF="del.htm?id=&lt;c:out value="${contact.id}"/&gt;"&gt;Del&lt;/A&gt;
  1738. &lt;/td&gt;
  1739. &lt;/authz:authorize&gt;</programlisting></para>
  1740. <para>This tag would cause the tag's body to be output if the
  1741. principal has been granted ROLE_SUPERVISOR.</para>
  1742. <para>The <literal>authz:authorize</literal> tag declares the
  1743. following attributes:</para>
  1744. <para><itemizedlist spacing="compact">
  1745. <listitem>
  1746. <para><literal>ifAllGranted</literal>: All the listed roles
  1747. must be granted for the tag to output its body.</para>
  1748. </listitem>
  1749. <listitem>
  1750. <para><literal>ifAnyGranted</literal>: Any of the listed roles
  1751. must be granted for the tag to output its body.</para>
  1752. </listitem>
  1753. <listitem>
  1754. <para><literal>ifNotGranted</literal>: None of the listed
  1755. roles must be granted for the tag to output its body.</para>
  1756. </listitem>
  1757. </itemizedlist></para>
  1758. <para>You'll note that in each attribute you can list multiple
  1759. roles. Simply separate the roles using a comma. The
  1760. <literal>authorize</literal> tag ignores whitespace in
  1761. attributes.</para>
  1762. <para>The tag library logically ANDs all of it's parameters
  1763. together. This means that if you combine two or more attributes, all
  1764. attributes must be true for the tag to output it's body. Don't add
  1765. an <literal>ifAllGranted="ROLE_SUPERVISOR"</literal>, followed by an
  1766. <literal>ifNotGranted="ROLE_SUPERVISOR"</literal>, or you'll be
  1767. surprised to never see the tag's body.</para>
  1768. <para>By requiring all attributes to return true, the authorize tag
  1769. allows you to create more complex authorization scenarios. For
  1770. example, you could declare an
  1771. <literal>ifAllGranted="ROLE_SUPERVISOR"</literal> and an
  1772. <literal>ifNotGranted="ROLE_NEWBIE_SUPERVISOR"</literal> in the same
  1773. tag, in order to prevent new supervisors from seeing the tag body.
  1774. However it would no doubt be simpler to use
  1775. <literal>ifAllGranted="ROLE_EXPERIENCED_SUPERVISOR"</literal> rather
  1776. than inserting NOT conditions into your design.</para>
  1777. <para>One last item: the tag verifies the authorizations in a
  1778. specific order: first <literal>ifNotGranted</literal>, then
  1779. <literal>ifAllGranted</literal>, and finally,
  1780. <literal>ifAnyGranted</literal>.</para>
  1781. </sect3>
  1782. <sect3>
  1783. <title>AuthenticationTag</title>
  1784. <para><literal>AuthenticationTag</literal> is used to simply output
  1785. the current principal to the web page.</para>
  1786. <para>The following JSP fragment illustrates how to use the
  1787. <literal>AuthenticationTag</literal>:</para>
  1788. <para><programlisting>&lt;authz:authentication operation="principal"/&gt;</programlisting></para>
  1789. <para>This tag would cause the principal's name to be output. The
  1790. taglib properly supports the various types of principals that can
  1791. exist in the <literal>Authentication</literal> object, such as a
  1792. <literal>String</literal> or <literal>UserDetails</literal>
  1793. instance.</para>
  1794. <para>The "operation" attribute must always be "principal". This may
  1795. be expanded in the future, such as obtaining other
  1796. <literal>Authentication</literal>-related properties such as email
  1797. address or telephone numbers.</para>
  1798. </sect3>
  1799. <sect3>
  1800. <title>AclTag</title>
  1801. <para><literal>AclTag</literal> is used to include content if the
  1802. current principal has a ACL to the indicated domain object.</para>
  1803. <para>The following JSP fragment illustrates how to use the
  1804. <literal>AclTag</literal>:</para>
  1805. <para><programlisting>&lt;authz:acl domainObject="${contact}" hasPermission="16,1"&gt;
  1806. &lt;td&gt;&lt;A HREF="&lt;c:url value="del.htm"&gt;&lt;c:param name="contactId" value="${contact.id}"/&gt;&lt;/c:url&gt;"&gt;Del&lt;/A&gt;&lt;/td&gt;
  1807. &lt;/authz:acl&gt;</programlisting></para>
  1808. <para>This tag would cause the tag's body to be output if the
  1809. principal holds either permission 16 or permission 1 for the
  1810. "contact" domain object. The numbers are actually integers that are
  1811. used with <literal>AbstractBasicAclEntry</literal> bit masking.
  1812. Please refer tro the ACL section of this reference guide to
  1813. understand more about the ACL capabilities of Acegi Security.</para>
  1814. </sect3>
  1815. </sect2>
  1816. <sect2 id="security-authorization-recommendations">
  1817. <title>Authorization Recommendations</title>
  1818. <para>Given there are several ways to achieve similar authorization
  1819. outcomes in the Acegi Security System for Spring, the following
  1820. general recommendations are made:</para>
  1821. <itemizedlist>
  1822. <listitem>
  1823. <para>Grant authorities using
  1824. <literal>GrantedAuthorityImpl</literal> where possible. Because it
  1825. is already supported by the Acegi Security System for Spring, you
  1826. avoid the need to create custom
  1827. <literal>AuthenticationManager</literal> or
  1828. <literal>AuthenticationProvider</literal> implementations simply
  1829. to populate the <literal>Authentication</literal> object with a
  1830. custom <literal>GrantedAuthority</literal>.</para>
  1831. </listitem>
  1832. <listitem>
  1833. <para>Writing an <literal>AccessDecisionVoter</literal>
  1834. implementation and using either <literal>ConsensusBased</literal>,
  1835. <literal>AffirmativeBased</literal> or
  1836. <literal>UnanimousBased</literal> as the
  1837. <literal>AccessDecisionManager</literal> may be the best approach
  1838. to implementing your custom access decision rules.</para>
  1839. </listitem>
  1840. </itemizedlist>
  1841. </sect2>
  1842. </sect1>
  1843. <sect1 id="afterinvocation">
  1844. <title>After Invocation Handling</title>
  1845. <sect2 id="afterinvocation-overview">
  1846. <title>Overview</title>
  1847. <para>Whilst the <literal>AccessDecisionManager</literal> is called by
  1848. the <literal>AbstractSecurityInterceptor</literal> before proceeding
  1849. with the secure object invocation, some applications need a way of
  1850. modifying the object actually returned by the secure object
  1851. invocation. Whilst you could easily implement your own AOP concern to
  1852. achieve this, Acegi Security provides a convenient hook that has
  1853. several concrete implementations that integrate with its ACL
  1854. capabilities.</para>
  1855. <para>Figure 5 illustrates Acegi Security's
  1856. <literal>AfterInvocationManager</literal> and its concrete
  1857. implementations.</para>
  1858. <para><mediaobject>
  1859. <imageobject role="html">
  1860. <imagedata align="center" fileref="images/AfterInvocation.gif"
  1861. format="GIF" />
  1862. </imageobject>
  1863. <caption>
  1864. <para>Figure 5: After Invocation Implementation</para>
  1865. </caption>
  1866. </mediaobject></para>
  1867. <para>Like many other parts of Acegi Security,
  1868. <literal>AfterInvocationManager</literal> has a single concrete
  1869. implementation, <literal>AfterInvocationProvider</literal>, which
  1870. polls a list of <literal>AfterInvocationProvider</literal>s. Each
  1871. <literal>AfterInvocationProvider</literal> is allowed to modify the
  1872. return object or throw an <literal>AccessDeniedException</literal>.
  1873. Indeed multiple providers can modify the object, as the result of the
  1874. previous provider is passed to the next in the list. Let's now
  1875. consider our ACL-aware implementations of
  1876. <literal>AfterInvocationProvider</literal>.</para>
  1877. <para>Please be aware that if you're using
  1878. <literal>AfterInvocationManager</literal>, you will still need
  1879. configuration attributes that allow the
  1880. <literal>MethodSecurityInterceptor</literal>'s
  1881. <literal>AccessDecisionManager</literal> to allow an operation. If
  1882. you're using the typical Acegi Security included
  1883. <literal>AccessDecisionManager</literal> implementations, having no
  1884. configuration attributes defined for a particular secure method
  1885. invocation will cause each <literal>AccessDecisionVoter</literal> to
  1886. abstain from voting. In turn, if the
  1887. <literal>AccessDecisionManager</literal> property
  1888. "<literal>allowIfAllAbstainDecisions</literal>" is
  1889. <literal>false</literal>, an <literal>AccessDeniedException</literal>
  1890. will be thrown. You may avoid this potential issue by either (i)
  1891. setting "<literal>allowIfAllAbstainDecisions</literal>" to
  1892. <literal>true</literal> (although this is generally not recommended)
  1893. or (ii) simply ensure that there is at least one configuration
  1894. attribute that an <literal>AccessDecisionVoter</literal> will vote to
  1895. grant access for. This latter (recommended) approach is usually
  1896. achieved through a <literal>ROLE_USER</literal> or
  1897. <literal>ROLE_AUTHENTICATED</literal> configuration attribute.</para>
  1898. </sect2>
  1899. <sect2 id="afterinvocation-acl-aware">
  1900. <title>ACL-Aware AfterInvocationProviders</title>
  1901. <para>A common services layer method we've all written at one stage or
  1902. another looks like this:</para>
  1903. <para><programlisting>public Contact getById(Integer id);</programlisting></para>
  1904. <para>Quite often, only principals with permission to read the
  1905. <literal>Contact</literal> should be allowed to obtain it. In this
  1906. situation the <literal>AccessDecisionManager</literal> approach
  1907. provided by the <literal>AbstractSecurityInterceptor</literal> will
  1908. not suffice. This is because the identity of the
  1909. <literal>Contact</literal> is all that is available before the secure
  1910. object is invoked. The
  1911. <literal>BasicAclAfterInvocationProvider</literal> delivers a
  1912. solution, and is configured as follows:</para>
  1913. <para><programlisting>&lt;bean id="afterAclRead" class="net.sf.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationProvider"&gt;
  1914. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  1915. &lt;property name="requirePermission"&gt;
  1916. &lt;list&gt;
  1917. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  1918. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.READ"/&gt;
  1919. &lt;/list&gt;
  1920. &lt;/property&gt;
  1921. &lt;/bean&gt;</programlisting></para>
  1922. <para>In the above example, the <literal>Contact</literal> will be
  1923. retrieved and passed to the
  1924. <literal>BasicAclEntryAfterInvocationProvider</literal>. The provider
  1925. will thrown an <literal>AccessDeniedException</literal> if one of the
  1926. listed <literal>requirePermission</literal>s is not held by the
  1927. <literal>Authentication</literal>. The
  1928. <literal>BasicAclEntryAfterInvocationProvider</literal> queries the
  1929. <literal>AclManager</literal> to determine the ACL that applies for
  1930. this domain object to this <literal>Authentication</literal>.</para>
  1931. <para>Similar to the
  1932. <literal>BasicAclEntryAfterInvocationProvider</literal> is
  1933. <literal>BasicAclEntryAfterInvocationCollectionFilteringProvider</literal>.
  1934. It is designed to remove <literal>Collection</literal> or array
  1935. elements for which a principal does not have access. It never thrown
  1936. an <literal>AccessDeniedException</literal> - simply silently removes
  1937. the offending elements. The provider is configured as follows:</para>
  1938. <para><programlisting>&lt;bean id="afterAclCollectionRead" class="net.sf.acegisecurity.afterinvocation.BasicAclEntryAfterInvocationCollectionFilteringProvider"&gt;
  1939. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  1940. &lt;property name="requirePermission"&gt;
  1941. &lt;list&gt;
  1942. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  1943. &lt;ref local="net.sf.acegisecurity.acl.basic.SimpleAclEntry.READ"/&gt;
  1944. &lt;/list&gt;
  1945. &lt;/property&gt;
  1946. &lt;/bean&gt;</programlisting></para>
  1947. <para>As you can imagine, the returned <literal>Object</literal> must
  1948. be a <literal>Collection</literal> or array for this provider to
  1949. operate. It will remove any element if the
  1950. <literal>AclManager</literal> indicates the
  1951. <literal>Authentication</literal> does not hold one of the listed
  1952. <literal>requirePermission</literal>s.</para>
  1953. <para>The Contacts sample application demonstrates these two
  1954. <literal>AfterInvocationProvider</literal>s.</para>
  1955. </sect2>
  1956. </sect1>
  1957. <sect1 id="security-run-as">
  1958. <title>Run-As Authentication Replacement</title>
  1959. <sect2 id="security-run-as-purpose">
  1960. <title>Purpose</title>
  1961. <para>The <literal>AbstractSecurityInterceptor</literal> is able to
  1962. temporarily replace the <literal>Authentication</literal> object in
  1963. the <literal>SecureContext</literal> and
  1964. <literal>ContextHolder</literal> during the
  1965. <literal>SecurityInterceptorCallback</literal>. This only occurs if
  1966. the original <literal>Authentication</literal> object was successfully
  1967. processed by the <literal>AuthenticationManager</literal> and
  1968. <literal>AccessDecisionManager</literal>. The
  1969. <literal>RunAsManager</literal> will indicate the replacement
  1970. <literal>Authentication</literal> object, if any, that should be used
  1971. during the <literal>SecurityInterceptorCallback</literal>.</para>
  1972. <para>By temporarily replacing the <literal>Authentication</literal>
  1973. object during a <literal>SecurityInterceptorCallback</literal>, the
  1974. secured invocation will be able to call other objects which require
  1975. different authentication and authorization credentials. It will also
  1976. be able to perform any internal security checks for specific
  1977. <literal>GrantedAuthority</literal> objects. Because Acegi Security
  1978. provides a number of helper classes that automatically configure
  1979. remoting protocols based on the contents of the
  1980. <literal>ContextHolder</literal>, these run-as replacements are
  1981. particularly useful when calling remote web services.</para>
  1982. </sect2>
  1983. <sect2 id="security-run-as-usage">
  1984. <title>Usage</title>
  1985. <para>A <literal>RunAsManager</literal> interface is provided by the
  1986. Acegi Security System for Spring:</para>
  1987. <para><programlisting>public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config);
  1988. public boolean supports(ConfigAttribute attribute);
  1989. public boolean supports(Class clazz);</programlisting></para>
  1990. <para>The first method returns the <literal>Authentication</literal>
  1991. object that should replace the existing
  1992. <literal>Authentication</literal> object for the duration of the
  1993. method invocation. If the method returns <literal>null</literal>, it
  1994. indicates no replacement should be made. The second method is used by
  1995. the <literal>AbstractSecurityInterceptor</literal> as part of its
  1996. startup validation of configuration attributes. The
  1997. <literal>supports(Class)</literal> method is called by a security
  1998. interceptor implementation to ensure the configured
  1999. <literal>RunAsManager</literal> supports the type of secure object
  2000. that the security interceptor will present.</para>
  2001. <para>One concrete implementation of a <literal>RunAsManager</literal>
  2002. is provided with the Acegi Security System for Spring. The
  2003. <literal>RunAsManagerImpl</literal> class returns a replacement
  2004. <literal>RunAsUserToken</literal> if any
  2005. <literal>ConfigAttribute</literal> starts with
  2006. <literal>RUN_AS_</literal>. If any such
  2007. <literal>ConfigAttribute</literal> is found, the replacement
  2008. <literal>RunAsUserToken</literal> will contain the same principal,
  2009. credentials and granted authorities as the original
  2010. <literal>Authentication</literal> object, along with a new
  2011. <literal>GrantedAuthorityImpl</literal> for each
  2012. <literal>RUN_AS_</literal> <literal>ConfigAttribute</literal>. Each
  2013. new <literal>GrantedAuthorityImpl</literal> will be prefixed with
  2014. <literal>ROLE_</literal>, followed by the <literal>RUN_AS</literal>
  2015. <literal>ConfigAttribute</literal>. For example, a
  2016. <literal>RUN_AS_SERVER</literal> will result in the replacement
  2017. <literal>RunAsUserToken</literal> containing a
  2018. <literal>ROLE_RUN_AS_SERVER</literal> granted authority.</para>
  2019. <para>The replacement <literal>RunAsUserToken</literal> is just like
  2020. any other <literal>Authentication</literal> object. It needs to be
  2021. authenticated by the <literal>AuthenticationManager</literal>,
  2022. probably via delegation to a suitable
  2023. <literal>AuthenticationProvider</literal>. The
  2024. <literal>RunAsImplAuthenticationProvider</literal> performs such
  2025. authentication. It simply accepts as valid any
  2026. <literal>RunAsUserToken</literal> presented.</para>
  2027. <para>To ensure malicious code does not create a
  2028. <literal>RunAsUserToken</literal> and present it for guaranteed
  2029. acceptance by the <literal>RunAsImplAuthenticationProvider</literal>,
  2030. the hash of a key is stored in all generated tokens. The
  2031. <literal>RunAsManagerImpl</literal> and
  2032. <literal>RunAsImplAuthenticationProvider</literal> is created in the
  2033. bean context with the same key:</para>
  2034. <para><programlisting>&lt;bean id="runAsManager" class="net.sf.acegisecurity.runas.RunAsManagerImpl"&gt;
  2035. &lt;property name="key"&gt;&lt;value&gt;my_run_as_password&lt;/value&gt;&lt;/property&gt;
  2036. &lt;/bean&gt;</programlisting><programlisting>&lt;bean id="runAsAuthenticationProvider" class="net.sf.acegisecurity.runas.RunAsImplAuthenticationProvider"&gt;
  2037. &lt;property name="key"&gt;&lt;value&gt;my_run_as_password&lt;/value&gt;&lt;/property&gt;
  2038. &lt;/bean&gt;</programlisting></para>
  2039. <para>By using the same key, each <literal>RunAsUserToken</literal>
  2040. can be validated it was created by an approved
  2041. <literal>RunAsManagerImpl</literal>. The
  2042. <literal>RunAsUserToken</literal> is immutable after creation for
  2043. security reasons.</para>
  2044. </sect2>
  2045. </sect1>
  2046. <sect1 id="security-ui">
  2047. <title>User Interfacing with the ContextHolder</title>
  2048. <sect2 id="security-ui-purpose">
  2049. <title>Purpose</title>
  2050. <para>Everything presented so far assumes one thing: the
  2051. <literal>ContextHolder</literal> is populated with a valid
  2052. <literal>SecureContext</literal>, which in turn contains a valid
  2053. <literal>Authentication</literal> object. Developers are free to do
  2054. this in whichever way they like, such as directly calling the relevant
  2055. objects at runtime. However, several classes have been provided to
  2056. make this process transparent in many situations. We call these
  2057. classes "authentication mechanisms".</para>
  2058. <para>The <literal>net.sf.acegisecurity.ui</literal> package provides
  2059. what we call "authentication processing mechanisms". An authentication
  2060. processing mechanism is solely concerned with received an
  2061. authentication request from the principal, testing if it seems valid,
  2062. and if so, placing the authentication request token onto the
  2063. ContextHolder. Of course, if the authentication request is invalid,
  2064. the authentication processing mechanism is responsible for informing
  2065. the principal in whatever way is appropriate to the protocol.</para>
  2066. <para>Recall the HttpSessionContextIntegrationFilter (discussed in the
  2067. context section) is responsible for storing the ContextHolder contents
  2068. between invocations. This means no authentication processing mechanism
  2069. need ever interact directly with HttpSession. Indeed
  2070. HttpSessionContextIntegrationFilter has been designed to minimise the
  2071. unnecessary creation of HttpSessions, as might occur when using Basic
  2072. authentication for example.</para>
  2073. <para>There are several authentication processing mechanisms included
  2074. with Acegi Security, which will be briefly discussed in this chapter.
  2075. The most popular (and almost always recommended) approach is HTTP Form
  2076. Authentication, which uses a login form to authenticate the user.
  2077. Another approach (commonly use with web services) is HTTP Basic
  2078. Authentication, which allows clients to use HTTP headers to present
  2079. authentication information to the Acegi Security System for Spring.
  2080. Alternatively, you can also use Yale Central Authentication Service
  2081. (CAS) for enterprise-wide single sign on. The final (and generally
  2082. unrecommended) approach is via Container Adapters, which allow
  2083. supported web containers to perform the authentication themselves.
  2084. HTTP Form Authentication and Basic Authentication is discussed below,
  2085. whilst CAS and Container Adapters are discussed in separate sections
  2086. of this document.</para>
  2087. </sect2>
  2088. <sect2 id="security-ui-http-form">
  2089. <title>HTTP Form Authentication</title>
  2090. <para>HTTP Form Authentication involves using the
  2091. <literal>AuthenticationProcessingFilter</literal> to process a login
  2092. form. The login form simply contains <literal>j_username</literal> and
  2093. <literal>j_password</literal> input fields, and posts to a URL that is
  2094. monitored by the filter (by default
  2095. <literal>j_acegi_security_check</literal>). The filter is defined in
  2096. <literal>web.xml</literal> behind a
  2097. <literal>FilterToBeanProxy</literal> as follows:</para>
  2098. <para><programlisting>&lt;filter&gt;
  2099. &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt;
  2100. &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
  2101. &lt;init-param&gt;
  2102. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  2103. &lt;param-value&gt;net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter&lt;/param-value&gt;
  2104. &lt;/init-param&gt;
  2105. &lt;/filter&gt;
  2106. &lt;filter-mapping&gt;
  2107. &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt;
  2108. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  2109. &lt;/filter-mapping&gt;</programlisting></para>
  2110. <para>For a discussion of <literal>FilterToBeanProxy</literal>, please
  2111. refer to the Filters section. The application context will need to
  2112. define the <literal>AuthenticationProcessingFilter</literal>:</para>
  2113. <para><programlisting>&lt;bean id="authenticationProcessingFilter" class="net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter"&gt;
  2114. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  2115. &lt;property name="authenticationFailureUrl"&gt;&lt;value&gt;/acegilogin.jsp?login_error=1&lt;/value&gt;&lt;/property&gt;
  2116. &lt;property name="defaultTargetUrl"&gt;&lt;value&gt;/&lt;/value&gt;&lt;/property&gt;
  2117. &lt;property name="filterProcessesUrl"&gt;&lt;value&gt;/j_acegi_security_check&lt;/value&gt;&lt;/property&gt;
  2118. &lt;/bean&gt;</programlisting></para>
  2119. <para>The configured <literal>AuthenticationManager</literal>
  2120. processes each authentication request. If authentication fails, the
  2121. browser will be redirected to the
  2122. <literal>authenticationFailureUrl</literal>. The
  2123. <literal>AuthenticationException</literal> will be placed into the
  2124. <literal>HttpSession</literal> attribute indicated by
  2125. <literal>AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY</literal>,
  2126. enabling a reason to be provided to the user on the error page.</para>
  2127. <para>If authentication is successful, the resulting
  2128. <literal>Authentication</literal> object will be placed into the
  2129. <literal>ContextHolder</literal>.</para>
  2130. <para>Once the <literal>ContextHolder</literal> has been updated, the
  2131. browser will need to be redirected to the target URL. The target URL
  2132. is usually indicated by the <literal>HttpSession</literal> attribute
  2133. specified by
  2134. <literal>AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY</literal>.
  2135. This attribute is automatically set by the
  2136. <literal>SecurityEnforcementFilter</literal> when an
  2137. <literal>AuthenticationException</literal> occurs, so that after login
  2138. is completed the user can return to what they were trying to access.
  2139. If for some reason the <literal>HttpSession</literal> does not
  2140. indicate the target URL, the browser will be redirected to the
  2141. <literal>defaultTargetUrl</literal> property.</para>
  2142. <para>Because this authentication approach is fully contained within a
  2143. single web application, HTTP Form Authentication is recommended to be
  2144. used instead of Container Adapters.</para>
  2145. </sect2>
  2146. <sect2 id="security-ui-http-basic">
  2147. <title>HTTP Basic Authentication</title>
  2148. <para>The Acegi Security System for Spring provides a
  2149. <literal>BasicProcessingFilter</literal> which is capable of
  2150. processing basic authentication credentials presented in HTTP headers.
  2151. This can be used for authenticating calls made by Spring remoting
  2152. protocols (such as Hessian and Burlap), as well as normal user agents
  2153. (such as Internet Explorer and Navigator). The standard governing HTTP
  2154. Basic Authentication is defined by RFC 1945, Section 11, and the
  2155. <literal>BasicProcessingFilter</literal> conforms with this RFC. Basic
  2156. Authentication is an attractive approach to authentication, because it
  2157. is very widely deployed in user agents and implementation is extremely
  2158. simple (it's just a Base64 encoding of the username:password,
  2159. specified in a HTTP header).</para>
  2160. <para>To implement HTTP Basic Authentication, it is necessary to
  2161. define <literal>BasicProcessingFilter</literal> in the fitler chain.
  2162. The application context will need to define the
  2163. <literal>BasicProcessingFilter</literal> and its required
  2164. collaborator:</para>
  2165. <para><programlisting>&lt;bean id="basicProcessingFilter" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilter"&gt;
  2166. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  2167. &lt;property name="authenticationEntryPoint"&gt;&lt;ref bean="authenticationEntryPoint"/&gt;&lt;/property&gt;
  2168. &lt;/bean&gt;
  2169. &lt;bean id="authenticationEntryPoint" class="net.sf.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint"&gt;
  2170. &lt;property name="realmName"&gt;&lt;value&gt;Name Of Your Realm&lt;/value&gt;&lt;/property&gt;
  2171. &lt;/bean&gt;</programlisting></para>
  2172. <para>The configured <literal>AuthenticationManager</literal>
  2173. processes each authentication request. If authentication fails, the
  2174. configured <literal>AuthenticationEntryPoint</literal> will be used to
  2175. retry the authentication process. Usually you will use the
  2176. <literal>BasicProcessingFilterEntryPoint</literal>, which returns a
  2177. 401 response with a suitable header to retry HTTP Basic
  2178. authentication. If authentication is successful, the resulting
  2179. <literal>Authentication</literal> object will be placed into the
  2180. <literal>ContextHolder</literal>.</para>
  2181. <para>If the authentication event was successful, or authentication
  2182. was not attempted because the HTTP header did not contain a supported
  2183. authentication request, the filter chain will continue as normal. The
  2184. only time the filter chain will be interrupted is if authentication
  2185. fails and the <literal>AuthenticationEntryPoint</literal> is called,
  2186. as discussed in the previous paragraph.</para>
  2187. </sect2>
  2188. <sect2 id="security-ui-http-digest">
  2189. <title>HTTP Digest Authentication</title>
  2190. <para>The Acegi Security System for Spring provides a
  2191. <literal>DigestProcessingFilter</literal> which is capable of
  2192. processing digest authentication credentials presented in HTTP
  2193. headers. Digest Authentication attempts to solve many of the
  2194. weakenesses of Basic authentication, specifically by ensuring
  2195. credentials are never sent in clear text across the wire. Many user
  2196. agents support Digest Authentication, including FireFox and Internet
  2197. Explorer. The standard governing HTTP Digest Authentication is defined
  2198. by RFC 2617, which updates an earlier version of the Digest
  2199. Authentication standard prescribed by RFC 2069. Most user agents
  2200. implement RFC 2617. The Acegi Security
  2201. <literal>DigestProcessingFilter</literal> is compatible with the
  2202. "<literal>auth</literal>" quality of protection
  2203. (<literal>qop</literal>) prescribed by RFC 2617, which also provides
  2204. backward compatibility with RFC 2069. Digest Authentication is a
  2205. highly attractive option if you need to use unencrypted HTTP (ie no
  2206. TLS/HTTPS) and wish to maximise security of the authentication
  2207. process. Indeed Digest Authentication is a mandatory requirement for
  2208. the WebDAV protocol, as noted by RFC 2518 Section 17.1, so we should
  2209. expect to see it increasingly deployed and replacing Basic
  2210. Authentication.</para>
  2211. <para>Digest Authentication is definitely the most secure choice
  2212. between Form Authentication, Basic Authentication and Digest
  2213. Authentication, although extra security also means more complex user
  2214. agent implementations. Central to Digest Authentication is a "nonce".
  2215. This is a value the server generates. Acegi Security's nonce adopts
  2216. the following format:</para>
  2217. <para><programlisting>base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
  2218. expirationTime: The date and time when the nonce expires, expressed in milliseconds
  2219. key: A private key to prevent modification of the nonce token
  2220. </programlisting></para>
  2221. <para>The <literal>DigestProcessingFilterEntryPoint</literal> has a
  2222. property specifying the <literal>key</literal> used for generating the
  2223. nonce tokens, along with a <literal>nonceValiditySeconds</literal>
  2224. property for determining the expiration time (default 300, which
  2225. equals five minutes). Whilstever the nonce is valid, the digest is
  2226. computed by concatenating various strings including the username,
  2227. password, nonce, URI being requested, a client-generated nonce (merely
  2228. a random value which the user agent generates each request), the realm
  2229. name etc, then performing an MD5 hash. Both the server and user agent
  2230. perform this digest computation, resulting in different hash codes if
  2231. they disagree on an included value (eg password). In the Acegi
  2232. Security implementation, if the server-generated nonce has merely
  2233. expired (but the digest was otherwise valid), the
  2234. <literal>DigestProcessingFilterEntryPoint</literal> will send a
  2235. <literal>"stale=true"</literal> header. This tells the user agent
  2236. there is no need to disturb the user (as the password and username etc
  2237. is correct), but simply to try again using a new nonce.</para>
  2238. <para>An appropriate value for
  2239. <literal>DigestProcessingFilterEntryPoint</literal>'s
  2240. <literal>nonceValiditySeconds</literal> parameter will depend on your
  2241. application. Extremely secure applications should note that an
  2242. intercepted authentication header can be used to impersonate the
  2243. principal until the <literal>expirationTime</literal> contained in the
  2244. nonce is reached. This is the key principle when selecting an
  2245. appropriate setting, but it would be unusual for immensly secure
  2246. applications to not be running over TLS/HTTPS in the first
  2247. instance.</para>
  2248. <para>Because of the more complex implementation of Digest
  2249. Authentication, there are often user agent issues. For example,
  2250. Internet Explorer fails to present an "<literal>opaque</literal>"
  2251. token on subsequent requests in the same session. The Acegi Security
  2252. filters therefore encapsulate all state information into the
  2253. "<literal>nonce</literal>" token instead. In our testing, the Acegi
  2254. Security implementation works reliably with FireFox and Internet
  2255. Explorer, correctly handling nonce timeouts etc.</para>
  2256. <para>Now that we've reviewed the theory, let's see how to use it. To
  2257. implement HTTP Digest Authentication, it is necessary to define
  2258. <literal>DigestProcessingFilter</literal> in the fitler chain. The
  2259. application context will need to define the
  2260. <literal>DigestProcessingFilter</literal> and its required
  2261. collaborators:</para>
  2262. <para><programlisting>&lt;bean id="digestProcessingFilter" class="net.sf.acegisecurity.ui.digestauth.DigestProcessingFilter"&gt;
  2263. &lt;property name="authenticationDao"&gt;&lt;ref local="jdbcDaoImpl"/&gt;&lt;/property&gt;
  2264. &lt;property name="authenticationEntryPoint"&gt;&lt;ref local="digestProcessingFilterEntryPoint"/&gt;&lt;/property&gt;
  2265. &lt;property name="userCache"&gt;&lt;ref local="userCache"/&gt;&lt;/property&gt;
  2266. &lt;/bean&gt;
  2267. &lt;bean id="digestProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.digestauth.DigestProcessingFilterEntryPoint"&gt;
  2268. &lt;property name="realmName"&gt;&lt;value&gt;Contacts Realm via Digest Authentication&lt;/value&gt;&lt;/property&gt;
  2269. &lt;property name="key"&gt;&lt;value&gt;acegi&lt;/value&gt;&lt;/property&gt;
  2270. &lt;property name="nonceValiditySeconds"&gt;&lt;value&gt;10&lt;/value&gt;&lt;/property&gt;
  2271. &lt;/bean&gt;</programlisting></para>
  2272. <para>The configured <literal>AuthenticationDao</literal> is needed
  2273. because <literal>DigestProcessingFilter</literal> must have direct
  2274. access to the clear text password of a user. Digest Authentication
  2275. will NOT work if you are using encoded passwords in your DAO. The DAO
  2276. collaborator, along with the <literal>UserCache</literal>, are
  2277. typically shared directly with a
  2278. <literal>DaoAuthenticationProvider</literal>. The
  2279. <literal>authenticationEntryPoint</literal> property must be
  2280. <literal>DigestProcessingFilterEntryPoint</literal>, so that
  2281. <literal>DigestProcessingFilter</literal> can obtain the correct
  2282. <literal>realmName</literal> and <literal>key</literal> for digest
  2283. calculations.</para>
  2284. <para>Like <literal>BasicAuthenticationFilter</literal>, if
  2285. authentication is successful an <literal>Authentication</literal>
  2286. request token will be placed into the
  2287. <literal>ContextHolder</literal>. If the authentication event was
  2288. successful, or authentication was not attempted because the HTTP
  2289. header did not contain a Digest Authentication request, the filter
  2290. chain will continue as normal. The only time the filter chain will be
  2291. interrupted is if authentication fails and the
  2292. <literal>AuthenticationEntryPoint</literal> is called, as discussed in
  2293. the previous paragraph.</para>
  2294. <para>Digest Authentication's RFC offers a range of additional
  2295. features to further increase security. For example, the nonce can be
  2296. changed on every request. Despite this, the Acegi Security
  2297. implementation was designed to minimise the complexity of the
  2298. implementation (and the doubtless user agent incompatibilities that
  2299. would emerge), and avoid needing to store server-side state. You are
  2300. invited to review RFC 2617 if you wish to explore these features in
  2301. more detail. As far as we are aware, the Acegi Security implementation
  2302. does comply with the minimum standards of this RFC.</para>
  2303. </sect2>
  2304. <sect2 id="security-ui-anonymous">
  2305. <title>Anonymous Authentication</title>
  2306. <para>Particularly in the case of web request URI security, sometimes
  2307. it is more convenient to assign configuration attributes against every
  2308. possible secure object invocation. Put differently, sometimes it is
  2309. nice to say <literal>ROLE_SOMETHING</literal> is required by default
  2310. and only allow certain exceptions to this rule, such as for login,
  2311. logout and home pages of an application. There are also other
  2312. situations where anonymous authentication would be desired, such as
  2313. when an auditing interceptor queries the
  2314. <literal>ContextHolder</literal> to identify which principal was
  2315. responsible for a given operation. Such classes can be authored with
  2316. more robustness if they know the <literal>ContextHolder</literal>
  2317. always contains an <literal>Authentication</literal> object, and never
  2318. <literal>null</literal>.</para>
  2319. <para>Acegi Security provides three classes that together provide an
  2320. anoymous authentication feature.
  2321. <literal>AnonymousAuthenticationToken</literal> is an implementation
  2322. of <literal>Authentication</literal>, and stores the
  2323. <literal>GrantedAuthority</literal>[]s which apply to the anonymous
  2324. principal. There is a corresponding
  2325. <literal>AnonymousAuthenticationProvider</literal>, which is chained
  2326. into the <literal>ProviderManager</literal> so that
  2327. <literal>AnonymousAuthenticationTokens</literal> are accepted.
  2328. Finally, there is an AnonymousProcessingFilter, which is chained after
  2329. the normal authentication mechanisms and automatically add an
  2330. <literal>AnonymousAuthenticationToken</literal> to the
  2331. <literal>ContextHolder</literal> if there is no existing
  2332. <literal>Authentication</literal> held there. The definition of the
  2333. filter and authentication provider appears as follows:</para>
  2334. <para><programlisting>&lt;bean id="anonymousProcessingFilter" class="net.sf.acegisecurity.providers.anonymous.AnonymousProcessingFilter"&gt;
  2335. &lt;property name="key"&gt;&lt;value&gt;foobar&lt;/value&gt;&lt;/property&gt;
  2336. &lt;property name="userAttribute"&gt;&lt;value&gt;anonymousUser,ROLE_ANONYMOUS&lt;/value&gt;&lt;/property&gt;
  2337. &lt;/bean&gt;
  2338. &lt;bean id="anonymousAuthenticationProvider" class="net.sf.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider"&gt;
  2339. &lt;property name="key"&gt;&lt;value&gt;foobar&lt;/value&gt;&lt;/property&gt;
  2340. &lt;/bean&gt;</programlisting></para>
  2341. <para>The <literal>key</literal> is shared between the filter and
  2342. authentication provider, so that tokens created by the former are
  2343. accepted by the latter. The <literal>userAttribute</literal> is
  2344. expressed in the form of
  2345. <literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>.
  2346. This is the same syntax as used after the equals sign for
  2347. <literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal>
  2348. property.</para>
  2349. <para>As explained earlier, the benefit of anonymous authentication is
  2350. that all URI patterns can have security applied to them. For
  2351. example:</para>
  2352. <para><programlisting>&lt;bean id="filterInvocationInterceptor" class="net.sf.acegisecurity.intercept.web.FilterSecurityInterceptor"&gt;
  2353. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  2354. &lt;property name="accessDecisionManager"&gt;&lt;ref local="httpRequestAccessDecisionManager"/&gt;&lt;/property&gt;
  2355. &lt;property name="objectDefinitionSource"&gt;
  2356. &lt;value&gt;
  2357. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  2358. PATTERN_TYPE_APACHE_ANT
  2359. /index.jsp=ROLE_ANONYMOUS,ROLE_USER
  2360. /hello.htm=ROLE_ANONYMOUS,ROLE_USER
  2361. /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER
  2362. /acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER
  2363. /**=ROLE_USER
  2364. &lt;/value&gt;
  2365. &lt;/property&gt;
  2366. &lt;/bean&gt;</programlisting>Rounding out the anonymous authentication
  2367. discussion is the <literal>AuthenticationTrustResolver</literal>
  2368. interface, with its corresponding
  2369. <literal>AuthenticationTrustResolverImpl</literal> implementation.
  2370. This interface provides an
  2371. <literal>isAnonymous(Authentication)</literal> method, which allows
  2372. interested classes to take into account this special type of
  2373. authentication status. The
  2374. <literal>SecurityEnforcementFilter</literal> uses this interface in
  2375. processing <literal>AccessDeniedException</literal>s. If an
  2376. <literal>AccessDeniedException</literal> is thrown, and the
  2377. authentication is of an anonymous type, instead of throwing a 403
  2378. (forbidden) response, the filter will instead commence the
  2379. <literal>AuthenticationEntryPoint</literal> so the principal can
  2380. authenticate properly. This is a necessary distinction, otherwise
  2381. principals would always be deemed "authenticated" and never be given
  2382. an opportunity to login via form, basic, digest or some other normal
  2383. authentication mechanism.</para>
  2384. </sect2>
  2385. <sect2 id="security-ui-remember-me">
  2386. <title>Remember-Me Authentication</title>
  2387. <para>Remember-me authentication refers to web sites being able to
  2388. remember the identity of a principal between sessions. This is
  2389. typically accomplished by sending a cookie to the browser, with the
  2390. cookie being detected during future sessions and causing automated
  2391. login to take place. Acegi Security provides the necessary hooks so
  2392. that such operations can take place, along with providing a concrete
  2393. implementation that uses hashing to preserve the security of
  2394. cookie-based tokens.</para>
  2395. <para>Remember-me authentication is not used with digest or basic
  2396. authentication, given they are often not used with
  2397. <literal>HttpSession</literal>s. Remember-me is used with
  2398. <literal>AuthenticationProcessingFilter</literal>, and is implemented
  2399. via hooks in the <literal>AbstractProcessingFilter</literal>
  2400. superclass. The hooks will invoke a concrete
  2401. <literal>RememberMeServices</literal> at the appropriate times. The
  2402. interface looks like this:</para>
  2403. <para><programlisting>public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
  2404. public void loginFail(HttpServletRequest request, HttpServletResponse response);
  2405. public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication);</programlisting></para>
  2406. <para>Please refer to JavaDocs for a fuller discussion on what the
  2407. methods do, although note at this stage
  2408. <literal>AbstractProcessingFilter</literal> only calls the
  2409. <literal>loginFail()</literal> and <literal>loginSuccess()</literal>
  2410. methods. The <literal>autoLogin()</literal> method is called by
  2411. <literal>RememberMeProcessingFilter</literal> whenever the
  2412. <literal>ContextHolder</literal> does not contain an
  2413. <literal>Authentication</literal>. This interface therefore provides
  2414. the underlaying remember-me implementation with sufficient
  2415. notification of authentication-related events, and delegates to the
  2416. implementation whenever a candidate web request might contain a cookie
  2417. and wish to be remembered.</para>
  2418. <para>This design allows any number of remember-me implementation
  2419. strategies. In the interests of simplicity and avoiding the need for
  2420. DAO implementations that specify write and create methods, Acegi
  2421. Security's only concrete implementation,
  2422. <literal>TokenBasedRememberMeServices</literal>, uses hashing to
  2423. achieve a useful remember-me strategy. In essence a cookie is sent to
  2424. the browser upon successful interactive authentication, with that
  2425. cookie being composed as follows:</para>
  2426. <para><programlisting>base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
  2427. username: As identifiable to TokenBasedRememberMeServices.getAuthenticationDao()
  2428. password: That matches the relevant UserDetails retrieved from TokenBasedRememberMeServices.getAuthenticationDao()
  2429. expirationTime: The date and time when the remember-me token expires, expressed in milliseconds
  2430. key: A private key to prevent modification of the remember-me token
  2431. </programlisting></para>
  2432. <para>As such the remember-me token is valid only for the period
  2433. specified, and provided that the username, password and key does not
  2434. change. Notably, this has a potential security issue issue in that a
  2435. captured remember-me token will be usable from any user agent until
  2436. such time as the token expires. This is the same issue as with digest
  2437. authentication. If a principal is aware a token has been captured,
  2438. they can easily change their password and immediately invalidate all
  2439. remember-me tokens on issue. However, if more significant security is
  2440. needed a rolling token approach should be used (this would require a
  2441. database) or remember-me services should simply not be used.</para>
  2442. <para><literal>TokenBasedRememberMeServices</literal> generates a
  2443. <literal>RememberMeAuthenticationToken</literal>, which is processed
  2444. by <literal>RememberMeAuthenticationProvider</literal>. A
  2445. <literal>key</literal> is shared between this authentication provider
  2446. and the <literal>TokenBasedRememberMeServices</literal>. In addition,
  2447. <literal>TokenBasedRememberMeServices</literal> requires an
  2448. <literal>AuthenticationDao</literal> from which it can retrieve the
  2449. username and password for signature comparison purposes, and generate
  2450. the <literal>RememberMeAuthenticationToken</literal> to contain the
  2451. correct <literal>GrantedAuthority</literal>[]s. Some sort of logout
  2452. command should be provided by the application (typically via a JSP)
  2453. that invalidates the cookie upon user request. See the Contacts Sample
  2454. application's <literal>logout.jsp</literal> for an example.</para>
  2455. <para>The beans required in an application context to enable
  2456. remember-me services are as follows:</para>
  2457. <para><programlisting>&lt;bean id="rememberMeProcessingFilter" class="net.sf.acegisecurity.ui.rememberme.RememberMeProcessingFilter"&gt;
  2458. &lt;property name="rememberMeServices"&gt;&lt;ref local="rememberMeServices"/&gt;&lt;/property&gt;
  2459. &lt;/bean&gt;
  2460. &lt;bean id="rememberMeServices" class="net.sf.acegisecurity.ui.rememberme.TokenBasedRememberMeServices"&gt;
  2461. &lt;property name="authenticationDao"&gt;&lt;ref local="jdbcDaoImpl"/&gt;&lt;/property&gt;
  2462. &lt;property name="key"&gt;&lt;value&gt;springRocks&lt;/value&gt;&lt;/property&gt;
  2463. &lt;/bean&gt;
  2464. &lt;bean id="rememberMeAuthenticationProvider" class="net.sf.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider"&gt;
  2465. &lt;property name="key"&gt;&lt;value&gt;springRocks&lt;/value&gt;&lt;/property&gt;
  2466. &lt;/bean&gt;</programlisting>Don't forget to add your
  2467. <literal>RememberMeServices</literal> implementation to your
  2468. <literal>AuthenticationProcessingFilter.setRememberMeServices()</literal>
  2469. property, include the <literal>RememberMeProcessingFilter</literal> in
  2470. your <literal>AuthenticationManager.setProviders()</literal> list, and
  2471. add a call to <literal>RememberMeProcessingFilter</literal> into your
  2472. <literal>FilterChainProxy</literal> (typically immediately after your
  2473. <literal>AuthenticationProcessingFilter</literal>).</para>
  2474. </sect2>
  2475. <sect2 id="security-ui-well-known">
  2476. <title>Well-Known Locations</title>
  2477. <para>Prior to release 0.8.0, Acegi Security referred to "well-known
  2478. locations" in discussions about storing the
  2479. <literal>Authentication</literal>. This approach did not explicitly
  2480. separate the function of <literal>HttpSession</literal> storage of
  2481. <literal>ContextHolder</literal> contents from the processing of
  2482. authentication requests received through various protocols. In
  2483. addition, the previous approach did not facilitate storage of
  2484. non-<literal>Authentication</literal> objects between requests, which
  2485. was limiting usefulness of the <literal>ContextHolder</literal> system
  2486. to member of the community. For these reasons, the notion of
  2487. well-known locations was abandoned, the
  2488. <literal>HttpSessionContextIntegrationFilter</literal> was
  2489. established, and the purpose of authentication processing mechanisms
  2490. was explicitly defined and limited to interaction with the
  2491. <literal>ContextHolder</literal> only. There is no need to refer to
  2492. well-known locations any more and we hope this clearer separation of
  2493. responsibilities enhances understanding of the project.</para>
  2494. </sect2>
  2495. </sect1>
  2496. <sect1 id="security-container-adapters">
  2497. <title>Container Adapters</title>
  2498. <sect2 id="security-container-adapters-overview">
  2499. <title>Overview</title>
  2500. <para>Very early versions of the Acegi Security System for Spring
  2501. exclusively used Container Adapters for interfacing authentication
  2502. with end users. Whilst this worked well, it required considerable time
  2503. to support multiple container versions and the configuration itself
  2504. was relatively time-consuming for developers. For this reason the HTTP
  2505. Form Authentication and HTTP Basic Authentication approaches were
  2506. developed, and are today recommended for almost all
  2507. applications.</para>
  2508. <para>Container Adapters enable the Acegi Security System for Spring
  2509. to integrate directly with the containers used to host end user
  2510. applications. This integration means that applications can continue to
  2511. leverage the authentication and authorization capabilities built into
  2512. containers (such as <literal>isUserInRole()</literal> and form-based
  2513. or basic authentication), whilst benefiting from the enhanced security
  2514. interception capabilities provided by the Acegi Security System for
  2515. Spring (it should be noted that Acegi Security also offers
  2516. <literal>ContextHolderAwareRequestWrapper</literal> to deliver
  2517. <literal>isUserInRole()</literal> and similar Servlet Specification
  2518. compatibility methods).</para>
  2519. <para>The integration between a container and the Acegi Security
  2520. System for Spring is achieved through an adapter. The adapter provides
  2521. a container-compatible user authentication provider, and needs to
  2522. return a container-compatible user object.</para>
  2523. <para>The adapter is instantiated by the container and is defined in a
  2524. container-specific configuration file. The adapter then loads a Spring
  2525. application context which defines the normal authentication manager
  2526. settings, such as the authentication providers that can be used to
  2527. authenticate the request. The application context is usually named
  2528. <literal>acegisecurity.xml</literal> and is placed in a
  2529. container-specific location.</para>
  2530. <para>The Acegi Security System for Spring currently supports Jetty,
  2531. Catalina (Tomcat), JBoss and Resin. Additional container adapters can
  2532. easily be written.</para>
  2533. </sect2>
  2534. <sect2 id="security-container-adapters-adapter-provider">
  2535. <title>Adapter Authentication Provider</title>
  2536. <para>As is always the case, the container adapter generated
  2537. <literal>Authentication</literal> object still needs to be
  2538. authenticated by an <literal>AuthenticationManager</literal> when
  2539. requested to do so by the
  2540. <literal>AbstractSecurityInterceptor</literal>. The
  2541. <literal>AuthenticationManager</literal> needs to be certain the
  2542. adapter-provided <literal>Authentication</literal> object is valid and
  2543. was actually authenticated by a trusted adapter.</para>
  2544. <para>Adapters create <literal>Authentication</literal> objects which
  2545. are immutable and implement the <literal>AuthByAdapter</literal>
  2546. interface. These objects store the hash of a key that is defined by
  2547. the adapter. This allows the <literal>Authentication</literal> object
  2548. to be validated by the <literal>AuthByAdapterProvider</literal>. This
  2549. authentication provider is defined as follows:</para>
  2550. <para><programlisting>&lt;bean id="authByAdapterProvider" class="net.sf.acegisecurity.adapters.AuthByAdapterProvider"&gt;
  2551. &lt;property name="key"&gt;&lt;value&gt;my_password&lt;/value&gt;&lt;/property&gt;
  2552. &lt;/bean&gt;</programlisting></para>
  2553. <para>The key must match the key that is defined in the
  2554. container-specific configuration file that starts the adapter. The
  2555. <literal>AuthByAdapterProvider</literal> automatically accepts as
  2556. valid any <literal>AuthByAdapter</literal> implementation that returns
  2557. the expected hash of the key.</para>
  2558. <para>To reiterate, this means the adapter will perform the initial
  2559. authentication using providers such as
  2560. <literal>DaoAuthenticationProvider</literal>, returning an
  2561. <literal>AuthByAdapter</literal> instance that contains a hash code of
  2562. the key. Later, when an application calls a security interceptor
  2563. managed resource, the <literal>AuthByAdapter</literal> instance in the
  2564. <literal>SecureContext</literal> in the
  2565. <literal>ContextHolder</literal> will be tested by the application's
  2566. <literal>AuthByAdapterProvider</literal>. There is no requirement for
  2567. additional authentication providers such as
  2568. <literal>DaoAuthenticationProvider</literal> within the
  2569. application-specific application context, as the only type of
  2570. <literal>Authentication</literal> instance that will be presented by
  2571. the application is from the container adapter.</para>
  2572. <para>Classloader issues are frequent with containers and the use of
  2573. container adapters illustrates this further. Each container requires a
  2574. very specific configuration. The installation instructions are
  2575. provided below. Once installed, please take the time to try the sample
  2576. application to ensure your container adapter is properly
  2577. configured.</para>
  2578. <para>When using container adapters with the
  2579. <literal>DaoAuthenticationProvider</literal>, ensure you set its
  2580. <literal>forcePrincipalAsString</literal> property to
  2581. <literal>true</literal>.</para>
  2582. </sect2>
  2583. <sect2 id="security-container-adapters-catalina">
  2584. <title>Catalina (Tomcat) Installation</title>
  2585. <para>The following was tested with Jakarta Tomcat 4.1.30 and
  2586. 5.0.19.</para>
  2587. <para><literal>$CATALINA_HOME</literal> refers to the root of your
  2588. Catalina (Tomcat) installation.</para>
  2589. <para>Edit your <literal>$CATALINA_HOME/conf/server.xml</literal> file
  2590. so the <literal>&lt;Engine&gt;</literal> section contains only one
  2591. active <literal>&lt;Realm&gt;</literal> entry. An example realm
  2592. entry:</para>
  2593. <para><programlisting> &lt;Realm className="net.sf.acegisecurity.adapters.catalina.CatalinaAcegiUserRealm"
  2594. appContextLocation="conf/acegisecurity.xml"
  2595. key="my_password" /&gt;</programlisting></para>
  2596. <para>Be sure to remove any other <literal>&lt;Realm&gt;</literal>
  2597. entry from your <literal>&lt;Engine&gt;</literal> section.</para>
  2598. <para>Copy <literal>acegisecurity.xml</literal> into
  2599. <literal>$CATALINA_HOME/conf</literal>.</para>
  2600. <para>Copy <literal>acegi-security-catalina-XX.jar</literal> into
  2601. <literal>$CATALINA_HOME/server/lib</literal>.</para>
  2602. <para>Copy the following files into
  2603. <literal>$CATALINA_HOME/common/lib</literal>:</para>
  2604. <itemizedlist>
  2605. <listitem>
  2606. <para><literal>aopalliance.jar</literal></para>
  2607. </listitem>
  2608. <listitem>
  2609. <para><literal>spring.jar</literal></para>
  2610. </listitem>
  2611. <listitem>
  2612. <para><literal>commons-codec.jar</literal></para>
  2613. </listitem>
  2614. <listitem>
  2615. <para><literal>burlap.jar</literal></para>
  2616. </listitem>
  2617. <listitem>
  2618. <para><literal>hessian.jar</literal></para>
  2619. </listitem>
  2620. </itemizedlist>
  2621. <para>None of the above JAR files (or
  2622. <literal>acegi-security-XX.jar</literal>) should be in your
  2623. application's <literal>WEB-INF/lib</literal>. The realm name indicated
  2624. in your <literal>web.xml</literal> does not matter with
  2625. Catalina.</para>
  2626. <para>We have received reports of problems using this Container
  2627. Adapter with Mac OS X. A work-around is to use a script such as
  2628. follows:</para>
  2629. <para><programlisting>#!/bin/sh
  2630. export CATALINA_HOME="/Library/Tomcat"
  2631. export JAVA_HOME="/Library/Java/Home"
  2632. cd /
  2633. $CATALINA_HOME/bin/startup.sh</programlisting></para>
  2634. </sect2>
  2635. <sect2 id="security-container-adapters-jetty">
  2636. <title>Jetty Installation</title>
  2637. <para>The following was tested with Jetty 4.2.18.</para>
  2638. <para><literal>$JETTY_HOME</literal> refers to the root of your Jetty
  2639. installation.</para>
  2640. <para>Edit your <literal>$JETTY_HOME/etc/jetty.xml</literal> file so
  2641. the <literal>&lt;Configure class&gt;</literal> section has a new
  2642. addRealm call:</para>
  2643. <para><programlisting> &lt;Call name="addRealm"&gt;
  2644. &lt;Arg&gt;
  2645. &lt;New class="net.sf.acegisecurity.adapters.jetty.JettyAcegiUserRealm"&gt;
  2646. &lt;Arg&gt;Spring Powered Realm&lt;/Arg&gt;
  2647. &lt;Arg&gt;my_password&lt;/Arg&gt;
  2648. &lt;Arg&gt;etc/acegisecurity.xml&lt;/Arg&gt;
  2649. &lt;/New&gt;
  2650. &lt;/Arg&gt;
  2651. &lt;/Call&gt;</programlisting></para>
  2652. <para>Copy <literal>acegisecurity.xml</literal> into
  2653. <literal>$JETTY_HOME/etc</literal>.</para>
  2654. <para>Copy the following files into
  2655. <literal>$JETTY_HOME/ext</literal>:<itemizedlist>
  2656. <listitem>
  2657. <para><literal>aopalliance.jar</literal></para>
  2658. </listitem>
  2659. <listitem>
  2660. <para><literal>commons-logging.jar</literal></para>
  2661. </listitem>
  2662. <listitem>
  2663. <para><literal>spring.jar</literal></para>
  2664. </listitem>
  2665. <listitem>
  2666. <para><literal>acegi-security-jetty-XX.jar</literal></para>
  2667. </listitem>
  2668. <listitem>
  2669. <para><literal>commons-codec.jar</literal></para>
  2670. </listitem>
  2671. <listitem>
  2672. <para><literal>burlap.jar</literal></para>
  2673. </listitem>
  2674. <listitem>
  2675. <para><literal>hessian.jar</literal></para>
  2676. </listitem>
  2677. </itemizedlist></para>
  2678. <para>None of the above JAR files (or
  2679. <literal>acegi-security-XX.jar</literal>) should be in your
  2680. application's <literal>WEB-INF/lib</literal>. The realm name indicated
  2681. in your <literal>web.xml</literal> does matter with Jetty. The
  2682. <literal>web.xml</literal> must express the same
  2683. <literal>&lt;realm-name&gt;</literal> as your
  2684. <literal>jetty.xml</literal> (in the example above, "Spring Powered
  2685. Realm").</para>
  2686. </sect2>
  2687. <sect2 id="security-container-adapters-joss">
  2688. <title>JBoss Installation</title>
  2689. <para>The following was tested with JBoss 3.2.6.</para>
  2690. <para><literal>$JBOSS_HOME</literal> refers to the root of your JBoss
  2691. installation.</para>
  2692. <para>There are two different ways of making spring context available
  2693. to the Jboss integration classes.</para>
  2694. <para>The first approach is by editing your
  2695. <literal>$JBOSS_HOME/server/your_config/conf/login-config.xml</literal>
  2696. file so that it contains a new entry under the
  2697. <literal>&lt;Policy&gt;</literal> section:</para>
  2698. <para><programlisting> &lt;application-policy name = "SpringPoweredRealm"&gt;
  2699. &lt;authentication&gt;
  2700. &lt;login-module code = "net.sf.acegisecurity.adapters.jboss.JbossSpringLoginModule"
  2701. flag = "required"&gt;
  2702. &lt;module-option name = "appContextLocation"&gt;acegisecurity.xml&lt;/module-option&gt;
  2703. &lt;module-option name = "key"&gt;my_password&lt;/module-option&gt;
  2704. &lt;/login-module&gt;
  2705. &lt;/authentication&gt;
  2706. &lt;/application-policy&gt;</programlisting></para>
  2707. <para>Copy <literal>acegisecurity.xml</literal> into
  2708. <literal>$JBOSS_HOME/server/your_config/conf</literal>.</para>
  2709. <para>In this configuration <literal>acegisecurity.xml</literal>
  2710. contains the spring context definition including all the
  2711. authentication manager beans. You have to bear in mind though, that
  2712. <literal>SecurityContext</literal> is created and destroyed on each
  2713. login request, so the login operation might become costly.
  2714. Alternatively, the second approach is to use Spring singleton
  2715. capabilities through
  2716. <literal>org.springframework.beans.factory.access.SingletonBeanFactoryLocator</literal>.
  2717. The required configuration for this approach is:</para>
  2718. <para><programlisting> &lt;application-policy name = "SpringPoweredRealm"&gt;
  2719. &lt;authentication&gt;
  2720. &lt;login-module code = "net.sf.acegisecurity.adapters.jboss.JbossSpringLoginModule"
  2721. flag = "required"&gt;
  2722. &lt;module-option name = "singletonId"&gt;springRealm&lt;/module-option&gt;
  2723. &lt;module-option name = "key"&gt;my_password&lt;/module-option&gt;
  2724. &lt;module-option name = "authenticationManager"&gt;authenticationManager&lt;/module-option&gt;
  2725. &lt;/login-module&gt;
  2726. &lt;/authentication&gt;
  2727. &lt;/application-policy&gt;</programlisting></para>
  2728. <para>In the above code fragment,
  2729. <literal>authenticationManager</literal> is a helper property that
  2730. defines the expected name of the
  2731. <literal>AuthenticationManager</literal> in case you have several
  2732. defined in the IoC container. The <literal>singletonId</literal>
  2733. property references a bean defined in a
  2734. <literal>beanRefFactory.xml</literal> file. This file needs to be
  2735. available from anywhere on the JBoss classpath, including
  2736. <literal>$JBOSS_HOME/server/your_config/conf</literal>. The
  2737. <literal>beanRefFactory.xml</literal> contains the following
  2738. declaration:</para>
  2739. <para><programlisting>&lt;beans&gt;
  2740. &lt;bean id="springRealm" singleton="true" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext"&gt;
  2741. &lt;constructor-arg&gt;
  2742. &lt;list&gt;
  2743. &lt;value&gt;acegisecurity.xml&lt;/value&gt;
  2744. &lt;/list&gt;
  2745. &lt;/constructor-arg&gt;
  2746. &lt;/bean&gt;
  2747. &lt;/beans&gt;</programlisting></para>
  2748. <para>Finally, irrespective of the configuration approach you need to
  2749. copy the following files into
  2750. <literal>$JBOSS_HOME/server/your_config/lib</literal>:<itemizedlist>
  2751. <listitem>
  2752. <para><literal>aopalliance.jar</literal></para>
  2753. </listitem>
  2754. <listitem>
  2755. <para><literal>spring.jar</literal></para>
  2756. </listitem>
  2757. <listitem>
  2758. <para><literal>acegi-security-jboss-XX.jar</literal></para>
  2759. </listitem>
  2760. <listitem>
  2761. <para><literal>commons-codec.jar</literal></para>
  2762. </listitem>
  2763. <listitem>
  2764. <para><literal>burlap.jar</literal></para>
  2765. </listitem>
  2766. <listitem>
  2767. <para><literal>hessian.jar</literal></para>
  2768. </listitem>
  2769. </itemizedlist></para>
  2770. <para>None of the above JAR files (or
  2771. <literal>acegi-security-XX.jar</literal>) should be in your
  2772. application's <literal>WEB-INF/lib</literal>. The realm name indicated
  2773. in your <literal>web.xml</literal> does not matter with JBoss.
  2774. However, your web application's
  2775. <literal>WEB-INF/jboss-web.xml</literal> must express the same
  2776. <literal>&lt;security-domain&gt;</literal> as your
  2777. <literal>login-config.xml</literal>. For example, to match the above
  2778. example, your <literal>jboss-web.xml</literal> would look like
  2779. this:</para>
  2780. <para><programlisting>&lt;jboss-web&gt;
  2781. &lt;security-domain&gt;java:/jaas/SpringPoweredRealm&lt;/security-domain&gt;
  2782. &lt;/jboss-web&gt;</programlisting></para>
  2783. </sect2>
  2784. <sect2 id="security-container-adapters-resin">
  2785. <title>Resin Installation</title>
  2786. <para>The following was tested with Resin 3.0.6.</para>
  2787. <para><literal>$RESIN_HOME</literal> refers to the root of your Resin
  2788. installation.</para>
  2789. <para>Resin provides several ways to support the container adapter. In
  2790. the instructions below we have elected to maximise consistency with
  2791. other container adapter configurations. This will allow Resin users to
  2792. simply deploy the sample application and confirm correct
  2793. configuration. Developers comfortable with Resin are naturally able to
  2794. use its capabilities to package the JARs with the web application
  2795. itself, and/or support single sign-on.</para>
  2796. <para>Copy the following files into
  2797. <literal>$RESIN_HOME/lib</literal>:<itemizedlist>
  2798. <listitem>
  2799. <para><literal>aopalliance.jar</literal></para>
  2800. </listitem>
  2801. <listitem>
  2802. <para><literal>commons-logging.jar</literal></para>
  2803. </listitem>
  2804. <listitem>
  2805. <para><literal>spring.jar</literal></para>
  2806. </listitem>
  2807. <listitem>
  2808. <para><literal>acegi-security-resin-XX.jar</literal></para>
  2809. </listitem>
  2810. <listitem>
  2811. <para><literal>commons-codec.jar</literal></para>
  2812. </listitem>
  2813. <listitem>
  2814. <para><literal>burlap.jar</literal></para>
  2815. </listitem>
  2816. <listitem>
  2817. <para><literal>hessian.jar</literal></para>
  2818. </listitem>
  2819. </itemizedlist></para>
  2820. <para>Unlike the container-wide <literal>acegisecurity.xml</literal>
  2821. files used by other container adapters, each Resin web application
  2822. will contain its own
  2823. <literal>WEB-INF/resin-acegisecurity.xml</literal> file. Each web
  2824. application will also contain a <literal>resin-web.xml</literal> file
  2825. which Resin uses to start the container adapter:</para>
  2826. <para><programlisting>&lt;web-app&gt;
  2827. &lt;authenticator&gt;
  2828. &lt;type&gt;net.sf.acegisecurity.adapters.resin.ResinAcegiAuthenticator&lt;/type&gt;
  2829. &lt;init&gt;
  2830. &lt;app-context-location&gt;WEB-INF/resin-acegisecurity.xml&lt;/app-context-location&gt;
  2831. &lt;key&gt;my_password&lt;/key&gt;
  2832. &lt;/init&gt;
  2833. &lt;/authenticator&gt;
  2834. &lt;/web-app&gt;</programlisting></para>
  2835. <para>With the basic configuration provided above, none of the JAR
  2836. files listed (or <literal>acegi-security-XX.jar</literal>) should be
  2837. in your application's <literal>WEB-INF/lib</literal>. The realm name
  2838. indicated in your <literal>web.xml</literal> does not matter with
  2839. Resin, as the relevant authentication class is indicated by the
  2840. <literal>&lt;authenticator&gt;</literal> setting.</para>
  2841. </sect2>
  2842. </sect1>
  2843. <sect1 id="security-cas">
  2844. <title>Yale Central Authentication Service (CAS) Single Sign On</title>
  2845. <sect2 id="security-cas-overview">
  2846. <title>Overview</title>
  2847. <para>Yale University produces an enterprise-wide single sign on
  2848. system known as CAS. Unlike other initiatives, Yale's Central
  2849. Authentication Service is open source, widely used, simple to
  2850. understand, platform independent, and supports proxy capabilities. The
  2851. Acegi Security System for Spring fully supports CAS, and provides an
  2852. easy migration path from single-application deployments of Acegi
  2853. Security through to multiple-application deployments secured by an
  2854. enterprise-wide CAS server.</para>
  2855. <para>You can learn more about CAS at
  2856. <literal>http://www.yale.edu/tp/auth/</literal>. You will need to
  2857. visit this URL to download the CAS Server files. Whilst the Acegi
  2858. Security System for Spring includes two CAS libraries in the
  2859. "-with-dependencies" ZIP file, you will still need the CAS Java Server
  2860. Pages and <literal>web.xml</literal> to customise and deploy your CAS
  2861. server.</para>
  2862. </sect2>
  2863. <sect2 id="security-cas-how-cas-works">
  2864. <title>How CAS Works</title>
  2865. <para>Whilst the CAS web site above contains two documents that detail
  2866. the architecture of CAS, we present the general overview again here
  2867. within the context of the Acegi Security System for Spring. The
  2868. following refers to CAS 2.0, being the version of CAS that Acegi
  2869. Security System for Spring supports.</para>
  2870. <para>Somewhere in your enterprise you will need to setup a CAS
  2871. server. The CAS server is simply a standard WAR file, so there isn't
  2872. anything difficult about setting up your server. Inside the WAR file
  2873. you will customise the login and other single sign on pages displayed
  2874. to users. You will also need to specify in the web.xml a
  2875. <literal>PasswordHandler</literal>. The
  2876. <literal>PasswordHandler</literal> has a simple method that returns a
  2877. boolean as to whether a given username and password is valid. Your
  2878. <literal>PasswordHandler</literal> implementation will need to link
  2879. into some type of backend authentication repository, such as an LDAP
  2880. server or database.</para>
  2881. <para>If you are already running an existing CAS server instance, you
  2882. will have already established a <literal>PasswordHandler</literal>. If
  2883. you do not already have a <literal>PasswordHandler</literal>, you
  2884. might prefer to use the Acegi Security System for Spring
  2885. <literal>CasPasswordHandler</literal> class. This class delegates
  2886. through to the standard Acegi Security
  2887. <literal>AuthenticationManager</literal>, enabling you to use a
  2888. security configuration you might already have in place. You do not
  2889. need to use the <literal>CasPasswordHandler</literal> class on your
  2890. CAS server if you do not wish. The Acegi Security System for Spring
  2891. will function as a CAS client successfully irrespective of the
  2892. <literal>PasswordHandler</literal> you've chosen for your CAS
  2893. server.</para>
  2894. <para>Apart from the CAS server itself, the other key player is of
  2895. course the secure web applications deployed throughout your
  2896. enterprise. These web applications are known as "services". There are
  2897. two types of services: standard services and proxy services. A proxy
  2898. service is able to request resources from other services on behalf of
  2899. the user. This will be explained more fully later.</para>
  2900. <para>Services can be developed in a large variety of languages, due
  2901. to CAS 2.0's very light XML-based protocol. The Yale CAS home page
  2902. contains a clients archive which demonstrates CAS clients in Java,
  2903. Active Server Pages, Perl, Python and others. Naturally, Java support
  2904. is very strong given the CAS server is written in Java. You do not
  2905. need to use any of CAS' client classes in applications secured by the
  2906. Acegi Security System for Spring. This is handled transparently for
  2907. you.</para>
  2908. <para>The basic interaction between a web browser, CAS server and an
  2909. Acegi Security for System Spring secured service is as follows:</para>
  2910. <orderedlist>
  2911. <listitem>
  2912. <para>The web user is browsing the service's public pages. CAS or
  2913. Acegi Security is not involved.</para>
  2914. </listitem>
  2915. <listitem>
  2916. <para>The user eventually requests a page that is either secure or
  2917. one of the beans it uses is secure. Acegi Security's
  2918. <literal>SecurityEnforcementFilter</literal> will detect the
  2919. <literal>AuthenticationException</literal>.</para>
  2920. </listitem>
  2921. <listitem>
  2922. <para>Because the user's <literal>Authentication</literal> object
  2923. (or lack thereof) caused an
  2924. <literal>AuthenticationException</literal>, the
  2925. <literal>SecurityEnforcementFilter</literal> will call the
  2926. configured <literal>AuthenticationEntryPoint</literal>. If using
  2927. CAS, this will be the
  2928. <literal>CasProcessingFilterEntryPoint</literal> class.</para>
  2929. </listitem>
  2930. <listitem>
  2931. <para>The <literal>CasProcessingFilterEntry</literal> point will
  2932. redirect the user's browser to the CAS server. It will also
  2933. indicate a <literal>service</literal> parameter, which is the
  2934. callback URL for the Acegi Security service. For example, the URL
  2935. to which the browser is redirected might be
  2936. <literal>https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_acegi_cas_security_check</literal>.</para>
  2937. </listitem>
  2938. <listitem>
  2939. <para>After the user's browser redirects to CAS, they will be
  2940. prompted for their username and password. If the user presents a
  2941. session cookie which indicates they've previously logged on, they
  2942. will not be prompted to login again (there is an exception to this
  2943. procedure, which we'll cover later). CAS will use the
  2944. <literal>PasswordHandler</literal> discussed above to decide
  2945. whether the username and password is valid.</para>
  2946. </listitem>
  2947. <listitem>
  2948. <para>Upon successful login, CAS will redirect the user's browser
  2949. back to the original service. It will also include a
  2950. <literal>ticket</literal> parameter, which is an opaque string
  2951. representing the "service ticket". Continuing our earlier example,
  2952. the URL the browser is redirected to might be
  2953. <literal>https://server3.company.com/webapp/j_acegi_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ</literal>.</para>
  2954. </listitem>
  2955. <listitem>
  2956. <para>Back in the service web application, the
  2957. <literal>CasProcessingFilter</literal> is always listening for
  2958. requests to <literal>/j_acegi_cas_security_check</literal> (this
  2959. is configurable, but we'll use the defaults in this introduction).
  2960. The processing filter will construct a
  2961. <literal>UsernamePasswordAuthenticationToken</literal>
  2962. representing the service ticket. The principal will be equal to
  2963. <literal>CasProcessingFilter.CAS_STATEFUL_IDENTIFIER</literal>,
  2964. whilst the credentials will be the service ticket opaque value.
  2965. This authentication request will then be handed to the configured
  2966. <literal>AuthenticationManager</literal>.</para>
  2967. </listitem>
  2968. <listitem>
  2969. <para>The <literal>AuthenticationManager</literal> implementation
  2970. will be the <literal>ProviderManager</literal>, which is in turn
  2971. configured with the <literal>CasAuthenticationProvider</literal>.
  2972. The <literal>CasAuthenticationProvider</literal> only responds to
  2973. <literal>UsernamePasswordAuthenticationToken</literal>s containing
  2974. the CAS-specific principal (such as
  2975. <literal>CasProcessingFilter.CAS_STATEFUL_IDENTIFIER</literal>)
  2976. and <literal>CasAuthenticationToken</literal>s (discussed
  2977. later).</para>
  2978. </listitem>
  2979. <listitem>
  2980. <para><literal>CasAuthenticationProvider</literal> will validate
  2981. the service ticket using a <literal>TicketValidator</literal>
  2982. implementation. Acegi Security includes one implementation, the
  2983. <literal>CasProxyTicketValidator</literal>. This implementation a
  2984. ticket validation class included in the CAS client library. The
  2985. <literal>CasProxyTicketValidator</literal> makes a HTTPS request
  2986. to the CAS server in order to validate the service ticket. The
  2987. <literal>CasProxyTicketValidator</literal> may also include a
  2988. proxy callback URL, which is included in this example:
  2989. <literal>https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_acegi_cas_security_check&amp;ticket=ST-0-ER94xMJmn6pha35CQRoZ&amp;pgtUrl=https://server3.company.com/webapp/casProxy/receptor</literal>.</para>
  2990. </listitem>
  2991. <listitem>
  2992. <para>Back on the CAS server, the proxy validation request will be
  2993. received. If the presented service ticket matches the service URL
  2994. the ticket was issued to, CAS will provide an affirmative response
  2995. in XML indicating the username. If any proxy was involved in the
  2996. authentication (discussed below), the list of proxies is also
  2997. included in the XML response.</para>
  2998. </listitem>
  2999. <listitem>
  3000. <para>[OPTIONAL] If the request to the CAS validation service
  3001. included the proxy callback URL (in the <literal>pgtUrl</literal>
  3002. parameter), CAS will include a <literal>pgtIou</literal> string in
  3003. the XML response. This <literal>pgtIou</literal> represents a
  3004. proxy-granting ticket IOU. The CAS server will then create its own
  3005. HTTPS connection back to the <literal>pgtUrl</literal>. This is to
  3006. mutually authenticate the CAS server and the claimed service URL.
  3007. The HTTPS connection will be used to send a proxy granting ticket
  3008. to the original web application. For example,
  3009. <literal>https://server3.company.com/webapp/casProxy/receptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&amp;pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH</literal>.
  3010. We suggest you use CAS' <literal>ProxyTicketReceptor</literal>
  3011. servlet to receive these proxy-granting tickets, if they are
  3012. required.</para>
  3013. </listitem>
  3014. <listitem>
  3015. <para>The <literal>CasProxyTicketValidator</literal> will parse
  3016. the XML received from the CAS server. It will return to the
  3017. <literal>CasAuthenticationProvider</literal> a
  3018. <literal>TicketResponse</literal>, which includes the username
  3019. (mandatory), proxy list (if any were involved), and proxy-granting
  3020. ticket IOU (if the proxy callback was requested).</para>
  3021. </listitem>
  3022. <listitem>
  3023. <para>Next <literal>CasAuthenticationProvider</literal> will call
  3024. a configured <literal>CasProxyDecider</literal>. The
  3025. <literal>CasProxyDecider</literal> indicates whether the proxy
  3026. list in the <literal>TicketResponse</literal> is acceptable to the
  3027. service. Several implementations are provided with the Acegi
  3028. Security System: <literal>RejectProxyTickets</literal>,
  3029. <literal>AcceptAnyCasProxy</literal> and
  3030. <literal>NamedCasProxyDecider</literal>. These names are largely
  3031. self-explanatory, except <literal>NamedCasProxyDecider</literal>
  3032. which allows a <literal>List</literal> of trusted proxies to be
  3033. provided.</para>
  3034. </listitem>
  3035. <listitem>
  3036. <para><literal>CasAuthenticationProvider</literal> will next
  3037. request a <literal>CasAuthoritiesPopulator</literal> to advise the
  3038. <literal>GrantedAuthority</literal> objects that apply to the user
  3039. contained in the <literal>TicketResponse</literal>. Acegi Security
  3040. includes a <literal>DaoCasAuthoritiesPopulator</literal> which
  3041. simply uses the <literal>AuthenticationDao</literal>
  3042. infrastructure to find the <literal>UserDetails</literal> and
  3043. their associated <literal>GrantedAuthority</literal>s. Note that
  3044. the password and enabled/disabled status of
  3045. <literal>UserDetails</literal> returned by the
  3046. <literal>AuthenticationDao</literal> are ignored, as the CAS
  3047. server is responsible for authentication decisions.
  3048. <literal>DaoCasAuthoritiesPopulator</literal> is only concerned
  3049. with retrieving the <literal>GrantedAuthority</literal>s.</para>
  3050. </listitem>
  3051. <listitem>
  3052. <para>If there were no problems,
  3053. <literal>CasAuthenticationProvider</literal> constructs a
  3054. <literal>CasAuthenticationToken</literal> including the details
  3055. contained in the <literal>TicketResponse</literal> and the
  3056. <literal>GrantedAuthority</literal>s. The
  3057. <literal>CasAuthenticationToken</literal> contains the hash of a
  3058. key, so that the <literal>CasAuthenticationProvider</literal>
  3059. knows it created it.</para>
  3060. </listitem>
  3061. <listitem>
  3062. <para>Control then returns to
  3063. <literal>CasProcessingFilter</literal>, which places the created
  3064. <literal>CasAuthenticationToken</literal> into the
  3065. <literal>HttpSession</literal> attribute named
  3066. <literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>.</para>
  3067. </listitem>
  3068. <listitem>
  3069. <para>The user's browser is redirected to the original page that
  3070. caused the <literal>AuthenticationException</literal>.</para>
  3071. </listitem>
  3072. <listitem>
  3073. <para>As the <literal>Authentication</literal> object is now in
  3074. the well-known location, it is handled like any other
  3075. authentication approach. Usually the
  3076. <literal>HttpSessionIntegrationFilter</literal> will be used to
  3077. associate the <literal>Authentication</literal> object with the
  3078. <literal>ContextHolder</literal> for the duration of each
  3079. request.</para>
  3080. </listitem>
  3081. </orderedlist>
  3082. <para>It's good that you're still here! It might sound involved, but
  3083. you can relax as the Acegi Security System for Spring classes hide
  3084. much of the complexity. Let's now look at how this is
  3085. configured.</para>
  3086. </sect2>
  3087. <sect2 id="security-cas-install-server">
  3088. <title>CAS Server Installation (Optional)</title>
  3089. <para>As mentioned above, the Acegi Security System for Spring
  3090. includes a <literal>PasswordHandler</literal> that bridges your
  3091. existing <literal>AuthenticationManager</literal> into CAS. You do not
  3092. need to use this <literal>PasswordHandler</literal> to use Acegi
  3093. Security on the client side (any CAS
  3094. <literal>PasswordHandler</literal> will do).</para>
  3095. <para>To install, you will need to download and extract the CAS server
  3096. archive. We used version 2.0.12. There will be a
  3097. <literal>/web</literal> directory in the root of the deployment. Copy
  3098. an <literal>applicationContext.xml</literal> containing your
  3099. <literal>AuthenticationManager</literal> as well as the
  3100. <literal>CasPasswordHandler</literal> into the
  3101. <literal>/web/WEB-INF</literal> directory. A sample
  3102. <literal>applicationContext.xml</literal> is included below:</para>
  3103. <programlisting>&lt;bean id="inMemoryDaoImpl" class="net.sf.acegisecurity.providers.dao.memory.InMemoryDaoImpl"&gt;
  3104. &lt;property name="userMap"&gt;
  3105. &lt;value&gt;
  3106. marissa=koala,ROLES_IGNORED_BY_CAS
  3107. dianne=emu,ROLES_IGNORED_BY_CAS
  3108. scott=wombat,ROLES_IGNORED_BY_CAS
  3109. peter=opal,disabled,ROLES_IGNORED_BY_CAS
  3110. &lt;/value&gt;
  3111. &lt;/property&gt;
  3112. &lt;/bean&gt;
  3113. &lt;bean id="daoAuthenticationProvider" class="net.sf.acegisecurity.providers.dao.DaoAuthenticationProvider"&gt;
  3114. &lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
  3115. &lt;/bean&gt;
  3116. &lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt;
  3117. &lt;property name="providers"&gt;
  3118. &lt;list&gt;
  3119. &lt;ref bean="daoAuthenticationProvider"/&gt;
  3120. &lt;/list&gt;
  3121. &lt;/property&gt;
  3122. &lt;/bean&gt;
  3123. &lt;bean id="casPasswordHandler" class="net.sf.acegisecurity.adapters.cas.CasPasswordHandler"&gt;
  3124. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  3125. &lt;/bean&gt;</programlisting>
  3126. <para>Note the granted authorities are ignored by CAS because it has
  3127. no way of communicating the granted authorities to calling
  3128. applications. CAS is only concerned with username and passwords (and
  3129. the enabled/disabled status).</para>
  3130. <para>Next you will need to edit the existing
  3131. <literal>/web/WEB-INF/web.xml</literal> file. Add (or edit in the case
  3132. of the <literal>authHandler</literal> property) the following
  3133. lines:</para>
  3134. <para><programlisting>&lt;context-param&gt;
  3135. &lt;param-name&gt;edu.yale.its.tp.cas.authHandler&lt;/param-name&gt;
  3136. &lt;param-value&gt;net.sf.acegisecurity.adapters.cas.CasPasswordHandlerProxy&lt;/param-value&gt;
  3137. &lt;/context-param&gt;
  3138. &lt;context-param&gt;
  3139. &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
  3140. &lt;param-value&gt;/WEB-INF/applicationContext.xml&lt;/param-value&gt;
  3141. &lt;/context-param&gt;
  3142. &lt;listener&gt;
  3143. &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
  3144. &lt;/listener&gt;</programlisting></para>
  3145. <para>Copy the <literal>spring.jar</literal> and
  3146. <literal>acegi-security.jar</literal> files into
  3147. <literal>/web/WEB-INF/lib</literal>. Now use the <literal>ant
  3148. dist</literal> task in the <literal>build.xml</literal> in the root of
  3149. the directory structure. This will create
  3150. <literal>/lib/cas.war</literal>, which is ready for deployment to your
  3151. servlet container.</para>
  3152. <para>Note CAS heavily relies on HTTPS. You can't even test the system
  3153. without a HTTPS certificate. Whilst you should refer to your web
  3154. container's documentation on setting up HTTPS, if you need some
  3155. additional help or a test certificate you might like to check the
  3156. <literal>samples/contacts/etc/ssl</literal> directory.</para>
  3157. </sect2>
  3158. <sect2 id="security-cas-install-client">
  3159. <title>CAS Acegi Security System Client Installation</title>
  3160. <para>The web application side of CAS is made easy due to the Acegi
  3161. Security System for Spring. It is assumed you already know the basics
  3162. of using the Acegi Security System for Spring, so these are not
  3163. covered again below. Only the CAS-specific beans are mentioned.</para>
  3164. <para>You will need to add a <literal>ServiceProperties</literal> bean
  3165. to your application context. This represents your service:</para>
  3166. <para><programlisting>&lt;bean id="serviceProperties" class="net.sf.acegisecurity.ui.cas.ServiceProperties"&gt;
  3167. &lt;property name="service"&gt;&lt;value&gt;https://localhost:8443/contacts-cas/j_acegi_cas_security_check&lt;/value&gt;&lt;/property&gt;
  3168. &lt;property name="sendRenew"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  3169. &lt;/bean&gt;</programlisting></para>
  3170. <para>The <literal>service</literal> must equal a URL that will be
  3171. monitored by the <literal>CasProcessingFilter</literal>. The
  3172. <literal>sendRenew</literal> defaults to false, but should be set to
  3173. true if your application is particularly sensitive. What this
  3174. parameter does is tell the CAS login service that a single sign on
  3175. login is unacceptable. Instead, the user will need to re-enter their
  3176. username and password in order to gain access to the service.</para>
  3177. <para>The following beans should be configured to commence the CAS
  3178. authentication process:</para>
  3179. <para><programlisting>&lt;bean id="casProcessingFilter" class="net.sf.acegisecurity.ui.cas.CasProcessingFilter"&gt;
  3180. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  3181. &lt;property name="authenticationFailureUrl"&gt;&lt;value&gt;/casfailed.jsp&lt;/value&gt;&lt;/property&gt;
  3182. &lt;property name="defaultTargetUrl"&gt;&lt;value&gt;/&lt;/value&gt;&lt;/property&gt;
  3183. &lt;property name="filterProcessesUrl"&gt;&lt;value&gt;/j_acegi_cas_security_check&lt;/value&gt;&lt;/property&gt;
  3184. &lt;/bean&gt;
  3185. &lt;bean id="securityEnforcementFilter" class="net.sf.acegisecurity.intercept.web.SecurityEnforcementFilter"&gt;
  3186. &lt;property name="filterSecurityInterceptor"&gt;&lt;ref bean="filterInvocationInterceptor"/&gt;&lt;/property&gt;
  3187. &lt;property name="authenticationEntryPoint"&gt;&lt;ref bean="casProcessingFilterEntryPoint"/&gt;&lt;/property&gt;
  3188. &lt;/bean&gt;
  3189. &lt;bean id="casProcessingFilterEntryPoint" class="net.sf.acegisecurity.ui.cas.CasProcessingFilterEntryPoint"&gt;
  3190. &lt;property name="loginUrl"&gt;&lt;value&gt;https://localhost:8443/cas/login&lt;/value&gt;&lt;/property&gt;
  3191. &lt;property name="serviceProperties"&gt;&lt;ref bean="serviceProperties"/&gt;&lt;/property&gt;
  3192. &lt;/bean&gt;</programlisting></para>
  3193. <para>You will also need to add the
  3194. <literal>CasProcessingFilter</literal> to web.xml:</para>
  3195. <para><programlisting>&lt;filter&gt;
  3196. &lt;filter-name&gt;Acegi CAS Processing Filter&lt;/filter-name&gt;
  3197. &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
  3198. &lt;init-param&gt;
  3199. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  3200. &lt;param-value&gt;net.sf.acegisecurity.ui.cas.CasProcessingFilter&lt;/param-value&gt;
  3201. &lt;/init-param&gt;
  3202. &lt;/filter&gt;
  3203. &lt;filter-mapping&gt;
  3204. &lt;filter-name&gt;Acegi CAS Processing Filter&lt;/filter-name&gt;
  3205. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  3206. &lt;/filter-mapping&gt;</programlisting></para>
  3207. <para>The <literal>CasProcessingFilter</literal> has very similar
  3208. properties to the <literal>AuthenticationProcessingFilter</literal>
  3209. (used for form-based logins). Each property is
  3210. self-explanatory.</para>
  3211. <para>For CAS to operate, the
  3212. <literal>SecurityEnforcementFilter</literal> must have its
  3213. <literal>authenticationEntryPoint</literal> property set to the
  3214. <literal>CasProcessingFilterEntryPoint</literal> bean.</para>
  3215. <para>The <literal>CasProcessingFilterEntryPoint</literal> must refer
  3216. to the <literal>ServiceProperties</literal> bean (discussed above),
  3217. which provides the URL to the enterprise's CAS login server. This is
  3218. where the user's browser will be redirected.</para>
  3219. <para>Next you need to add an <literal>AuthenticationManager</literal>
  3220. that uses <literal>CasAuthenticationProvider</literal> and its
  3221. collaborators:</para>
  3222. <para><programlisting>&lt;bean id="authenticationManager" class="net.sf.acegisecurity.providers.ProviderManager"&gt;
  3223. &lt;property name="providers"&gt;
  3224. &lt;list&gt;
  3225. &lt;ref bean="casAuthenticationProvider"/&gt;
  3226. &lt;/list&gt;
  3227. &lt;/property&gt;
  3228. &lt;/bean&gt;
  3229. &lt;bean id="casAuthenticationProvider" class="net.sf.acegisecurity.providers.cas.CasAuthenticationProvider"&gt;
  3230. &lt;property name="casAuthoritiesPopulator"&gt;&lt;ref bean="casAuthoritiesPopulator"/&gt;&lt;/property&gt;
  3231. &lt;property name="casProxyDecider"&gt;&lt;ref bean="casProxyDecider"/&gt;&lt;/property&gt;
  3232. &lt;property name="ticketValidator"&gt;&lt;ref bean="casProxyTicketValidator"/&gt;&lt;/property&gt;
  3233. &lt;property name="statelessTicketCache"&gt;&lt;ref bean="statelessTicketCache"/&gt;&lt;/property&gt;
  3234. &lt;property name="key"&gt;&lt;value&gt;my_password_for_this_auth_provider_only&lt;/value&gt;&lt;/property&gt;
  3235. &lt;/bean&gt;
  3236. &lt;bean id="casProxyTicketValidator" class="net.sf.acegisecurity.providers.cas.ticketvalidator.CasProxyTicketValidator"&gt;
  3237. &lt;property name="casValidate"&gt;&lt;value&gt;https://localhost:8443/cas/proxyValidate&lt;/value&gt;&lt;/property&gt;
  3238. &lt;property name="proxyCallbackUrl"&gt;&lt;value&gt;https://localhost:8443/contacts-cas/casProxy/receptor&lt;/value&gt;&lt;/property&gt;
  3239. &lt;property name="serviceProperties"&gt;&lt;ref bean="serviceProperties"/&gt;&lt;/property&gt;
  3240. &lt;!-- &lt;property name="trustStore"&gt;&lt;value&gt;/some/path/to/your/lib/security/cacerts&lt;/value&gt;&lt;/property&gt; --&gt;
  3241. &lt;/bean&gt;
  3242. &lt;bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"&gt;
  3243. &lt;property name="configLocation"&gt;
  3244. &lt;value&gt;classpath:/ehcache-failsafe.xml&lt;/value&gt;
  3245. &lt;/property&gt;
  3246. &lt;/bean&gt;
  3247. &lt;bean id="ticketCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;
  3248. &lt;property name="cacheManager"&gt;
  3249. &lt;ref local="cacheManager"/&gt;
  3250. &lt;/property&gt;
  3251. &lt;property name="cacheName"&gt;
  3252. &lt;value&gt;ticketCache&lt;/value&gt;
  3253. &lt;/property&gt;
  3254. &lt;/bean&gt;
  3255. &lt;bean id="statelessTicketCache" class="net.sf.acegisecurity.providers.cas.cache.EhCacheBasedTicketCache"&gt;
  3256. &lt;property name="cache"&gt;&lt;ref local="ticketCacheBackend"/&gt;&lt;/property&gt;
  3257. &lt;/bean&gt;
  3258. &lt;bean id="casAuthoritiesPopulator" class="net.sf.acegisecurity.providers.cas.populator.DaoCasAuthoritiesPopulator"&gt;
  3259. &lt;property name="authenticationDao"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
  3260. &lt;/bean&gt;
  3261. &lt;bean id="casProxyDecider" class="net.sf.acegisecurity.providers.cas.proxy.RejectProxyTickets"/&gt;</programlisting></para>
  3262. <para>The beans are all reasonable self-explanatory if you refer back
  3263. to the "How CAS Works" section. Careful readers might notice one
  3264. surprise: the <literal>statelessTicketCache</literal> property of the
  3265. <literal>CasAuthenticationProvider</literal>. This is discussed in
  3266. detail in the "Advanced CAS Usage" section.</para>
  3267. <para>Note the <literal>CasProxyTicketValidator</literal> has a
  3268. remarked out <literal>trustStore</literal> property. This property
  3269. might be helpful if you experience HTTPS certificate issues. Also note
  3270. the <literal>proxyCallbackUrl</literal> is set so the service can
  3271. receive a proxy-granting ticket. As mentioned above, this is optional
  3272. and unnecessary if you do not require proxy-granting tickets. If you
  3273. do use this feature, you will need to configure a suitable servlet to
  3274. receive the proxy-granting tickets. We suggest you use CAS'
  3275. <literal>ProxyTicketReceptor</literal> by adding the following to your
  3276. web application's <literal>web.xml</literal>:</para>
  3277. <para><programlisting>&lt;servlet&gt;
  3278. &lt;servlet-name&gt;casproxy&lt;/servlet-name&gt;
  3279. &lt;servlet-class&gt;edu.yale.its.tp.cas.proxy.ProxyTicketReceptor&lt;/servlet-class&gt;
  3280. &lt;/servlet&gt;
  3281. &lt;servlet-mapping&gt;
  3282. &lt;servlet-name&gt;casproxy&lt;/servlet-name&gt;
  3283. &lt;url-pattern&gt;/casProxy/*&lt;/url-pattern&gt;
  3284. &lt;/servlet-mapping&gt;</programlisting></para>
  3285. <para>This completes the configuration of CAS. If you haven't made any
  3286. mistakes, your web application should happily work within the
  3287. framework of CAS single sign on. No other parts of the Acegi Security
  3288. System for Spring need to be concerned about the fact CAS handled
  3289. authentication.</para>
  3290. <para>There is also a <literal>contacts-cas.war</literal> file in the
  3291. sample applications directory. This sample application uses the above
  3292. settings and can be deployed to see CAS in operation.</para>
  3293. </sect2>
  3294. <sect2 id="security-cas-advanced-usage">
  3295. <title>Advanced CAS Usage</title>
  3296. <para>The <literal>CasAuthenticationProvider</literal> distinguishes
  3297. between stateful and stateless clients. A stateful client is
  3298. considered any that originates via the
  3299. <literal>CasProcessingFilter</literal>. A stateless client is any that
  3300. presents an authentication request via the
  3301. <literal>UsernamePasswordAuthenticationToken</literal> with a
  3302. principal equal to
  3303. <literal>CasProcessingFilter.CAS_STATELESS_IDENTIFIER</literal>.</para>
  3304. <para>Stateless clients are likely to be via remoting protocols such
  3305. as Hessian and Burlap. The <literal>BasicProcessingFilter</literal> is
  3306. still used in this case, but the remoting protocol client is expected
  3307. to present a username equal to the static string above, and a password
  3308. equal to a CAS service ticket. Clients should acquire a CAS service
  3309. ticket directly from the CAS server.</para>
  3310. <para>Because remoting protocols have no way of presenting themselves
  3311. within the context of a <literal>HttpSession</literal>, it isn't
  3312. possible to rely on the <literal>HttpSession</literal>'s
  3313. <literal>HttpSessionIntegrationFilter.ACEGI_SECURITY_AUTHENTICATION_KEY</literal>
  3314. attribute to locate the <literal>CasAuthenticationToken</literal>.
  3315. Furthermore, because the CAS server invalidates a service ticket after
  3316. it has been validated by the <literal>TicketValidator</literal>,
  3317. presenting the same service ticket on subsequent requests will not
  3318. work. It is similarly very difficult to obtain a proxy-granting ticket
  3319. for a remoting protocol client, as they are often deployed on client
  3320. machines which rarely have HTTPS URLs that would be accessible to the
  3321. CAS server.</para>
  3322. <para>One obvious option is to not use CAS at all for remoting
  3323. protocol clients. However, this would eliminate many of the desirable
  3324. features of CAS.</para>
  3325. <para>As a middle-ground, the
  3326. <literal>CasAuthenticationProvider</literal> uses a
  3327. <literal>StatelessTicketCache</literal>. This is used solely for
  3328. requests with a principal equal to
  3329. <literal>CasProcessingFilter.CAS_STATELESS_IDENTIFIER</literal>. What
  3330. happens is the <literal>CasAuthenticationProvider</literal> will store
  3331. the resulting <literal>CasAuthenticationToken</literal> in the
  3332. <literal>StatelessTicketCache</literal>, keyed on the service ticket.
  3333. Accordingly, remoting protocol clients can present the same service
  3334. ticket and the <literal>CasAuthenticationProvider</literal> will not
  3335. need to contact the CAS server for validation (aside from the first
  3336. request).</para>
  3337. <para>The other aspect of advanced CAS usage involves creating proxy
  3338. tickets from the proxy-granting ticket. As indicated above, we
  3339. recommend you use CAS' <literal>ProxyTicketReceptor</literal> to
  3340. receive these tickets. The <literal>ProxyTicketReceptor</literal>
  3341. provides a static method that enables you to obtain a proxy ticket by
  3342. presenting the proxy-granting IOU ticket. You can obtain the
  3343. proxy-granting IOU ticket by calling
  3344. <literal>CasAuthenticationToken.getProxyGrantingTicketIou()</literal>.</para>
  3345. <para>It is hoped you find CAS integration easy and useful with the
  3346. Acegi Security System for Spring classes. Welcome to enterprise-wide
  3347. single sign on!</para>
  3348. </sect2>
  3349. </sect1>
  3350. <sect1 id="security-x509">
  3351. <title>X509 Authentication</title>
  3352. <sect2 id="security-x509-overview">
  3353. <title>Overview</title>
  3354. <para>The most common use of X509 certificate authentication is in
  3355. verifying the identity of a server when using SSL, most commonly when
  3356. using HTTPS from a browser. The browser will automatically check that
  3357. the certificate presented by a server has been issued (ie digitally
  3358. signed) by one of a list of trusted certificate authorities which it
  3359. maintains.</para>
  3360. <para>You can also use SSL with <quote>mutual authentication</quote>;
  3361. the server will then request a valid certificate from the client as
  3362. part of the SSL handshake. The server will authenticate the client by
  3363. checking that it's certificate is signed by an acceptable authority.
  3364. If a valid certificate has been provided, it can be obtained through
  3365. the servlet API in an application. The Acegi Security X509 module
  3366. extracts the certificate using a filter and passes it to the
  3367. configured X509 authentication provider to allow any additional
  3368. application-specific checks to be applied. It also maps the
  3369. certificate to an application user and loads that user's set of
  3370. granted authorities for use with the standard Acegi Security
  3371. infrastructure.</para>
  3372. <para>You should be familiar with using certificates and setting up
  3373. client authentication for your servlet container before attempting to
  3374. use it with Acegi Security. Most of the work is in creating and
  3375. installing suitable certificates and keys. For example, if you're
  3376. using Tomcat then read the instructions here <ulink
  3377. url="http://jakarta.apache.org/tomcat/tomcat-5.0-doc/ssl-howto.html"></ulink>.
  3378. It's important that you get this working before trying it out with
  3379. Acegi Security.</para>
  3380. </sect2>
  3381. <sect2 id="security-x509-details">
  3382. <title>X509 with Acegi Security</title>
  3383. <para>With X509 authentication, there is no explicit login procedure
  3384. so the implementation is relatively simple; there is no need to
  3385. redirect requests in order to interact with the user. As a result,
  3386. some of the classes behave slightly differently from their equivalents
  3387. in other packages. For example, the default <quote>entry point</quote>
  3388. class, which is normally responsible for starting the authentication
  3389. process, is only invoked if the certificate is rejected and it always
  3390. returns an error to the user. With a suitable bean configuration, the
  3391. normal sequence of events is as follows <orderedlist>
  3392. <listitem>
  3393. <para>The <classname>X509ProcessingFilter</classname> extracts
  3394. the certificate from the request and uses it as the credentials
  3395. for an authentication request. The generated authentication
  3396. request is an <classname>X509AuthenticationToken</classname>.
  3397. The request is passed to the authentication manager.</para>
  3398. </listitem>
  3399. <listitem>
  3400. <para>The <classname>X509AuthenticationProvider</classname>
  3401. receives the token. Its main concern is to obtain the user
  3402. information (in particular the user's granted authorities) that
  3403. matches the certificate. It delegates this responsibility to an
  3404. <interfacename>X509AuthoritiesPopulator</interfacename>.</para>
  3405. </listitem>
  3406. .
  3407. <listitem>
  3408. <para>The populator's single method,
  3409. <methodname>getUserDetails(X509Certificate
  3410. userCertificate)</methodname> is invoked. Implementations should
  3411. return a <classname>UserDetails</classname> instance containing
  3412. the array of <classname>GrantedAuthority</classname> objects for
  3413. the user. This method can also choose to reject the certificate
  3414. (for example if it doesn't contain a matching user name). In
  3415. such cases it should throw a
  3416. <exceptionname>BadCredentialsException</exceptionname>. A
  3417. DAO-based implementation,
  3418. <classname>DaoX509AuthoritiesPopulator</classname>, is provided
  3419. which extracts the user's name from the subject <quote>common
  3420. name</quote> (CN) in the certificate. It also allows you to set
  3421. your own regular expression to match a different part of the
  3422. subject's distinguished name. An
  3423. <classname>AuthenticationDao</classname> is used to load the
  3424. user information.<!-- TODO: Give email matching as an example --></para>
  3425. </listitem>
  3426. <listitem>
  3427. <para>If everything has gone smoothly then there should be a
  3428. valid <classname>Authentication</classname> object in the secure
  3429. context and the invocation will procede as normal. If no
  3430. certificate was found, or the certificate was rejected, then the
  3431. <classname>SecurityEnforcementFilter</classname> will invoke the
  3432. <classname>X509ProcessingFilterEntryPoint</classname> which
  3433. returns a 403 error (forbidden) to the user.</para>
  3434. </listitem>
  3435. </orderedlist></para>
  3436. </sect2>
  3437. <sect2 id="security-x509-config">
  3438. <title>Configuring the X509 Provider</title>
  3439. <para>There is a version of the <link
  3440. linkend="security-sample">contacts sample application</link> which
  3441. uses X509. Copy the beans and filter setup from this as a starting
  3442. point for configuring your own application. A set of example
  3443. certificates is also included which you can use to configure your
  3444. server. These are <itemizedlist>
  3445. <listitem>
  3446. <para><filename>marissa.p12</filename>: A PKCS12 format file
  3447. containing the client key and certificate. These should be
  3448. installed in your browser. It maps to the user
  3449. <quote>marissa</quote> in the application.</para>
  3450. </listitem>
  3451. <listitem>
  3452. <para><filename>server.p12</filename>: The server certificate
  3453. and key for HTTPS connections.</para>
  3454. </listitem>
  3455. <listitem>
  3456. <para><filename>ca.jks</filename>: A Java keystore containing
  3457. the certificate for the authority which issued marissa's
  3458. certificate. This will be used by the container to validate
  3459. client certificates.</para>
  3460. </listitem>
  3461. </itemizedlist> For JBoss 3.2.7 (with Tomcat 5.0), the SSL
  3462. configuration in the <filename>server.xml</filename> file looks like
  3463. this <programlisting>&lt;!-- SSL/TLS Connector configuration --&gt;
  3464. &lt;Connector port="8443" address="${jboss.bind.address}"
  3465. maxThreads="100" minSpareThreads="5" maxSpareThreads="15"
  3466. scheme="https" secure="true"
  3467. sslProtocol = "TLS"
  3468. clientAuth="true" keystoreFile="${jboss.server.home.dir}/conf/server.p12"
  3469. keystoreType="PKCS12" keystorePass="password"
  3470. truststoreFile="${jboss.server.home.dir}/conf/ca.jks"
  3471. truststoreType="JKS" truststorePass="password"
  3472. /&gt;</programlisting><parameter>clientAuth</parameter> can also be set to
  3473. <parameter>want</parameter> if you still want SSL connections to
  3474. succeed even if the client doesn't provide a certificate. Obviously
  3475. these clients won't be able to access any objects secured by Acegi
  3476. Security (unless you use a non-X509 authentication mechanism, such as
  3477. BASIC authentication, to authenticate the user).</para>
  3478. </sect2>
  3479. </sect1>
  3480. <sect1 id="security-channels">
  3481. <title>Channel Security</title>
  3482. <sect2 id="security-channels-overview">
  3483. <title>Overview</title>
  3484. <para>In addition to coordinating the authentication and authorization
  3485. requirements of your application, the Acegi Security System for Spring
  3486. is also able to ensure unauthenticated web requests have certain
  3487. properties. These properties may include being of a particular
  3488. transport type, having a particular <literal>HttpSession</literal>
  3489. attribute set and so on. The most common requirement is for your web
  3490. requests to be received using a particular transport protocol, such as
  3491. HTTPS.</para>
  3492. <para>An important issue in considering transport security is that of
  3493. session hijacking. Your web container manages a
  3494. <literal>HttpSession</literal> by reference to a
  3495. <literal>jsessionid</literal> that is sent to user agents either via a
  3496. cookie or URL rewriting. If the <literal>jsessionid</literal> is ever
  3497. sent over HTTP, there is a possibility that session identifier can be
  3498. intercepted and used to impersonate the user after they complete the
  3499. authentication process. This is because most web containers maintain
  3500. the same session identifier for a given user, even after they switch
  3501. from HTTP to HTTPS pages.</para>
  3502. <para>If session hijacking is considered too significant a risk for
  3503. your particular application, the only option is to use HTTPS for every
  3504. request. This means the <literal>jsessionid</literal> is never sent
  3505. across an insecure channel. You will need to ensure your
  3506. <literal>web.xml</literal>-defined
  3507. <literal>&lt;welcome-file&gt;</literal> points to a HTTPS location,
  3508. and the application never directs the user to a HTTP location. The
  3509. Acegi Security System for Spring provides a solution to assist with
  3510. the latter.</para>
  3511. </sect2>
  3512. <sect2 id="security-channels-installation">
  3513. <title>Configuration</title>
  3514. <para>To utilise Acegi Security's channel security services, add the
  3515. following lines to <literal>web.xml</literal>:</para>
  3516. <para><programlisting>&lt;filter&gt;
  3517. &lt;filter-name&gt;Acegi Channel Processing Filter&lt;/filter-name&gt;
  3518. &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
  3519. &lt;init-param&gt;
  3520. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  3521. &lt;param-value&gt;net.sf.acegisecurity.securechannel.ChannelProcessingFilter&lt;/param-value&gt;
  3522. &lt;/init-param&gt;
  3523. &lt;/filter&gt;
  3524. &lt;filter-mapping&gt;
  3525. &lt;filter-name&gt;Acegi Channel Processing Filter&lt;/filter-name&gt;
  3526. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  3527. &lt;/filter-mapping&gt;</programlisting></para>
  3528. <para>As usual when running <literal>FilterToBeanProxy</literal>, you
  3529. will also need to configure the filter in your application
  3530. context:</para>
  3531. <para><programlisting>&lt;bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter"&gt;
  3532. &lt;property name="channelDecisionManager"&gt;&lt;ref bean="channelDecisionManager"/&gt;&lt;/property&gt;
  3533. &lt;property name="filterInvocationDefinitionSource"&gt;
  3534. &lt;value&gt;
  3535. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  3536. \A/secure/.*\Z=REQUIRES_SECURE_CHANNEL
  3537. \A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
  3538. \A/j_acegi_security_check.*\Z=REQUIRES_SECURE_CHANNEL
  3539. \A.*\Z=REQUIRES_INSECURE_CHANNEL
  3540. &lt;/value&gt;
  3541. &lt;/property&gt;
  3542. &lt;/bean&gt;
  3543. &lt;bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl"&gt;
  3544. &lt;property name="channelProcessors"&gt;
  3545. &lt;list&gt;
  3546. &lt;ref bean="secureChannelProcessor"/&gt;
  3547. &lt;ref bean="insecureChannelProcessor"/&gt;
  3548. &lt;/list&gt;
  3549. &lt;/property&gt;
  3550. &lt;/bean&gt;
  3551. &lt;bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/&gt;
  3552. &lt;bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/&gt;</programlisting></para>
  3553. <para>Like <literal>FilterSecurityInterceptor</literal>, Apache Ant
  3554. style paths are also supported by the
  3555. <literal>ChannelProcessingFilter</literal>.</para>
  3556. <para>The <literal>ChannelProcessingFilter</literal> operates by
  3557. filtering all web requests and determining the configuration
  3558. attributes that apply. It then delegates to the
  3559. <literal>ChannelDecisionManager</literal>. The default implementation,
  3560. <literal>ChannelDecisionManagerImpl</literal>, should suffice in most
  3561. cases. It simply delegates through the list of configured
  3562. <literal>ChannelProcessor</literal> instances. A
  3563. <literal>ChannelProcessor</literal> will review the request, and if it
  3564. is unhappy with the request (eg it was received across the incorrect
  3565. transport protocol), it will perform a redirect, throw an exception or
  3566. take whatever other action is appropriate.</para>
  3567. <para>Included with the Acegi Security System for Spring are two
  3568. concrete <literal>ChannelProcessor</literal> implementations:
  3569. <literal>SecureChannelProcessor</literal> ensures requests with a
  3570. configuration attribute of <literal>REQUIRES_SECURE_CHANNEL</literal>
  3571. are received over HTTPS, whilst
  3572. <literal>InsecureChannelProcessor</literal> ensures requests with a
  3573. configuration attribute of
  3574. <literal>REQUIRES_INSECURE_CHANNEL</literal> are received over HTTP.
  3575. Both implementations delegate to a
  3576. <literal>ChannelEntryPoint</literal> if the required transport
  3577. protocol is not used. The two <literal>ChannelEntryPoint</literal>
  3578. implementations included with Acegi Security simply redirect the
  3579. request to HTTP and HTTPS as appropriate. Appropriate defaults are
  3580. assigned to the <literal>ChannelProcessor</literal> implementations
  3581. for the configuration attribute keywords they respond to and the
  3582. <literal>ChannelEntryPoint</literal> they delegate to, although you
  3583. have the ability to override these using the application
  3584. context.</para>
  3585. <para>Note that the redirections are absolute (eg
  3586. http://www.company.com:8080/app/page), not relative (eg /app/page).
  3587. During testing it was discovered that Internet Explorer 6 Service Pack
  3588. 1 has a bug whereby it does not respond correctly to a redirection
  3589. instruction which also changes the port to use. Accordingly, absolute
  3590. URLs are used in conjunction with bug detection logic in the
  3591. <literal>PortResolverImpl</literal> that is wired up by default to
  3592. many Acegi Security beans. Please refer to the JavaDocs for
  3593. <literal>PortResolverImpl</literal> for further details.</para>
  3594. </sect2>
  3595. <sect2 id="security-channels-usage">
  3596. <title>Usage</title>
  3597. <para>Once configured, using the channel security filter is very easy.
  3598. Simply request pages without regard to the protocol (ie HTTP or HTTPS)
  3599. or port (eg 80, 8080, 443, 8443 etc). Obviously you'll still need a
  3600. way of making the initial request (probably via the
  3601. <literal>web.xml</literal> <literal>&lt;welcome-file&gt;</literal> or
  3602. a well-known home page URL), but once this is done the filter will
  3603. perform redirects as defined by your application context.</para>
  3604. <para>You can also add your own <literal>ChannelProcessor</literal>
  3605. implementations to the <literal>ChannelDecisionManagerImpl</literal>.
  3606. For example, you might set a <literal>HttpSession</literal> attribute
  3607. when a human user is detected via a "enter the contents of this
  3608. graphic" procedure. Your <literal>ChannelProcessor</literal> would
  3609. respond to say <literal>REQUIRES_HUMAN_USER</literal> configuration
  3610. attributes and redirect to an appropriate entry point to start the
  3611. human user validation process if the <literal>HttpSession</literal>
  3612. attribute is not currently set.</para>
  3613. <para>To decide whether a security check belongs in a
  3614. <literal>ChannelProcessor</literal> or an
  3615. <literal>AccessDecisionVoter</literal>, remember that the former is
  3616. designed to handle unauthenticated requests, whilst the latter is
  3617. designed to handle authenticated requests. The latter therefore has
  3618. access to the granted authorities of the authenticated principal. In
  3619. addition, problems detected by a <literal>ChannelProcessor</literal>
  3620. will generally cause a HTTP/HTTPS redirection so its requirements can
  3621. be met, whilst problems detected by an
  3622. <literal>AccessDecisionVoter</literal> will ultimately result in an
  3623. <literal>AccessDeniedException</literal> (depending on the governing
  3624. <literal>AccessDecisionManager</literal>).</para>
  3625. </sect2>
  3626. </sect1>
  3627. <sect1 id="acls">
  3628. <title>Instance-Based Access Control List (ACL) Security</title>
  3629. <sect2 id="acls-overview">
  3630. <title>Overview</title>
  3631. <para>Complex applications often will find the need to define access
  3632. permissions not simply at a web request or method invocation level.
  3633. Instead, security decisions need to comprise both who
  3634. (<literal>Authentication</literal>), where
  3635. (<literal>MethodInvocation</literal>) and what
  3636. (<literal>SomeDomainObject</literal>). In other words, authorization
  3637. decisions also need to consider the actual domain object instance
  3638. subject of a method invocation.</para>
  3639. <para>Imagine you're designing an application for a pet clinic. There
  3640. will be two main groups of users of your Spring-based application:
  3641. staff of the pet clinic, as well as the pet clinic's customers. The
  3642. staff will have access to all of the data, whilst your customers will
  3643. only be able to see their own customer records. To make it a little
  3644. more interesting, your customers can allow other users to see their
  3645. customer records, such as their "puppy preschool "mentor or president
  3646. of their local "Pony Club". Using Acegi Security System for Spring as
  3647. the foundation, you have several approaches that can be
  3648. used:<orderedlist>
  3649. <listitem>
  3650. <para>Write your business methods to enforce the security. You
  3651. could consult a collection within the
  3652. <literal>Customer</literal> domain object instance to determine
  3653. which users have access. By using the
  3654. <literal>ContextHolder.getContext()</literal> and casting it to
  3655. <literal>SecureContext</literal>, you'll be able to access the
  3656. <literal>Authentication</literal> object.</para>
  3657. </listitem>
  3658. <listitem>
  3659. <para>Write an <literal>AccessDecisionVoter</literal> to enforce
  3660. the security from the <literal>GrantedAuthority[]</literal>s
  3661. stored in the <literal>Authentication</literal> object. This
  3662. would mean your <literal>AuthenticationManager</literal> would
  3663. need to populate the <literal>Authentication</literal> with
  3664. custom <literal>GrantedAuthority</literal>[]s representing each
  3665. of the <literal>Customer</literal> domain object instances the
  3666. principal has access to.</para>
  3667. </listitem>
  3668. <listitem>
  3669. <para>Write an <literal>AccessDecisionVoter</literal> to enforce
  3670. the security and open the target <literal>Customer</literal>
  3671. domain object directly. This would mean your voter needs access
  3672. to a DAO that allows it to retrieve the
  3673. <literal>Customer</literal> object. It would then access the
  3674. <literal>Customer</literal> object's collection of approved
  3675. users and make the appropriate decision.</para>
  3676. </listitem>
  3677. </orderedlist></para>
  3678. <para>Each one of these approaches is perfectly legitimate. However,
  3679. the first couples your authorization checking to your business code.
  3680. The main problems with this include the enhanced difficulty of unit
  3681. testing and the fact it would be more difficult to reuse the
  3682. <literal>Customer</literal> authorization logic elsewhere. Obtaining
  3683. the <literal>GrantedAuthority[]</literal>s from the
  3684. <literal>Authentication</literal> object is also fine, but will not
  3685. scale to large numbers of <literal>Customer</literal>s. If a user
  3686. might be able to access 5,000 <literal>Customer</literal>s (unlikely
  3687. in this case, but imagine if it were a popular vet for a large Pony
  3688. Club!) the amount of memory consumed and time required to construct
  3689. the <literal>Authentication</literal> object would be undesirable. The
  3690. final method, opening the <literal>Customer</literal> directly from
  3691. external code, is probably the best of the three. It achieves
  3692. separation of concerns, and doesn't misuse memory or CPU cycles, but
  3693. it is still inefficient in that both the
  3694. <literal>AccessDecisionVoter</literal> and the eventual business
  3695. method itself will perform a call to the DAO responsible for
  3696. retrieving the <literal>Customer</literal> object. Two accesses per
  3697. method invocation is clearly undesirable. In addition, with every
  3698. approach listed you'll need to write your own access control list
  3699. (ACL) persistence and business logic from scratch.</para>
  3700. <para>Fortunately, there is another alternative, which we'll talk
  3701. about below.</para>
  3702. </sect2>
  3703. <sect2 id="acls-acl-package">
  3704. <title>The net.sf.acegisecurity.acl Package</title>
  3705. <para>The <literal>net.sf.acegisecurity.acl</literal> package is very
  3706. simple, comprising only a handful of interfaces and a single class, as
  3707. shown in Figure 6. It provides the basic foundation for access control
  3708. list (ACL) lookups.</para>
  3709. <para><mediaobject>
  3710. <imageobject role="html">
  3711. <imagedata align="center" fileref="images/ACLSecurity.gif"
  3712. format="GIF" />
  3713. </imageobject>
  3714. <caption>
  3715. <para>Figure 6: Access Control List Manager</para>
  3716. </caption>
  3717. </mediaobject></para>
  3718. <para>The central interface is <literal>AclManager</literal>, which is
  3719. defined by two methods:</para>
  3720. <para><programlisting>public AclEntry[] getAcls(java.lang.Object domainInstance);
  3721. public AclEntry[] getAcls(java.lang.Object domainInstance, Authentication authentication);</programlisting></para>
  3722. <para><literal>AclManager</literal> is intended to be used as a
  3723. collaborator against your business objects, or, more desirably,
  3724. <literal>AccessDecisionVoter</literal>s. This means you use Spring's
  3725. normal <literal>ApplicationContext</literal> features to wire up your
  3726. <literal>AccessDecisionVoter</literal> (or business method) with an
  3727. <literal>AclManager</literal>. Consideration was given to placing the
  3728. ACL information in the <literal>ContextHolder</literal>, but it was
  3729. felt this would be inefficient both in terms of memory usage as well
  3730. as the time spent loading potentially unused ACL information. The
  3731. trade-off of needing to wire up a collaborator for those objects
  3732. requiring ACL information is rather minor, particularly in a
  3733. Spring-managed application.</para>
  3734. <para>The first method of the <literal>AclManager</literal> will
  3735. return all ACLs applying to the domain object instance passed to it.
  3736. The second method does the same, but only returns those ACLs which
  3737. apply to the passed <literal>Authentication</literal> object.</para>
  3738. <para>The <literal>AclEntry</literal> interface returned by
  3739. <literal>AclManager</literal> is merely a marker interface. You will
  3740. need to provide an implementation that reflects that ACL permissions
  3741. for your application.</para>
  3742. <para>Rounding out the <literal>net.sf.acegisecurity.acl</literal>
  3743. package is an <literal>AclProviderManager</literal> class, with a
  3744. corresponding <literal>AclProvider</literal> interface.
  3745. <literal>AclProviderManager</literal> is a concrete implementation of
  3746. <literal>AclManager</literal>, which iterates through registered
  3747. <literal>AclProvider</literal>s. The first
  3748. <literal>AclProvider</literal> that indicates it can authoritatively
  3749. provide ACL information for the presented domain object instance will
  3750. be used. This is very similar to the
  3751. <literal>AuthenticationProvider</literal> interface used for
  3752. authentication.</para>
  3753. <para>With this background, let's now look at a usable ACL
  3754. implementation.</para>
  3755. </sect2>
  3756. <sect2 id="acls-masking">
  3757. <title>Integer Masked ACLs</title>
  3758. <para>Acegi Security System for Spring includes a production-quality
  3759. ACL provider implementation, which is shown in Figure 7.</para>
  3760. <para><mediaobject>
  3761. <imageobject role="html">
  3762. <imagedata align="center" fileref="images/BasicAclProvider.gif"
  3763. format="GIF" />
  3764. </imageobject>
  3765. <caption>
  3766. <para>Figure 7: Basic ACL Manager</para>
  3767. </caption>
  3768. </mediaobject></para>
  3769. <para>The implementation is based on integer masking, which is
  3770. commonly used for ACL permissions given its flexibility and speed.
  3771. Anyone who has used Unix's <literal>chmod</literal> command will know
  3772. all about this type of permission masking (eg <literal>chmod
  3773. 777</literal>). You'll find the classes and interfaces for the integer
  3774. masking ACL package under
  3775. <literal>net.sf.acegisecurity.acl.basic</literal>.</para>
  3776. <para>Extending the <literal>AclEntry</literal> interface is a
  3777. <literal>BasicAclEntry</literal> interface, with the main methods
  3778. shown below:</para>
  3779. <para><programlisting>public AclObjectIdentity getAclObjectIdentity();
  3780. public AclObjectIdentity getAclObjectParentIdentity();
  3781. public int getMask();
  3782. public java.lang.Object getRecipient();</programlisting></para>
  3783. <para>As shown, each <literal>BasicAclEntry</literal> has four main
  3784. properties. The <literal>mask</literal> is the integer that represents
  3785. the permissions granted to the <literal>recipient</literal>. The
  3786. <literal>aclObjectIdentity</literal> is able to identify the domain
  3787. object instance for which the ACL applies, and the
  3788. <literal>aclObjectParentIdentity</literal> optionally specifies the
  3789. parent of the domain object instance. Multiple
  3790. <literal>BasicAclEntry</literal>s usually exist against a single
  3791. domain object instance, and as suggested by the parent identity
  3792. property, permissions granted higher in the object hierarchy will
  3793. trickle down and be inherited (unless blocked by integer zero).</para>
  3794. <para><literal>BasicAclEntry</literal> implementations typically
  3795. provide convenience methods, such as
  3796. <literal>isReadAllowed()</literal>, to avoid application classes
  3797. needing to perform bit masking themselves. The
  3798. <literal>SimpleAclEntry</literal> and
  3799. <literal>AbstractBasicAclEntry</literal> demonstrate and provide much
  3800. of this bit masking logic.</para>
  3801. <para>The <literal>AclObjectIdentity</literal> itself is merely a
  3802. marker interface, so you need to provide implementations for your
  3803. domain objects. However, the package does include a
  3804. <literal>NamedEntityObjectIdentity</literal> implementation which will
  3805. suit many needs. The <literal>NamedEntityObjectIdentity</literal>
  3806. identifies a given domain object instance by the classname of the
  3807. instance and the identity of the instance. A
  3808. <literal>NamedEntityObjectIdentity</literal> can be constructed
  3809. manually (by calling the constructor and providing the classname and
  3810. identity <literal>String</literal>s), or by passing in any domain
  3811. object that contains a <literal>getId()</literal> method.</para>
  3812. <para>The actual <literal>AclProvider</literal> implementation is
  3813. named <literal>BasicAclProvider</literal>. It has adopted a similar
  3814. design to that used by the authentication-related
  3815. <literal>DaoAuthenticationProvder</literal>. Specifically, you define
  3816. a <literal>BasicAclDao</literal> against the provider, so different
  3817. ACL repository types can be accessed in a pluggable manner. The
  3818. <literal>BasicAclProvider</literal> also supports pluggable cache
  3819. providers (with Acegi Security System for Spring including an
  3820. implementation that fronts EH-CACHE).</para>
  3821. <para>The <literal>BasicAclDao</literal> interface is very simple to
  3822. implement:</para>
  3823. <para><programlisting>public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity);</programlisting></para>
  3824. <para>A <literal>BasicAclDao</literal> implementation needs to
  3825. understand the presented <literal>AclObjectIdentity</literal> and how
  3826. it maps to a storage repository, find the relevant records, and create
  3827. appropriate <literal>BasicAclEntry</literal> objects and return
  3828. them.</para>
  3829. <para>Acegi Security includes a single <literal>BasicAclDao</literal>
  3830. implementation called <literal>JdbcDaoImpl</literal>. As implied by
  3831. the name, <literal>JdbcDaoImpl</literal> accesses ACL information from
  3832. a JDBC database. There is also an extended version of this DAO,
  3833. <literal>JdbcExtendedDaoImpl</literal>, which provides CRUD operations
  3834. on the JDBC database, although we won't discuss these features here.
  3835. The default database schema and some sample data will aid in
  3836. understanding its function:</para>
  3837. <para><programlisting>CREATE TABLE acl_object_identity (
  3838. id IDENTITY NOT NULL,
  3839. object_identity VARCHAR_IGNORECASE(250) NOT NULL,
  3840. parent_object INTEGER,
  3841. acl_class VARCHAR_IGNORECASE(250) NOT NULL,
  3842. CONSTRAINT unique_object_identity UNIQUE(object_identity),
  3843. FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id)
  3844. );
  3845. CREATE TABLE acl_permission (
  3846. id IDENTITY NOT NULL,
  3847. acl_object_identity INTEGER NOT NULL,
  3848. recipient VARCHAR_IGNORECASE(100) NOT NULL,
  3849. mask INTEGER NOT NULL,
  3850. CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient),
  3851. FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id)
  3852. );
  3853. INSERT INTO acl_object_identity VALUES (1, 'corp.DomainObject:1', null, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
  3854. INSERT INTO acl_object_identity VALUES (2, 'corp.DomainObject:2', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
  3855. INSERT INTO acl_object_identity VALUES (3, 'corp.DomainObject:3', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
  3856. INSERT INTO acl_object_identity VALUES (4, 'corp.DomainObject:4', 1, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
  3857. INSERT INTO acl_object_identity VALUES (5, 'corp.DomainObject:5', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
  3858. INSERT INTO acl_object_identity VALUES (6, 'corp.DomainObject:6', 3, 'net.sf.acegisecurity.acl.basic.SimpleAclEntry');
  3859. INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1);
  3860. INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0);
  3861. INSERT INTO acl_permission VALUES (null, 2, 'marissa', 2);
  3862. INSERT INTO acl_permission VALUES (null, 3, 'scott', 14);
  3863. INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
  3864. <para>As can be seen, database-specific constraints are used
  3865. extensively to ensure the integrity of the ACL information. If you
  3866. need to use a different database (Hypersonic SQL statements are shown
  3867. above), you should try to implement equivalent constraints.</para>
  3868. <para>The <literal>JdbcDaoImpl</literal> will only respond to requests
  3869. for <literal>NamedEntityObjectIdentity</literal>s. It converts such
  3870. identities into a single <literal>String</literal>, comprising
  3871. the<literal> NamedEntityObjectIdentity.getClassname()</literal> +
  3872. <literal>":"</literal> +
  3873. <literal>NamedEntityObjectIdentity.getId()</literal>. This yields the
  3874. type of <literal>object_identity</literal> values shown above. As
  3875. indicated by the sample data, each database row corresponds to a
  3876. single <literal>BasicAclEntry</literal>. As stated earlier and
  3877. demonstrated by <literal>corp.DomainObject:2</literal> in the above
  3878. sample data, each domain object instance will often have multiple
  3879. <literal>BasicAclEntry</literal>[]s.</para>
  3880. <para>As <literal>JdbcDaoImpl</literal> is required to return concrete
  3881. <literal>BasicAclEntry</literal> classes, it needs to know which
  3882. <literal>BasicAclEntry</literal> implementation it is to create and
  3883. populate. This is the role of the <literal>acl_class</literal> column.
  3884. <literal>JdbcDaoImpl</literal> will create the indicated class and set
  3885. its <literal>mask</literal>, <literal>recipient</literal>,
  3886. <literal>aclObjectIdentity</literal> and
  3887. <literal>aclObjectParentIdentity</literal> properties.</para>
  3888. <para>As you can probably tell from the sample data, the
  3889. <literal>parent_object_identity</literal> value can either be null or
  3890. in the same format as the <literal>object_identity</literal>. If
  3891. non-null, <literal>JdbcDaoImpl</literal> will create a
  3892. <literal>NamedEntityObjectIdentity</literal> to place inside the
  3893. returned <literal>BasicAclEntry</literal> class.</para>
  3894. <para>Returning to the <literal>BasicAclProvider</literal>, before it
  3895. can poll the <literal>BasicAclDao</literal> implementation it needs to
  3896. convert the domain object instance it was passed into an
  3897. <literal>AclObjectIdentity</literal>.
  3898. <literal>BasicAclProvider</literal> has a <literal>protected
  3899. AclObjectIdentity obtainIdentity(Object domainInstance)</literal>
  3900. method that is responsible for this. As a protected method, it enables
  3901. subclasses to easily override. The normal implementation checks
  3902. whether the passed domain object instance implements the
  3903. <literal>AclObjectIdentityAware</literal> interface, which is merely a
  3904. getter for an <literal>AclObjectIdentity</literal>. If the domain
  3905. object does implement this interface, that is the identity returned.
  3906. If the domain object does not implement this interface, the method
  3907. will attempt to create an <literal>AclObjectIdentity</literal> by
  3908. passing the domain object instance to the constructor of a class
  3909. defined by the
  3910. <literal>BasicAclProvider.getDefaultAclObjectIdentity()</literal>
  3911. method. By default the defined class is
  3912. <literal>NamedEntityObjectIdentity</literal>, which was described in
  3913. more detail above. Therefore, you will need to either (i) provide a
  3914. <literal>getId()</literal> method on your domain objects, (ii)
  3915. implement <literal>AclObjectIdentityAware</literal> on your domain
  3916. objects, (iii) provide an alternative
  3917. <literal>AclObjectIdentity</literal> implementation that will accept
  3918. your domain object in its constructor, or (iv) override the
  3919. <literal>obtainIdentity(Object)</literal> method.</para>
  3920. <para>Once the <literal>AclObjectIdentity</literal> of the domain
  3921. object instance is determined, the <literal>BasicAclProvider</literal>
  3922. will poll the DAO to obtain its <literal>BasicAclEntry</literal>[]s.
  3923. If any of the entries returned by the DAO indicate there is a parent,
  3924. that parent will be polled, and the process will repeat until there is
  3925. no further parent. The permissions assigned to a
  3926. <literal>recipient</literal> closest to the domain object instance
  3927. will always take priority and override any inherited permissions. From
  3928. the sample data above, the following inherited permissions would
  3929. apply:</para>
  3930. <para><programlisting>--- Mask integer 0 = no permissions
  3931. --- Mask integer 1 = administer
  3932. --- Mask integer 2 = read
  3933. --- Mask integer 6 = read and write permissions
  3934. --- Mask integer 14 = read and write and create permissions
  3935. ---------------------------------------------------------------------
  3936. --- *** INHERITED RIGHTS FOR DIFFERENT INSTANCES AND RECIPIENTS ***
  3937. --- INSTANCE RECIPIENT PERMISSION(S) (COMMENT #INSTANCE)
  3938. ---------------------------------------------------------------------
  3939. --- 1 ROLE_SUPERVISOR Administer
  3940. --- 2 ROLE_SUPERVISOR None (overrides parent #1)
  3941. --- marissa Read
  3942. --- 3 ROLE_SUPERVISOR Administer (from parent #1)
  3943. --- scott Read, Write, Create
  3944. --- 4 ROLE_SUPERVISOR Administer (from parent #1)
  3945. --- 5 ROLE_SUPERVISOR Administer (from parent #3)
  3946. --- scott Read, Write, Create (from parent #3)
  3947. --- 6 ROLE_SUPERVISOR Administer (from parent #3)
  3948. --- scott Administer (overrides parent #3)</programlisting></para>
  3949. <para>So the above explains how a domain object instance has its
  3950. <literal>AclObjectIdentity</literal> discovered, and the
  3951. <literal>BasicAclDao</literal> will be polled successively until an
  3952. array of inherited permissions is constructed for the domain object
  3953. instance. The final step is to determine the
  3954. <literal>BasicAclEntry</literal>[]s that are actually applicable to a
  3955. given <literal>Authentication</literal> object.</para>
  3956. <para>As you would recall, the <literal>AclManager</literal> (and all
  3957. delegates, up to and including <literal>BasicAclProvider</literal>)
  3958. provides a method which returns only those
  3959. <literal>BasicAclEntry</literal>[]s applying to a passed
  3960. <literal>Authentication</literal> object.
  3961. <literal>BasicAclProvider</literal> delivers this functionality by
  3962. delegating the filtering operation to an
  3963. <literal>EffectiveAclsResolver</literal> implementation. The default
  3964. implementation,
  3965. <literal>GrantedAuthorityEffectiveAclsResolver</literal>, will iterate
  3966. through the <literal>BasicAclEntry</literal>[]s and include only those
  3967. where the <literal>recipient</literal> is equal to either the
  3968. <literal>Authentication</literal>'s <literal>principal</literal> or
  3969. any of the <literal>Authentication</literal>'s
  3970. <literal>GrantedAuthority</literal>[]s. Please refer to the JavaDocs
  3971. for more information.</para>
  3972. <mediaobject>
  3973. <imageobject role="html">
  3974. <imagedata align="center" fileref="images/Permissions.gif"
  3975. format="GIF" />
  3976. </imageobject>
  3977. <caption>
  3978. <para>Figure 8: ACL Instantiation Approach</para>
  3979. </caption>
  3980. </mediaobject>
  3981. </sect2>
  3982. <sect2 id="acls-conclusion">
  3983. <title>Conclusion</title>
  3984. <para>Acegi Security's instance-specific ACL packages shield you from
  3985. much of the complexity of developing your own ACL approach. The
  3986. interfaces and classes detailed above provide a scalable, customisable
  3987. ACL solution that is decoupled from your application code. Whilst the
  3988. reference documentation may suggest complexity, the basic
  3989. implementation is able to support most typical applications
  3990. out-of-the-box.</para>
  3991. </sect2>
  3992. </sect1>
  3993. <sect1 id="security-filters">
  3994. <title>Filters</title>
  3995. <sect2 id="security-filters-overview">
  3996. <title>Overview</title>
  3997. <para>The Acegi Security System for Spring uses filters extensively.
  3998. Each filter is covered in detail in a respective section of this
  3999. document. This section includes information that applies to all
  4000. filters.</para>
  4001. </sect2>
  4002. <sect2 id="security-filters-filtertobeanproxy">
  4003. <title>FilterToBeanProxy</title>
  4004. <para>Most filters are configured using the
  4005. <literal>FilterToBeanProxy</literal>. An example configuration from
  4006. <literal>web.xml</literal> follows:</para>
  4007. <para><programlisting>&lt;filter&gt;
  4008. &lt;filter-name&gt;Acegi HTTP Request Security Filter&lt;/filter-name&gt;
  4009. &lt;filter-class&gt;net.sf.acegisecurity.util.FilterToBeanProxy&lt;/filter-class&gt;
  4010. &lt;init-param&gt;
  4011. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  4012. &lt;param-value&gt;net.sf.acegisecurity.ClassThatImplementsFilter&lt;/param-value&gt;
  4013. &lt;/init-param&gt;
  4014. &lt;/filter&gt;</programlisting></para>
  4015. <para>Notice that the filter in <literal>web.xml</literal> is actually
  4016. a <literal>FilterToBeanProxy</literal>, and not the filter that will
  4017. actually implements the logic of the filter. What
  4018. <literal>FilterToBeanProxy</literal> does is delegate the
  4019. <literal>Filter</literal>'s methods through to a bean which is
  4020. obtained from the Spring application context. This enables the bean to
  4021. benefit from the Spring application context lifecycle support and
  4022. configuration flexibility. The bean must implement
  4023. <literal>javax.servlet.Filter</literal>.</para>
  4024. <para>The <literal>FilterToBeanProxy</literal> only requires a single
  4025. initialization parameter, <literal>targetClass</literal> or
  4026. <literal>targetBean</literal>. The <literal>targetClass</literal>
  4027. parameter locates the first object in the application context of the
  4028. specified class, whilst <literal>targetBean</literal> locates the
  4029. object by bean name. Like standard Spring web applications, the
  4030. <literal>FilterToBeanProxy</literal> accesses the application context
  4031. via<literal>
  4032. WebApplicationContextUtils.getWebApplicationContext(ServletContext)</literal>,
  4033. so you should configure a <literal>ContextLoaderListener</literal> in
  4034. <literal>web.xml</literal>.</para>
  4035. <para>There is a lifecycle issue to consider when hosting
  4036. <literal>Filter</literal>s in an IoC container instead of a servlet
  4037. container. Specifically, which container should be responsible for
  4038. calling the <literal>Filter</literal>'s "startup" and "shutdown"
  4039. methods? It is noted that the order of initialization and destruction
  4040. of a <literal>Filter</literal> can vary by servlet container, and this
  4041. can cause problems if one <literal>Filter</literal> depends on
  4042. configuration settings established by an earlier initialized
  4043. <literal>Filter</literal>. The Spring IoC container on the other hand
  4044. has more comprehensive lifecycle/IoC interfaces (such as
  4045. <literal>InitializingBean</literal>,
  4046. <literal>DisposableBean</literal>, <literal>BeanNameAware</literal>,
  4047. <literal>ApplicationContextAware</literal> and many others) as well as
  4048. a well-understood interface contract, predictable method invocation
  4049. ordering, autowiring support, and even options to avoid implementing
  4050. Spring interfaces (eg the <literal>destroy-method</literal> attribute
  4051. in Spring XML). For this reason we recommend the use of Spring
  4052. lifecycle services instead of servlet container lifecycle services
  4053. wherever possible. By default <literal>FilterToBeanProxy</literal>
  4054. will not delegate <literal>init(FilterConfig)</literal> and
  4055. <literal>destroy()</literal> methods through to the proxied bean. If
  4056. you do require such invocations to be delegated, set the
  4057. <literal>lifecycle</literal> initialization parameter to
  4058. <literal>servlet-container-managed</literal>.</para>
  4059. </sect2>
  4060. <sect2 id="security-filters-filterchainproxy">
  4061. <title>FilterChainProxy</title>
  4062. <para>Whilst <literal>FilterToBeanProxy</literal> is a very useful
  4063. class, the problem is that the lines of code required for
  4064. <literal>&lt;filter&gt;</literal> and
  4065. <literal>&lt;filter-mapping&gt;</literal> entries in
  4066. <literal>web.xml</literal> explodes when using more than a few
  4067. filters. To overcome this issue, Acegi Security provides a
  4068. <literal>FilterChainProxy</literal> class. It is wired using a
  4069. <literal>FilterToBeanProxy</literal> (just like in the example above),
  4070. but the target class is
  4071. <literal>net.sf.acegisecurity.util.FilterChainProxy</literal>. The
  4072. filter chain is then declared in the application context, using code
  4073. such as this:</para>
  4074. <para><programlisting>&lt;bean id="filterChainProxy" class="net.sf.acegisecurity.util.FilterChainProxy"&gt;
  4075. &lt;property name="filterInvocationDefinitionSource"&gt;
  4076. &lt;value&gt;
  4077. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  4078. PATTERN_TYPE_APACHE_ANT
  4079. /webServices/**=httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,securityEnforcementFilter
  4080. /**=httpSessionContextIntegrationFilterWithASCTrue,authenticationProcessingFilter,securityEnforcementFilter
  4081. &lt;/value&gt;
  4082. &lt;/property&gt;
  4083. &lt;/bean&gt;</programlisting></para>
  4084. <para>You may notice similarities with the way
  4085. <literal>SecurityEnforcementFilter</literal> is declared. Both regular
  4086. expressions and Ant Paths are supported, and the most specific URIs
  4087. appear first. At runtime the <literal>FilterChainProxy</literal> will
  4088. locate the first URI pattern that matches the current web request.
  4089. Each of the corresponding configuration attributes represent the name
  4090. of a bean defined in the application context. The filters will then be
  4091. invoked in the order they are specified, with standard
  4092. <literal>FilterChain</literal> behaviour being respected (a
  4093. <literal>Filter</literal> can elect not to proceed with the chain if
  4094. it wishes to end processing).</para>
  4095. <para>As you can see, <literal>FitlerChainProxy</literal> requires the
  4096. duplication of filter names for different request patterns (in the
  4097. above example, <literal>httpSessionContextIntegrationFilter</literal>
  4098. and <literal>securityEnforcementFilter</literal> are duplicated). This
  4099. design decision was made to enable <literal>FilterChainProxy</literal>
  4100. to specify different <literal>Filter</literal> invocation orders for
  4101. different URI patterns, and also to improve both the expressiveness
  4102. (in terms of regular expressions, Ant Paths, and any custom
  4103. <literal>FilterInvocationDefinitionSource</literal> implementations)
  4104. and clarity of which <literal>Filter</literal>s should be
  4105. invoked.</para>
  4106. <para>You may have noticed we have declared two
  4107. <literal>HttpSessionContextIntegrationFilter</literal>s in the filter
  4108. chain (<literal>ASC</literal> is short for
  4109. <literal>allowSessionCreation</literal>, a property of
  4110. <literal>HttpSessionContextIntegrationFilter</literal>). As web
  4111. services will never present a <literal>jsessionid</literal> on future
  4112. requests, creating <literal>HttpSession</literal>s for such user
  4113. agents would be wasteful. If you had a high-volume application which
  4114. required maximum scalability, we recommend you use the approach shown
  4115. above. For smaller applications, using a single
  4116. <literal>HttpSessionContextIntegrationFilter</literal> (with its
  4117. default <literal>allowSessionCreation</literal> as
  4118. <literal>true</literal>) would likely be sufficient.</para>
  4119. <para>In relation to lifecycle issues, the
  4120. <literal>FilterChainProxy</literal> will always delegate
  4121. <literal>init(FilterConfig)</literal> and <literal>destroy()</literal>
  4122. methods through to the underlaying <literal>Filter</literal>s if such
  4123. methods are called against <literal>FilterChainProxy</literal> itself.
  4124. In this case, <literal>FilterChainProxy</literal> guarantees to only
  4125. initialize and destroy each <literal>Filter</literal> once,
  4126. irrespective of how many times it is declared by the
  4127. <literal>FilterInvocationDefinitionSource</literal>. You control the
  4128. overall choice as to whether these methods are called or not via the
  4129. <literal>lifecycle</literal> initialization parameter of the
  4130. <literal>FilterToBeanProxy</literal> that proxies
  4131. <literal>FilterChainProxy</literal>. As discussed above, by default
  4132. any servlet container lifecycle invocations are not delegated through
  4133. to <literal>FilterChainProxy</literal>.</para>
  4134. </sect2>
  4135. <sect2 id="security-filters-order">
  4136. <title>Filter Ordering</title>
  4137. <para>The order that filters are defined in <literal>web.xml</literal>
  4138. is important. NB: THE FILTER ORDER CHANGED FROM VERSION 0.8.0.</para>
  4139. <para>Irrespective of which filters you are actually using, the order
  4140. of the <literal>&lt;filter-mapping&gt;</literal>s should be as
  4141. follows:</para>
  4142. <orderedlist>
  4143. <listitem>
  4144. <para><literal>ChannelProcessingFilter</literal>, because it might
  4145. need to redirect to a different protocol</para>
  4146. </listitem>
  4147. <listitem>
  4148. <para><literal>HttpSessionContextIntegrationFilter</literal>, so a
  4149. <literal>Context</literal> can be setup in the
  4150. <literal>ContextHolder</literal> at the beginning of a web
  4151. request, and any changes to the Context can be copied to the
  4152. <literal>HttpSession</literal> when the web request ends (ready
  4153. for use with the next web request)</para>
  4154. </listitem>
  4155. <listitem>
  4156. <para>Authentication processing mechanisms -
  4157. <literal>AuthenticationProcessingFilter</literal>,
  4158. <literal>CasProcessingFilter</literal>,
  4159. <literal>BasicProcessingFilter, HttpRequestIntegrationFilter,
  4160. JbossIntegrationFilter</literal> etc - so that the
  4161. <literal>ContextHolder</literal> can be modified to contain a
  4162. valid <literal>Authentication</literal> request token</para>
  4163. </listitem>
  4164. <listitem>
  4165. <para>The <literal>ContextHolderAwareRequestFilter</literal>, if
  4166. you are using it to install an Acegi Security aware
  4167. <literal>HttpServletRequestWrapper</literal> into your servlet
  4168. container</para>
  4169. </listitem>
  4170. <listitem>
  4171. <para><literal>RememberMeProcessingFilter</literal>, so that if no
  4172. earlier authentication processing mechanism updated the
  4173. <literal>ContextHolder</literal>, and the request presents a
  4174. cookie that enables remember-me services to take place, a suitable
  4175. remembered <literal><literal>Authentication</literal></literal>
  4176. object will be put there</para>
  4177. </listitem>
  4178. <listitem>
  4179. <para><literal>AnonymousProcessingFilter</literal>, so that if no
  4180. earlier authentication processing mechanism updated the
  4181. <literal>ContextHolder</literal>, an anonymous
  4182. <literal>Authentication</literal> object will be put there</para>
  4183. </listitem>
  4184. <listitem>
  4185. <para><literal>SecurityEnforcementFilter</literal>, to protect web
  4186. URIs and catch any Acegi Security exceptions so that an
  4187. appropriate <literal>AuthenticationEntryPoint</literal> can be
  4188. launched</para>
  4189. </listitem>
  4190. </orderedlist>
  4191. <para>All of the above filters use
  4192. <literal>FilterToBeanProxy</literal> or
  4193. <literal>FilterChainProxy</literal>, which is discussed in the
  4194. previous sections. It is recommended that a single
  4195. <literal>FilterToBeProxy</literal> proxy through to a single
  4196. <literal>FilterChainProxy</literal> for each application, with that
  4197. <literal>FilterChainProxy</literal> defining all of the Acegi Security
  4198. <literal>Filter</literal>s.</para>
  4199. <para>If you're using SiteMesh, ensure the Acegi Security filters
  4200. execute before the SiteMesh filters are called. This enables the
  4201. <literal>ContextHolder</literal> to be populated in time for use by
  4202. SiteMesh decorators.</para>
  4203. </sect2>
  4204. </sect1>
  4205. <sect1 id="security-sample">
  4206. <title>Contacts Sample Application</title>
  4207. <para>Included with the Acegi Security System for Spring is a very
  4208. simple application that can demonstrate the basic security facilities
  4209. provided by the system (and confirm your Container Adapter is properly
  4210. configured if you're using one).</para>
  4211. <para>If you build from CVS, the Contacts sample application includes
  4212. three deployable versions:
  4213. <literal>acegi-security-sample-contacts-filter.war</literal> is
  4214. configured with the HTTP Session Authentication approach. The
  4215. <literal><literal>acegi-security-sample-contacts-ca.war</literal></literal>
  4216. is configured to use a Container Adapter. Finally,
  4217. <literal>acegi-security-sample-contacts-cas.war</literal> is designed to
  4218. work with a Yale CAS server. If you're just wanting to see how the
  4219. sample application works, please use
  4220. <literal><literal>acegi-security-sample-contacts-filter.war</literal></literal>
  4221. as it does not require special configuration of your container. This is
  4222. also the artifact included in ofiical release ZIPs.</para>
  4223. <para>To deploy, simply copy the relevant WAR file from the Acegi
  4224. Security System for Spring distribution into your container’s
  4225. <literal>webapps</literal> directory.</para>
  4226. <para>After starting your container, check the application can load.
  4227. Visit
  4228. <literal>http://localhost:</literal><literal><literal>8080/</literal>acegi-security-sample-contacts-filter</literal>
  4229. (or whichever URL is appropriate for your web container and the WAR you
  4230. deployed). A random contact should be displayed. Click "Refresh" several
  4231. times and you will see different contacts. The business method that
  4232. provides this random contact is not secured.</para>
  4233. <para>Next, click "Debug". You will be prompted to authenticate, and a
  4234. series of usernames and passwords are suggested on that page. Simply
  4235. authenticate with any of these and view the resulting page. It should
  4236. contain a success message similar to the following:</para>
  4237. <blockquote>
  4238. <para>Context on ContextHolder is of type:
  4239. net.sf.acegisecurity.context.secure.SecureContextImpl</para>
  4240. <para>The Context implements SecureContext.</para>
  4241. <para>Authentication object is of type:
  4242. net.sf.acegisecurity.adapters.PrincipalAcegiUserToken</para>
  4243. <para>Authentication object as a String:
  4244. net.sf.acegisecurity.adapters.PrincipalAcegiUserToken@e9a7c2:
  4245. Username: marissa; Password: [PROTECTED]; Authenticated: true; Granted
  4246. Authorities: ROLE_TELLER, ROLE_SUPERVISOR</para>
  4247. <para>Authentication object holds the following granted
  4248. authorities:</para>
  4249. <para>ROLE_TELLER (getAuthority(): ROLE_TELLER)</para>
  4250. <para>ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR)</para>
  4251. <para>SUCCESS! Your [container adapter|web filter] appears to be
  4252. properly configured!</para>
  4253. </blockquote>
  4254. <para>If you receive a different message, and deployed
  4255. <literal>acegi-security-sample-contacts-ca.war</literal>, check you have
  4256. properly configured your Container Adapter as described elsewhere in
  4257. this reference guide.</para>
  4258. <para>Once you successfully receive the above message, return to the
  4259. sample application's home page and click "Manage". You can then try out
  4260. the application. Notice that only the contacts available to the
  4261. currently logged on user are displayed, and only users with
  4262. <literal>ROLE_SUPERVISOR</literal> are granted access to delete their
  4263. contacts. Behind the scenes, the
  4264. <literal>MethodSecurityInterceptor</literal> is securing the business
  4265. objects. If you're using
  4266. <literal><literal>acegi-security-sample-contacts-filter.war</literal></literal>
  4267. or <literal>acegi-security-sample-contacts-cas.war</literal>, the
  4268. <literal>FilterSecurityInterceptor</literal> is also securing the HTTP
  4269. requests. If using either of these WARs, be sure to try visiting
  4270. <literal>http://localhost:8080/contacts/secure/super</literal>, which
  4271. will demonstrate access being denied by the
  4272. <literal>SecurityEnforcementFilter</literal>. Note the sample
  4273. application enables you to modify the access control lists associated
  4274. with different contacts. Be sure to give this a try and understand how
  4275. it works by reviewing the sample application's application context XML
  4276. files.</para>
  4277. <para>The Contacts sample application also include a
  4278. <literal>client</literal> directory. Inside you will find a small
  4279. application that queries the backend business objects using several web
  4280. services protocols. This demonstrates how to use the Acegi Security
  4281. System for Spring for authentication with Spring remoting protocols. To
  4282. try this client, ensure your servlet container is still running the
  4283. Contacts sample application, and then execute <literal>client marissa
  4284. koala</literal>. The command-line parameters respectively represent the
  4285. username to use, and the password to use. Note that you may need to edit
  4286. <literal>client.properties</literal> to use a different target
  4287. URL.</para>
  4288. <para>Please note the sample application's <literal>client</literal>
  4289. does not currently support CAS. You can still give it a try, though, if
  4290. you're ambitious: try <literal>client _cas_stateless_
  4291. YOUR-SERVICE-TICKET-ID</literal>.</para>
  4292. </sect1>
  4293. <sect1 id="security-become-involved">
  4294. <title>Become Involved</title>
  4295. <para>We welcome you to become involved in the Acegi Security System for
  4296. Spring project. There are many ways of contributing, including reading
  4297. the mailing list and responding to questions from other people, writing
  4298. new code, improving existing code, assisting with documentation, or
  4299. simply making suggestions.</para>
  4300. <para>SourceForge provides CVS services for the project, allowing
  4301. anybody to access the latest code. If you wish to contribute new code,
  4302. please observe the following requirements. These exist to maintain the
  4303. quality and consistency of the project:</para>
  4304. <itemizedlist>
  4305. <listitem>
  4306. <para>Use a suitable IDE Jalopy plug-in to convert your code into
  4307. the project's consistent style</para>
  4308. </listitem>
  4309. <listitem>
  4310. <para>Ensure your code does not break any unit tests (run the Maven
  4311. <literal>test:test</literal> goal)</para>
  4312. </listitem>
  4313. <listitem>
  4314. <para>If you have added new code, please provide suitable unit tests
  4315. (use the Maven <literal>clover:html-report</literal> to view
  4316. coverage)</para>
  4317. </listitem>
  4318. <listitem>
  4319. <para>Join the acegisecurity-developer and acegisecurity-cvs mailing
  4320. lists so you're in the loop</para>
  4321. </listitem>
  4322. <listitem>
  4323. <para>Use CamelCase</para>
  4324. </listitem>
  4325. <listitem>
  4326. <para>Add a CVS <literal>$Id: index.xml,v 1.3 2004/04/02 21:12:25
  4327. fbos Exp $</literal> tag to the JavaDocs for any new class you
  4328. create</para>
  4329. </listitem>
  4330. </itemizedlist>
  4331. </sect1>
  4332. <sect1 id="security-further">
  4333. <title>Further Information</title>
  4334. <para>Questions and comments on the Acegi Security System for Spring are
  4335. welcome. Please use the Spring Community Forum web site at
  4336. <literal>http://forum.springframework.org</literal>. You're also welcome
  4337. to join the acegisecurity-developer mailing list. Our project home page
  4338. (where you can obtain the latest release of the project and access to
  4339. CVS, mailing lists, forums etc) is at
  4340. <literal>http://acegisecurity.sourceforge.net</literal>.</para>
  4341. </sect1>
  4342. </chapter>
  4343. </book>