springsecurity.xml 333 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466
  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>Spring Security</title>
  26. <subtitle>Reference Documentation</subtitle>
  27. <releaseinfo>2.0-SNAPSHOT</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>Spring Security provides a comprehensive security solution for
  39. J2EE-based enterprise software applications. As you will discover as you
  40. venture through this reference guide, we have tried to provide you a
  41. useful and highly configurable security system.</para>
  42. <para>Security is an ever-moving target, and it's important to pursue a
  43. comprehensive, system-wide approach. In security circles we encourage you
  44. to adopt "layers of security", so that each layer tries to be as secure as
  45. possible in its own right, with successive layers providing additional
  46. security. The "tighter" the security of each layer, the more robust and
  47. safe your application will be. At the bottom level you'll need to deal
  48. with issues such as transport security and system identification, in order
  49. to mitigate man-in-the-middle attacks. Next you'll generally utilise
  50. firewalls, perhaps with VPNs or IP security to ensure only authorised
  51. systems can attempt to connect. In corporate environments you may deploy a
  52. DMZ to separate public-facing servers from backend database and
  53. application servers. Your operating system will also play a critical part,
  54. addressing issues such as running processes as non-privileged users and
  55. maximising file system security. An operating system will usually also be
  56. configured with its own firewall. Hopefully somewhere along the way you'll
  57. be trying to prevent denial of service and brute force attacks against the
  58. system. An intrusion detection system will also be especially useful for
  59. monitoring and responding to attacks, with such systems able to take
  60. protective action such as blocking offending TCP/IP addresses in
  61. real-time. Moving to the higher layers, your Java Virtual Machine will
  62. hopefully be configured to minimize the permissions granted to different
  63. Java types, and then your application will add its own problem
  64. domain-specific security configuration. Spring Security makes this latter
  65. area - application security - much easier.</para>
  66. <para>Of course, you will need to properly address all security layers
  67. mentioned above, together with managerial factors that encompass every
  68. layer. A non-exhaustive list of such managerial factors would include
  69. security bulletin monitoring, patching, personnel vetting, audits, change
  70. control, engineering management systems, data backup, disaster recovery,
  71. performance benchmarking, load monitoring, centralised logging, incident
  72. response procedures etc.</para>
  73. <para>With Spring Security being focused on helping you with the
  74. enterprise application security layer, you will find that there are as
  75. many different requirements as there are business problem domains. A
  76. banking application has different needs from an ecommerce application. An
  77. ecommerce application has different needs from a corporate sales force
  78. automation tool. These custom requirements make application security
  79. interesting, challenging and rewarding.</para>
  80. <para>This reference guide has been largely restructured for the 1.0.0
  81. release of Spring Security (then called Acegi Security). Please read Part
  82. I, <link linkend="overall-architecture">Overall Architecture</link>, in
  83. its entirety. The remaining parts of the reference guide are structured in
  84. a more traditional reference style, designed to be read on an as-required
  85. basis.</para>
  86. <para>We hope that you find this reference guide useful, and we welcome
  87. your feedback and <link linkend="jira">suggestions</link>.</para>
  88. <para>Finally, welcome to the Spring Security <link
  89. linkend="community">community</link>.</para>
  90. </preface>
  91. <part id="overall-architecture">
  92. <title>Overall Architecture</title>
  93. <partintro>
  94. <para>Like most software, Spring Security has certain central
  95. interfaces, classes and conceptual abstractions that are commonly used
  96. throughout the framework. In this part of the reference guide we will
  97. introduce Spring Security, before examining these central elements that
  98. are necessary to successfully planning and executing a Spring Security
  99. integration.</para>
  100. </partintro>
  101. <chapter id="introduction">
  102. <title>Introduction</title>
  103. <sect1 id="what-is-acegi-security">
  104. <title>What is Spring Security?</title>
  105. <para>Spring Security provides comprehensive security services for
  106. J2EE-based enterprise software applications. There is a particular
  107. emphasis on supporting projects built using The Spring Framework,
  108. which is the leading J2EE solution for enterprise software
  109. development. If you're not using Spring for developing enterprise
  110. applications, we warmly encourage you to take a closer look at it.
  111. Some familiarity with Spring - and in particular dependency injection
  112. principles - will help you get up to speed with Spring Security more
  113. easily.</para>
  114. <para>People use Spring Security for many reasons, but most are drawn
  115. to the project after finding the security features of J2EE's Servlet
  116. Specification or EJB Specification lack the depth required for typical
  117. enterprise application scenarios. Whilst mentioning these standards,
  118. it's important to recognise that they are not portable at a WAR or EAR
  119. level. Therefore, if you switch server environments, it is typically a
  120. lot of work to reconfigure your application's security in the new
  121. target environment. Using Spring Security overcomes these problems,
  122. and also brings you dozens of other useful, entirely customisable
  123. security features.</para>
  124. <para>As you probably know, security comprises two major operations.
  125. The first is known as "authentication", which is the process of
  126. establishing a principal is who they claim to be. A "principal"
  127. generally means a user, device or some other system which can perform
  128. an action in your application. "Authorization" refers to the process
  129. of deciding whether a principal is allowed to perform an action in
  130. your application. To arrive at the point where an authorization
  131. decision is needed, the identity of the principal has already been
  132. established by the authentication process. These concepts are common,
  133. and not at all specific to Spring Security.</para>
  134. <para>At an authentication level, Spring Security supports a wide
  135. range of authentication models. Most of these authentication models
  136. are either provided by third parties, or are developed by relevant
  137. standards bodies such as the Internet Engineering Task Force. In
  138. addition, Spring Security provides its own set of authentication
  139. features. Specifically, Spring Security currently supports
  140. authentication integration with all of these technologies:</para>
  141. <itemizedlist spacing="compact">
  142. <listitem>
  143. <para>HTTP BASIC authentication headers (an IEFT RFC-based
  144. standard)</para>
  145. </listitem>
  146. <listitem>
  147. <para>HTTP Digest authentication headers (an IEFT RFC-based
  148. standard)</para>
  149. </listitem>
  150. <listitem>
  151. <para>HTTP X.509 client certificate exchange (an IEFT RFC-based
  152. standard)</para>
  153. </listitem>
  154. <listitem>
  155. <para>LDAP (a very common approach to cross-platform
  156. authentication needs, especially in large environments)</para>
  157. </listitem>
  158. <listitem>
  159. <para>Form-based authentication (for simple user interface
  160. needs)</para>
  161. </listitem>
  162. <listitem>
  163. <para>Computer Associates Siteminder</para>
  164. </listitem>
  165. <listitem>
  166. <para>JA-SIG Central Authentication Service (otherwise known as
  167. CAS, which is a popular open source single sign on system)</para>
  168. </listitem>
  169. <listitem>
  170. <para>Transparent authentication context propagation for Remote
  171. Method Invocation (RMI) and HttpInvoker (a Spring remoting
  172. protocol)</para>
  173. </listitem>
  174. <listitem>
  175. <para>Automatic "remember-me" authentication (so you can tick a
  176. box to avoid re-authentication for a predetermined period of
  177. time)</para>
  178. </listitem>
  179. <listitem>
  180. <para>Anonymous authentication (allowing every call to
  181. automatically assume a particular security identity)</para>
  182. </listitem>
  183. <listitem>
  184. <para>Run-as authentication (which is useful if one call should
  185. proceed with a different security identity)</para>
  186. </listitem>
  187. <listitem>
  188. <para>Java Authentication and Authorization Service (JAAS)</para>
  189. </listitem>
  190. <listitem>
  191. <para>Container integration with JBoss, Jetty, Resin and Tomcat
  192. (so you can still use Container Manager Authentication if
  193. desired)</para>
  194. </listitem>
  195. <listitem>
  196. <para>Java Open Source Single Sign On (JOSSO) *</para>
  197. </listitem>
  198. <listitem>
  199. <para>OpenNMS Network Management Platform *</para>
  200. </listitem>
  201. <listitem>
  202. <para>AppFuse *</para>
  203. </listitem>
  204. <listitem>
  205. <para>AndroMDA *</para>
  206. </listitem>
  207. <listitem>
  208. <para>Mule ESB *</para>
  209. </listitem>
  210. <listitem>
  211. <para>Direct Web Request (DWR) *</para>
  212. </listitem>
  213. <listitem>
  214. <para>Grails *</para>
  215. </listitem>
  216. <listitem>
  217. <para>Tapestry *</para>
  218. </listitem>
  219. <listitem>
  220. <para>JTrac *</para>
  221. </listitem>
  222. <listitem>
  223. <para>Jasypt *</para>
  224. </listitem>
  225. <listitem>
  226. <para>Roller *</para>
  227. </listitem>
  228. <listitem>
  229. <para>Elastic Plath *</para>
  230. </listitem>
  231. <listitem>
  232. <para>Atlassian Crowd *</para>
  233. </listitem>
  234. <listitem>
  235. <para>Your own authentication systems (see below)</para>
  236. </listitem>
  237. </itemizedlist>
  238. <para>(* Denotes provided by a third party; check our <ulink
  239. url="http://acegisecurity.org/powering.html">integration page</ulink>
  240. for links to the latest details)</para>
  241. <para>Many independent software vendors (ISVs) adopt Spring Security
  242. because of this significant choice of flexible authentication models.
  243. Doing so allows them to quickly integrate their solutions with
  244. whatever their end clients need, without undertaking a lot of
  245. engineering or requiring the client to change their environment. If
  246. none of the above authentication mechanisms suit your needs, Spring
  247. Security is an open platform and it is quite simple to write your own
  248. authentication mechanism. Many corporate users of Spring Security need
  249. to integrate with "legacy" systems that don't follow any particular
  250. security standards, and Spring Security is happy to "play nicely" with
  251. such systems.</para>
  252. <para>Sometimes the mere process of authentication isn't enough.
  253. Sometimes you need to also differentiate security based on the way a
  254. principal is interacting with your application. For example, you might
  255. want to ensure requests only arrive over HTTPS, in order to protect
  256. passwords from eavesdropping or end users from man-in-the-middle
  257. attacks. Or, you might want to ensure that an actual human being is
  258. making the requests and not some robot or other automated process.
  259. This is especially helpful to protect password recovery processes from
  260. brute force attacks, or simply to make it harder for people to
  261. duplicate your application's key content. To help you achieve these
  262. goals, Spring Security fully supports automatic "channel security",
  263. together with JCaptcha integration for human user detection.</para>
  264. <para>Irrespective of how authentication was undertaken, Spring
  265. Security provides a deep set of authorization capabilities. There are
  266. three main areas of interest in respect of authorization, these being
  267. authorizing web requests, authorizing methods can be invoked, and
  268. authorizing access to individual domain object instances. To help you
  269. understand the differences, consider the authorization capabilities
  270. found in the Servlet Specification web pattern security, EJB Container
  271. Managed Security and file system security respectively. Spring
  272. Security provides deep capabilities in all of these important areas,
  273. which we'll explore later in this reference guide.</para>
  274. </sect1>
  275. <sect1 id="history">
  276. <title>History</title>
  277. <para>Spring Security began in late 2003 as "The Acegi Security System
  278. for Spring". A question was posed on the Spring Developers' mailing
  279. list asking whether there had been any consideration given to a
  280. Spring-based security implementation. At the time the Spring community
  281. was relatively small (especially by today's size!), and indeed Spring
  282. itself had only existed as a SourceForge project from early 2003. The
  283. response to the question was that it was a worthwhile area, although a
  284. lack of time currently prevented its exploration.</para>
  285. <para>With that in mind, a simple security implementation was built
  286. and not released. A few weeks later another member of the Spring
  287. community inquired about security, and at the time this code was
  288. offered to them. Several other requests followed, and by January 2004
  289. around twenty people were using the code. These pioneering users were
  290. joined by others who suggested a SourceForge project was in order,
  291. which was duly established in March 2004.</para>
  292. <para>In those early days, the project didn't have any of its own
  293. authentication modules. Container Managed Security was relied upon for
  294. the authentication process, with Acegi Security instead focusing on
  295. authorization. This was suitable at first, but as more and more users
  296. requested additional container support, the fundamental limitation of
  297. container-specific authentication realm interfaces was experienced.
  298. There was also a related issue of adding new JARs to the container's
  299. classpath, which was a common source of end user confusion and
  300. misconfiguration.</para>
  301. <para>Acegi Security-specific authentication services were
  302. subsequently introduced. Around a year later, Acegi Security became an
  303. official Spring Framework subproject. The 1.0.0 final release was
  304. published in May 2006 - after more than two and a half years of active
  305. use in numerous production software projects and many hundreds of
  306. improvements and community contributions.</para>
  307. <para>Since work began on the 2.0 release, the project has been
  308. rebranded as "Spring Security".</para>
  309. <para>Today Spring Security enjoys a strong and active open source
  310. community. There are thousands of messages about Spring Security on
  311. the support forums. Fourteen developers work on the code itself, with
  312. an active community who also regularly share patches and support their
  313. peers.</para>
  314. </sect1>
  315. <sect1 id="release-numbering">
  316. <title>Release Numbering</title>
  317. <para>It is useful to understand how Spring Security release numbers
  318. work, as it will help you identify the effort (or lack thereof)
  319. involved in migrating to future releases of the project. Officially,
  320. we use the Apache Portable Runtime Project versioning guidelines,
  321. which can be viewed at
  322. <literal>http://apr.apache.org/versioning.html</literal>. We quote the
  323. introduction contained on that page for your convenience:</para>
  324. <para><quote>Versions are denoted using a standard triplet of
  325. integers: MAJOR.MINOR.PATCH. The basic intent is that MAJOR versions
  326. are incompatible, large-scale upgrades of the API. MINOR versions
  327. retain source and binary compatibility with older minor versions, and
  328. changes in the PATCH level are perfectly compatible, forwards and
  329. backwards.</quote></para>
  330. </sect1>
  331. </chapter>
  332. <chapter id="technical-overview">
  333. <title>Technical Overview</title>
  334. <sect1 id="runtime-environment">
  335. <title>Runtime Environment</title>
  336. <para>Spring Security is written to execute within a standard Java 1.3
  337. Runtime Environment. It also supports Java 5.0, although the Java
  338. types which are specific to this release are packaged in a separate
  339. package with the suffix "tiger" in their JAR filename. As Spring
  340. Security aims to operate in a self-contained manner, there is no need
  341. to place any special configuration files into your Java Runtime
  342. Environment. In particular, there is no need to configure a special
  343. Java Authentication and Authorization Service (JAAS) policy file or
  344. place Spring Security into common classpath locations.</para>
  345. <para>Similarly, if you are using an EJB Container or Servlet
  346. Container there is no need to put any special configuration files
  347. anywhere, nor include Spring Security in a server classloader.</para>
  348. <para>This above design offers maximum deployment time flexibility, as
  349. you can simply copy your target artifact (be it a JAR, WAR or EAR)
  350. from one system to another and it will immediately work.</para>
  351. </sect1>
  352. <sect1 id="shared-components">
  353. <title>Shared Components</title>
  354. <para>Let's explore some of the most important shared components in
  355. Spring Security. Components are considered "shared" if they are
  356. central to the framework and the framework cannot operate without
  357. them. These Java types represent the building blocks of the remaining
  358. system, so it's important to understand that they're there, even if
  359. you don't need to directly interact with them.</para>
  360. <para>The most fundamental object is
  361. <literal>SecurityContextHolder</literal>. This is where we store
  362. details of the present security context of the application, which
  363. includes details of the principal currently using the application. By
  364. default the <literal>SecurityContextHolder</literal> uses a
  365. <literal>ThreadLocal</literal> to store these details, which means
  366. that the security context is always available to methods in the same
  367. thread of execution, even if the security context is not explicitly
  368. passed around as an argument to those methods. Using a
  369. <literal>ThreadLocal</literal> in this way is quite safe if care is
  370. taken to clear the thread after the present principal's request is
  371. processed. Of course, Spring Security takes care of this for you
  372. automatically so there is no need to worry about it.</para>
  373. <para>Some applications aren't entirely suitable for using a
  374. <literal>ThreadLocal</literal>, because of the specific way they work
  375. with threads. For example, a Swing client might want all threads in a
  376. Java Virtual Machine to use the same security context. For this
  377. situation you would use the
  378. <literal>SecurityContextHolder.MODE_GLOBAL</literal>. Other
  379. applications might want to have threads spawned by the secure thread
  380. also assume the same security identity. This is achieved by using
  381. <literal>SecurityContextHolder.MODE_INHERITABLETHREADLOCAL</literal>.
  382. You can change the mode from the default
  383. <literal>SecurityContextHolder.MODE_THREADLOCAL</literal> in two ways.
  384. The first is to set a system property. Alternatively, call a static
  385. method on <literal>SecurityContextHolder</literal>. Most applications
  386. won't need to change from the default, but if you do, take a look at
  387. the JavaDocs for <literal>SecurityContextHolder</literal> to learn
  388. more.</para>
  389. <para>Inside the <literal>SecurityContextHolder</literal> we store
  390. details of the principal currently interacting with the application.
  391. Spring Security uses an <literal>Authentication</literal> object to
  392. represent this information. Whilst you won't normally need to create
  393. an <literal>Authentication</literal> object yourself, it is fairly
  394. common for users to query the <literal>Authentication</literal>
  395. object. You can use the following code block - from anywhere in your
  396. application - to do this:</para>
  397. <programlisting>Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
  398. if (obj instanceof UserDetails) {
  399. String username = ((UserDetails)obj).getUsername();
  400. } else {
  401. String username = obj.toString();
  402. }</programlisting>
  403. <para>The above code introduces a number of interesting relationships
  404. and key objects. First, you will notice that there is an intermediate
  405. object between <literal>SecurityContextHolder</literal> and
  406. <literal>Authentication</literal>. The
  407. <literal>SecurityContextHolder.getContext()</literal> method is
  408. actually returning a <literal>SecurityContext</literal>. Spring
  409. Security uses a few different <literal>SecurityContext</literal>
  410. implementations, such as if we need to store special information
  411. related to a request that is not principal-specific. A good example of
  412. this is our JCaptcha integration, which needs to know whether the
  413. current request came from a human user or not. Because such a decision
  414. has nothing at all to do with the principal the request may or may not
  415. be authenticated as, we store it in the
  416. <literal>SecurityContext</literal>.</para>
  417. <para>Another item to note from the above code fragment is that you
  418. can obtain a principal from the <literal>Authentication</literal>
  419. object. The principal is just an <literal>Object</literal>. Most of
  420. the time this can be cast into a <literal>UserDetails</literal>
  421. object. <literal>UserDetails</literal> is a central interface in
  422. Spring Security. It represents a principal, but in an extensible and
  423. application-specific way. Think of <literal>UserDetails</literal> as
  424. the adapter between your own user database and what Spring Security
  425. needs inside the <literal>SecurityContextHolder</literal>. Being a
  426. representation of something from your own user database, quite often
  427. you will cast the <literal>UserDetails</literal> to the original
  428. object that your application provided, so you can call
  429. business-specific methods (like <literal>getEmail()</literal>,
  430. <literal>getEmployeeNumber()</literal> and so on).</para>
  431. <para>By now you're probably wondering, so when do I provide a
  432. <literal>UserDetails</literal> object? How do I do that? I thought you
  433. said this thing was declarative and I didn't need to write any Java
  434. code - what gives? The short answer is that there is a special
  435. interface called <literal>UserDetailsService</literal>. The only
  436. method on this interface accepts a <literal>String</literal>-based
  437. username argument and returns a <literal>UserDetails</literal>. Most
  438. authentication providers that ship with Spring Security delegate to a
  439. <literal>UserDetailsService</literal> as part of the authentication
  440. process. The <literal>UserDetailsService</literal> is used to build
  441. the <literal>Authentication</literal> object that is stored in the
  442. <literal>SecurityContextHolder</literal>. The good news is that we
  443. provide a number of <literal>UserDetailsService</literal>
  444. implementations, including one that uses an in-memory map and another
  445. that uses JDBC. Most users tend to write their own, though, with such
  446. implementations often simply sitting on top of an existing Data Access
  447. Object (DAO) that represents their employees, customers, or other
  448. users of the enterprise application. Remember the advantage that
  449. whatever your UserDetailsService returns can always be obtained from
  450. the <literal>SecurityContextHolder</literal>, as per the above code
  451. fragment.</para>
  452. <para>Besides the principal, another important method provided by
  453. <literal>Authentication</literal> is
  454. <literal>getAuthorities(</literal>). This method provides an array of
  455. <literal>GrantedAuthority</literal> objects. A
  456. <literal>GrantedAuthority</literal> is, not surprisingly, an authority
  457. that is granted to the principal. Such authorities are usually
  458. "roles", such as <literal>ROLE_ADMINISTRATOR</literal> or
  459. <literal>ROLE_HR_SUPERVISOR</literal>. These roles are later on
  460. configured for web authorization, method authorization and domain
  461. object authorization. Other parts of Spring Security are capable of
  462. interpreting these authorities, and expect them to be present.
  463. <literal>GrantedAuthority</literal> objects are usually loaded by the
  464. <literal>UserDetailsService</literal>.</para>
  465. <para>Usually the <literal>GrantedAuthority</literal> objects are
  466. application-wide permissions. They are not specific to a given domain
  467. object. Thus, you wouldn't likely have a
  468. <literal>GrantedAuthority</literal> to represent a permission to
  469. <literal>Employee</literal> object number 54, because if there are
  470. thousands of such authorities you would quickly run out of memory (or,
  471. at the very least, cause the application to take a long time to
  472. authenticate a user). Of course, Spring Security is expressly designed
  473. to handle this common requirement, but you'd instead use the project's
  474. domain object security capabilities for this purpose.</para>
  475. <para>Last but not least, sometimes you will need to store the
  476. <literal>SecurityContext</literal> between HTTP requests. Other times
  477. the principal will re-authenticate on every request, although most of
  478. the time it will be stored. The
  479. <literal>HttpSessionContextIntegrationFilter</literal> is responsible
  480. for storing a <literal>SecurityContext</literal> between HTTP
  481. requests. As suggested by the name of the class, the
  482. <literal>HttpSession</literal> is used to store this information. You
  483. should never interact directly with the <literal>HttpSession</literal>
  484. for security purposes. There is simply no justification for doing so -
  485. always use the <literal>SecurityContextHolder</literal>
  486. instead.</para>
  487. <para>Just to recap, the major building blocks of Spring Security
  488. are:</para>
  489. <itemizedlist spacing="compact">
  490. <listitem>
  491. <para><literal>SecurityContextHolder</literal>, to provide any
  492. type access to the <literal>SecurityContext</literal>.</para>
  493. </listitem>
  494. <listitem>
  495. <para><literal>SecurityContext</literal>, to hold the
  496. <literal>Authentication</literal> and possibly request-specific
  497. security information.</para>
  498. </listitem>
  499. <listitem>
  500. <para><literal>HttpSessionContextIntegrationFilter</literal>, to
  501. store the <literal>SecurityContext</literal> in the
  502. <literal>HttpSession</literal> between web requests.</para>
  503. </listitem>
  504. <listitem>
  505. <para><literal>Authentication</literal>, to represent the
  506. principal in a Spring Security-specific manner.</para>
  507. </listitem>
  508. <listitem>
  509. <para><literal>GrantedAuthority</literal>, to reflect the
  510. application-wide permissions granted to a principal.</para>
  511. </listitem>
  512. <listitem>
  513. <para><literal>UserDetails</literal>, to provide the necessary
  514. information to build an Authentication object from your
  515. application's DAOs.</para>
  516. </listitem>
  517. <listitem>
  518. <para><literal>UserDetailsService</literal>, to create a
  519. <literal>UserDetails</literal> when passed in a
  520. <literal>String</literal>-based username (or certificate ID or
  521. alike).</para>
  522. </listitem>
  523. </itemizedlist>
  524. <para>Now that you've gained an understanding of these repeatedly-used
  525. components, let's take a closer look at the process of
  526. authentication.</para>
  527. </sect1>
  528. <sect1 id="common-authentication">
  529. <title>Authentication</title>
  530. <para>As mentioned in the beginning of this reference guide, Spring
  531. Security can participate in many different authentication
  532. environments. Whilst we recommend people use Spring Security for
  533. authentication and not integrate with existing Container Managed
  534. Authentication, it is nevertheless supported - as is integrating with
  535. your own proprietary authentication system. Let's first explore
  536. authentication from the perspective of Spring Security managing web
  537. security entirely on its own, which is illustrative of the most
  538. complex and most common situation.</para>
  539. <para>Consider a typical web application's authentication
  540. process:</para>
  541. <orderedlist>
  542. <listitem>
  543. <para>You visit the home page, and click on a link.</para>
  544. </listitem>
  545. <listitem>
  546. <para>A request goes to the server, and the server decides that
  547. you've asked for a protected resource.</para>
  548. </listitem>
  549. <listitem>
  550. <para>As you're not presently authenticated, the server sends back
  551. a response indicating that you must authenticate. The response
  552. will either be an HTTP response code, or a redirect to a
  553. particular web page.</para>
  554. </listitem>
  555. <listitem>
  556. <para>Depending on the authentication mechanism, your browser will
  557. either redirect to the specific web page so that you can fill out
  558. the form, or the browser will somehow retrieve your identity (eg a
  559. BASIC authentication dialogue box, a cookie, a X509 certificate
  560. etc).</para>
  561. </listitem>
  562. <listitem>
  563. <para>The browser will send back a response to the server. This
  564. will either be an HTTP POST containing the contents of the form
  565. that you filled out, or an HTTP header containing your
  566. authentication details.</para>
  567. </listitem>
  568. <listitem>
  569. <para>Next the server will decide whether or not the presented
  570. credentials are valid. If they're valid, the next step will
  571. happen. If they're invalid, usually your browser will be asked to
  572. try again (so you return to step two above).</para>
  573. </listitem>
  574. <listitem>
  575. <para>The original request that you made to cause the
  576. authentication process will be retried. Hopefully you've
  577. authenticated with sufficient granted authorities to access the
  578. protected resource. If you have sufficient access, the request
  579. will be successful. Otherwise, you'll receive back an HTTP error
  580. code 403, which means "forbidden".</para>
  581. </listitem>
  582. </orderedlist>
  583. <para>Spring Security has distinct classes responsible for most of the
  584. steps described above. The main participants (in the order that they
  585. are used) are the <literal>ExceptionTranslationFilter</literal>, an
  586. <literal>AuthenticationEntryPoint</literal>, an authentication
  587. mechanism, and an <literal>AuthenticationProvider</literal>.</para>
  588. <para><literal>ExceptionTranslationFilter</literal> is an Acegi
  589. Security filter that has responsibility for detecting any Acegi
  590. Security exceptions that are thrown. Such exceptions will generally be
  591. thrown by an <literal>AbstractSecurityInterceptor</literal>, which is
  592. the main provider of authorization services. We will discuss
  593. <literal>AbstractSecurityInterceptor</literal> in the next section,
  594. but for now we just need to know that it produces Java exceptions and
  595. knows nothing about HTTP or how to go about authenticating a
  596. principal. Instead the <literal>ExceptionTranslationFilter</literal>
  597. offers this service, with specific responsibility for either returning
  598. error code 403 (if the principal has been authenticated and therefore
  599. simply lacks sufficient access - as per step seven above), or
  600. launching an <literal>AuthenticationEntryPoint</literal> (if the
  601. principal has not been authenticated and therefore we need to go
  602. commence step three).</para>
  603. <para>The <literal>AuthenticationEntryPoint</literal> is responsible
  604. for step three in the above list. As you can imagine, each web
  605. application will have a default authentication strategy (well, this
  606. can be configured like nearly everything else in Spring Security, but
  607. let's keep it simple for now). Each major authentication system will
  608. have its own <literal>AuthenticationEntryPoint</literal>
  609. implementation, which takes actions such as described in step
  610. three.</para>
  611. <para>After your browser decides to submit your authentication
  612. credentials (either as an HTTP form post or HTTP header) there needs
  613. to be something on the server that "collects" these authentication
  614. details. By now we're at step six in the above list. In Spring
  615. Security we have a special name for the function of collecting
  616. authentication details from a user agent (usually a web browser), and
  617. that name is "authentication mechanism". After the authentication
  618. details are collected from the user agent, an
  619. "<literal>Authentication</literal> request" object is built and then
  620. presented to an
  621. <interfacename>AuthenticationProvider</interfacename>.</para>
  622. <para>The last played in the Spring Security authentication process is
  623. an <literal>AuthenticationProvider</literal>. Quite simply, it is
  624. responsible for taking an <literal>Authentication</literal> request
  625. object and deciding whether or not it is valid. The provider will
  626. either throw an exception or return a fully populated
  627. <literal>Authentication</literal> object. Remember our good friends,
  628. <literal>UserDetails</literal> and
  629. <literal>UserDetailsService</literal>? If not, head back to the
  630. previous section and refresh your memory. Most
  631. <literal>AuthenticationProvider</literal>s will ask a
  632. <literal>UserDetailsService</literal> to provide a
  633. <literal>UserDetails</literal> object. As mentioned earlier, most
  634. application will provide their own
  635. <literal>UserDetailsService</literal>, although some will be able to
  636. use the JDBC or in-memory implementation that ships with Spring
  637. Security. The resultant <literal>UserDetails</literal> object - and
  638. particularly the <literal>GrantedAuthority[]</literal>s contained
  639. within the <literal>UserDetails</literal> object - will be used when
  640. building the fully populated <literal>Authentication</literal>
  641. object.</para>
  642. <para>After the authentication mechanism receives back the
  643. fully-populated <literal>Authentication</literal> object, it will deem
  644. the request valid, put the <literal>Authentication</literal> into the
  645. <literal>SecurityContextHolder</literal>, and cause the original
  646. request to be retried (step seven above). If, on the other hand, the
  647. <literal>AuthenticationProvider</literal> rejected the request, the
  648. authentication mechanism will ask the user agent to retry (step two
  649. above).</para>
  650. <para>Whilst this describes the typical authentication workflow, the
  651. good news is that Spring Security doesn't mind how you put an
  652. <literal>Authentication</literal> inside the
  653. <literal>SecurityContextHolder</literal>. The only critical
  654. requirement is that the <literal>SecurityContextHolder</literal>
  655. contains an <literal>Authentication</literal> that represents a
  656. principal before the <literal>AbstractSecurityInterceptor</literal>
  657. needs to authorize a request.</para>
  658. <para>You can (and many users do) write their own filters or MVC
  659. controllers to provide interoperability with authentication systems
  660. that are not based on Spring Security. For example, you might be using
  661. Container Managed Authentication which makes the current user
  662. available from a ThreadLocal or JNDI location. Or you might work for a
  663. company that has a legacy proprietary authentication system, which is
  664. a corporate "standard" over which you have little control. In such
  665. situations it's quite easy to get Spring Security to work, and still
  666. provide authorization capabilities. All you need to do is write a
  667. filter (or equivalent) that reads the third-party user information
  668. from a location, build a Spring Security-specific Authentication
  669. object, and put it onto the SecurityContextHolder. It's quite easy to
  670. do this, and it is a fully-supported integration approach.</para>
  671. </sect1>
  672. <sect1 id="secure-objects">
  673. <title>Secure Objects</title>
  674. <para>If you're familiar with AOP, you'd be aware there are different
  675. types of advice available: before, after, throws and around. An around
  676. advice is very useful, because an advisor can elect whether or not to
  677. proceed with a method invocation, whether or not to modify the
  678. response, and whether or not to throw an exception. Spring Security
  679. provides an around advice for method invocations as well as web
  680. requests. We achieve an around advice for method invocations using AOP
  681. Alliance, and we achieve an around advice for web requests using a
  682. standard Filter.</para>
  683. <para>For those not familiar with AOP, the key point to understand is
  684. that Spring Security can help you protect method invocations as well
  685. as web requests. Most people are interested in securing method
  686. invocations on their services layer. This is because the services
  687. layer is where most business logic resides in current-generation J2EE
  688. applications (for clarification, the author disapproves of this design
  689. and instead advocates properly encapsulated domain objects together
  690. with the DTO, assembly, facade and transparent persistence patterns,
  691. but as anemic domain objects is the present mainstream approach, we'll
  692. talk about it here). If you just need to secure method invocations to
  693. the services layer, using the Spring's standard AOP platform
  694. (otherwise known as AOP Alliance) will be adequate. If you need to
  695. secure domain objects directly, you will likely find that AspectJ is
  696. worth considering.</para>
  697. <para>You can elect to perform method authorization using AspectJ or
  698. AOP Alliance, or you can elect to perform web request authorization
  699. using filters. You can use zero, one, two or three of these approaches
  700. together. The mainstream usage is to perform some web request
  701. authorization, coupled with some AOP Alliance method invocation
  702. authorization on the services layer.</para>
  703. <para>Spring Security uses the term "secure object" to refer to any
  704. object that can have security applied to it. Each secure object
  705. supported by Spring Security has its own class, which is a subclass of
  706. <literal>AbstractSecurityInterceptor</literal>. Importantly, by the
  707. time the <literal>AbstractSecurityInterceptor</literal> is run, the
  708. <literal>SecurityContextHolder</literal> will contain a valid
  709. <literal>Authentication</literal> if the principal has been
  710. authenticated.</para>
  711. <para>The <literal>AbstractSecurityInterceptor</literal> provides a
  712. consistent workflow for handling secure object requests. This workflow
  713. includes looking up the "configuration attributes" associated with the
  714. present request. A "configuration attribute" can be thought of as a
  715. String that has special meaning to the classes used by
  716. <literal>AbstractSecurityInterceptor</literal>. They're normally
  717. configured against your <literal>AbstractSecurityInterceptor</literal>
  718. using XML. Anyway, the <literal>AbstractSecurityInterceptor</literal>
  719. will ask an <literal>AccessDecisionManager</literal> "here's the
  720. configuration attributes, here's the current
  721. <literal>Authentication</literal> object, and here's details of the
  722. current request - is this particular principal allowed to perform this
  723. particular operation?".</para>
  724. <para>Assuming <literal>AccessDecisionManager</literal> decides to
  725. allow the request, the <literal>AbstractSecurityInterceptor</literal>
  726. will normally just proceed with the request. Having said that, on rare
  727. occasions users may want to replace the
  728. <literal>Authentication</literal> inside the
  729. <literal>SecurityContext</literal> with a different
  730. <literal>Authentication</literal>, which is handled by the
  731. <literal>AccessDecisionManager</literal> calling a
  732. <literal>RunAsManager</literal>. This might be useful in reasonably
  733. unusual situations, such as if a services layer method needs to call a
  734. remote system and present a different identity. Because Spring
  735. Security automatically propagates security identity from one server to
  736. another (assuming you're using a properly-configured RMI or
  737. HttpInvoker remoting protocol client), this may be useful.</para>
  738. <para>Following the secure object proceeding and then returning -
  739. which may mean a method invocation completing or a filter chain
  740. proceeding - the <literal>AbstractSecurityInterceptor</literal> gets
  741. one final chance to handle the invocation. At this stage the
  742. <literal>AbstractSecurityInterceptor</literal> is interested in
  743. possibly modifying the return object. We might want this to happen
  744. because an authorization decision couldn't be made "on the way in" to
  745. a secure object invocation. Being highly pluggable,
  746. <literal>AbstractSecurityInterceptor</literal> will pass control to an
  747. <literal>AfterInvocationManager</literal> to actually modify the
  748. object if needed. This class even can entirely replace the object, or
  749. throw an exception, or not change it in any way.</para>
  750. <para>Because <literal>AbstractSecurityInterceptor</literal> is the
  751. central template class, it seems fitting that the first figure should
  752. be devoted to it.</para>
  753. <para><mediaobject>
  754. <imageobject role="html">
  755. <imagedata align="center"
  756. fileref="images/SecurityInterception.gif"
  757. format="GIF" />
  758. </imageobject>
  759. <imageobject role="fo">
  760. <imagedata align="center"
  761. fileref="images/SecurityInterception.gif"
  762. format="GIF" />
  763. </imageobject>
  764. <caption>
  765. <para>Figure 1: The key "secure object" model</para>
  766. </caption>
  767. </mediaobject></para>
  768. <para>Only developers contemplating an entirely new way of
  769. intercepting and authorizing requests would need to use secure objects
  770. directly. For example, it would be possible to build a new secure
  771. object to secure calls to a messaging system. Anything that requires
  772. security and also provides a way of intercepting a call (like the AOP
  773. around advice semantics) is capable of being made into a secure
  774. object. Having said that, most Spring applications will simply use the
  775. three currently supported secure object types (AOP Alliance
  776. <literal>MethodInvocation</literal>, AspectJ
  777. <literal>JoinPoint</literal> and web request
  778. <literal>FilterInterceptor</literal>) with complete
  779. transparency.</para>
  780. </sect1>
  781. <sect1 id="common-conclusion">
  782. <title>Conclusion</title>
  783. <para>Congratulations! You have enough of a high-level picture of
  784. Spring Security to embark on your project. We've explored the shared
  785. components, how authentication works, and reviewed the common
  786. authorization concept of a "secure object". Everything that follows in
  787. this reference guide may or may not apply to your particular needs,
  788. and can be read in any order.</para>
  789. </sect1>
  790. </chapter>
  791. <chapter id="supporting-infrastructure">
  792. <title>Supporting Infrastructure</title>
  793. <para>This chapter introduces some of the supplementary and supporting
  794. infrastructure used by Spring Security. If a capability is not directly
  795. related to security, yet included in the Spring Security project, we
  796. will discuss it in this chapter.</para>
  797. <sect1 id="localization">
  798. <title>Localization</title>
  799. <para>Spring Security supports localization of exception messages that
  800. end users are likely to see. If your application is designed for
  801. English users, you don't need to do anything as by default all
  802. Security Security messages are in English. If you need to support
  803. other locales, everything you need to know is contained in this
  804. section.</para>
  805. <para>All exception messages can be localized, including messages
  806. related to authentication failures and access being denied
  807. (authorization failures). Exceptions and logging that is focused on
  808. developers or system deployers (including incorrect attributes,
  809. interface contract violations, using incorrect constructors, startup
  810. time validation, debug-level logging) etc are not localized and
  811. instead are hard-coded in English within Spring Security's
  812. code.</para>
  813. <para>Shipping in the <literal>acegi-security-xx.jar</literal> you
  814. will find an <literal>org.springframework.security</literal> package
  815. that in turn contains a <literal>messages.properties</literal> file.
  816. This should be referred to by your
  817. <literal>ApplicationContext</literal>, as Acegi Security classes
  818. implement Spring's <literal>MessageSourceAware</literal> interface and
  819. expect the message resolver to be dependency injected at application
  820. context startup time. Usually all you need to do is register a bean
  821. inside your application context to refer to the messages. An example
  822. is shown below:</para>
  823. <para><programlisting>&lt;bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"&gt;
  824. &lt;property name="basename"&gt;&lt;value&gt;org/acegisecurity/messages&lt;/value&gt;&lt;/property&gt;
  825. &lt;/bean&gt; </programlisting></para>
  826. <para>The <literal>messages.properties</literal> is named in
  827. accordance with standard resource bundles and represents the default
  828. language supported by Spring Security messages. This default file is
  829. in English. If you do not register a message source, Spring Security
  830. will still work correctly and fallback to hard-coded English versions
  831. of the messages.</para>
  832. <para>If you wish to customize the
  833. <literal>messages.properties</literal> file, or support other
  834. languages, you should copy the file, rename it accordingly, and
  835. register it inside the above bean definition. There are not a large
  836. number of message keys inside this file, so localization should not be
  837. considered a major initiative. If you do perform localization of this
  838. file, please consider sharing your work with the community by logging
  839. a JIRA task and attaching your appropriately-named localized version
  840. of <literal>messages.properties</literal>.</para>
  841. <para>Rounding out the discussion on localization is the Spring
  842. <literal>ThreadLocal</literal> known as
  843. <literal>org.springframework.context.i18n.LocaleContextHolder</literal>.
  844. You should set the <literal>LocaleContextHolder</literal> to represent
  845. the preferred <literal>Locale</literal> of each user. Spring Security
  846. will attempt to locate a message from the message source using the
  847. <literal>Locale</literal> obtained from this
  848. <literal>ThreadLocal</literal>. Please refer to Spring documentation
  849. for further details on using <literal>LocaleContextHolder</literal>
  850. and the helper classes that can automatically set it for you (eg
  851. <literal>AcceptHeaderLocaleResolver</literal>,
  852. <literal>CookieLocaleResolver</literal>,
  853. <literal>FixedLocaleResolver</literal>,
  854. <literal>SessionLocaleResolver</literal> etc)</para>
  855. </sect1>
  856. <sect1 id="filters">
  857. <title>Filters</title>
  858. <para>Spring Security uses many filters, as referred to throughout the
  859. remainder of this reference guide. You have a choice in how these
  860. filters are added to your web application, in that you can use either
  861. <literal>FilterToBeanProxy</literal> or
  862. <literal>FilterChainProxy</literal>. We'll look at both below.</para>
  863. <para>Most filters are configured using the
  864. <literal>FilterToBeanProxy</literal>. An example configuration from
  865. <literal>web.xml</literal> follows:</para>
  866. <para><programlisting>&lt;filter&gt;
  867. &lt;filter-name&gt;Spring Security HTTP Request Security Filter&lt;/filter-name&gt;
  868. &lt;filter-class&gt;org.springframework.security.util.FilterToBeanProxy&lt;/filter-class&gt;
  869. &lt;init-param&gt;
  870. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  871. &lt;param-value&gt;org.springframework.security.ClassThatImplementsFilter&lt;/param-value&gt;
  872. &lt;/init-param&gt;
  873. &lt;/filter&gt;</programlisting></para>
  874. <para>Notice that the filter in <literal>web.xml</literal> is actually
  875. a <literal>FilterToBeanProxy</literal>, and not the filter that will
  876. actually implement the logic of the filter. What
  877. <literal>FilterToBeanProxy</literal> does is delegate the
  878. <literal>Filter</literal>'s methods through to a bean which is
  879. obtained from the Spring application context. This enables the bean to
  880. benefit from the Spring application context lifecycle support and
  881. configuration flexibility. The bean must implement
  882. <literal>javax.servlet.Filter</literal>.</para>
  883. <para>The <literal>FilterToBeanProxy</literal> only requires a single
  884. initialization parameter, <literal>targetClass</literal> or
  885. <literal>targetBean</literal>. The <literal>targetClass</literal>
  886. parameter locates the first object in the application context of the
  887. specified class, whilst <literal>targetBean</literal> locates the
  888. object by bean name. Like standard Spring web applications, the
  889. <literal>FilterToBeanProxy</literal> accesses the application context
  890. via<literal>
  891. WebApplicationContextUtils.getWebApplicationContext(ServletContext)</literal>,
  892. so you should configure a <literal>ContextLoaderListener</literal> in
  893. <literal>web.xml</literal>.</para>
  894. <para>There is a lifecycle issue to consider when hosting
  895. <literal>Filter</literal>s in an IoC container instead of a servlet
  896. container. Specifically, which container should be responsible for
  897. calling the <literal>Filter</literal>'s "startup" and "shutdown"
  898. methods? It is noted that the order of initialization and destruction
  899. of a <literal>Filter</literal> can vary by servlet container, and this
  900. can cause problems if one <literal>Filter</literal> depends on
  901. configuration settings established by an earlier initialized
  902. <literal>Filter</literal>. The Spring IoC container on the other hand
  903. has more comprehensive lifecycle/IoC interfaces (such as
  904. <literal>InitializingBean</literal>,
  905. <literal>DisposableBean</literal>, <literal>BeanNameAware</literal>,
  906. <literal>ApplicationContextAware</literal> and many others) as well as
  907. a well-understood interface contract, predictable method invocation
  908. ordering, autowiring support, and even options to avoid implementing
  909. Spring interfaces (eg the <literal>destroy-method</literal> attribute
  910. in Spring XML). For this reason we recommend the use of Spring
  911. lifecycle services instead of servlet container lifecycle services
  912. wherever possible. By default <literal>FilterToBeanProxy</literal>
  913. will not delegate <literal>init(FilterConfig)</literal> and
  914. <literal>destroy()</literal> methods through to the proxied bean. If
  915. you do require such invocations to be delegated, set the
  916. <literal>lifecycle</literal> initialization parameter to
  917. <literal>servlet-container-managed</literal>.</para>
  918. <para>Rather than using <literal>FilterToBeanProxy</literal>, we
  919. strongly recommend to use <literal>FilterChainProxy</literal> instead.
  920. Whilst <literal>FilterToBeanProxy</literal> is a very useful class,
  921. the problem is that the lines of code required for
  922. <literal>&lt;filter&gt;</literal> and
  923. <literal>&lt;filter-mapping&gt;</literal> entries in
  924. <literal>web.xml</literal> explodes when using more than a few
  925. filters. To overcome this issue, Spring Security provides a
  926. <literal>FilterChainProxy</literal> class. It is wired using a
  927. <literal>FilterToBeanProxy</literal> (just like in the example above),
  928. but the target class is
  929. <literal>org.springframework.security.util.FilterChainProxy</literal>.
  930. The filter chain is then declared in the application context, using
  931. code such as this:</para>
  932. <para><programlisting>&lt;bean id="filterChainProxy"
  933. class="org.springframework.security.util.FilterChainProxy"&gt;
  934. &lt;property name="filterInvocationDefinitionSource"&gt;
  935. &lt;value&gt;
  936. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  937. PATTERN_TYPE_APACHE_ANT
  938. /webServices/**=httpSessionContextIntegrationFilterWithASCFalse,basicProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
  939. /**=httpSessionContextIntegrationFilterWithASCTrue,authenticationProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor
  940. &lt;/value&gt;
  941. &lt;/property&gt;
  942. &lt;/bean&gt; </programlisting></para>
  943. <para>You may notice similarities with the way
  944. <literal>FilterSecurityInterceptor</literal> is declared. Both regular
  945. expressions and Ant Paths are supported, and the most specific URIs
  946. appear first. At runtime the <literal>FilterChainProxy</literal> will
  947. locate the first URI pattern that matches the current web request.
  948. Each of the corresponding configuration attributes represent the name
  949. of a bean defined in the application context. The filters will then be
  950. invoked in the order they are specified, with standard
  951. <literal>FilterChain</literal> behaviour being respected (a
  952. <literal>Filter</literal> can elect not to proceed with the chain if
  953. it wishes to end processing).</para>
  954. <para>As you can see, <literal>FilterChainProxy</literal> requires the
  955. duplication of filter names for different request patterns (in the
  956. above example, <literal>exceptionTranslationFilter</literal> and
  957. <literal>filterSecurityInterceptor</literal> are duplicated). This
  958. design decision was made to enable <literal>FilterChainProxy</literal>
  959. to specify different <literal>Filter</literal> invocation orders for
  960. different URI patterns, and also to improve both the expressiveness
  961. (in terms of regular expressions, Ant Paths, and any custom
  962. <literal>FilterInvocationDefinitionSource</literal> implementations)
  963. and clarity of which <literal>Filter</literal>s should be
  964. invoked.</para>
  965. <para>You may have noticed we have declared two
  966. <literal>HttpSessionContextIntegrationFilter</literal>s in the filter
  967. chain (<literal>ASC</literal> is short for
  968. <literal>allowSessionCreation</literal>, a property of
  969. <literal>HttpSessionContextIntegrationFilter</literal>). As web
  970. services will never present a <literal>jsessionid</literal> on future
  971. requests, creating <literal>HttpSession</literal>s for such user
  972. agents would be wasteful. If you had a high-volume application which
  973. required maximum scalability, we recommend you use the approach shown
  974. above. For smaller applications, using a single
  975. <literal>HttpSessionContextIntegrationFilter</literal> (with its
  976. default <literal>allowSessionCreation</literal> as
  977. <literal>true</literal>) would likely be sufficient.</para>
  978. <para>In relation to lifecycle issues, the
  979. <literal>FilterChainProxy</literal> will always delegate
  980. <literal>init(FilterConfig)</literal> and <literal>destroy()</literal>
  981. methods through to the underlaying <literal>Filter</literal>s if such
  982. methods are called against <literal>FilterChainProxy</literal> itself.
  983. In this case, <literal>FilterChainProxy</literal> guarantees to only
  984. initialize and destroy each <literal>Filter</literal> once,
  985. irrespective of how many times it is declared by the
  986. <literal>FilterInvocationDefinitionSource</literal>. You control the
  987. overall choice as to whether these methods are called or not via the
  988. <literal>lifecycle</literal> initialization parameter of the
  989. <literal>FilterToBeanProxy</literal> that proxies
  990. <literal>FilterChainProxy</literal>. As discussed above, by default
  991. any servlet container lifecycle invocations are not delegated through
  992. to <literal>FilterChainProxy</literal>.</para>
  993. <para>You can also omit a URI pattern from the filter chain by using
  994. the token <literal>#NONE#</literal> on the right-hand side of the
  995. <literal>&lt;URI Pattern&gt; = &lt;Filter Chain&gt;</literal>
  996. expression. For example, using the example above, if you wanted to
  997. exclude the <filename>/webservices</filename> location completely, you
  998. would modify the corresponding line in the bean declaration to be
  999. <programlisting>
  1000. /webServices/**=#NONE#
  1001. </programlisting> Note that anything matching this path will then have
  1002. no authentication or authorization services applied and will be freely
  1003. accessible.</para>
  1004. <para>The order that filters are defined in <literal>web.xml</literal>
  1005. is very important. Irrespective of which filters you are actually
  1006. using, the order of the <literal>&lt;filter-mapping&gt;</literal>s
  1007. should be as follows:</para>
  1008. <orderedlist>
  1009. <listitem>
  1010. <para><literal>ChannelProcessingFilter</literal>, because it might
  1011. need to redirect to a different protocol</para>
  1012. </listitem>
  1013. <listitem>
  1014. <para><literal>ConcurrentSessionFilter</literal>, because it
  1015. doesn't use any <literal>SecurityContextHolder</literal>
  1016. functionality but needs to update the
  1017. <literal>SessionRegistry</literal> to reflect ongoing requests
  1018. from the principal</para>
  1019. </listitem>
  1020. <listitem>
  1021. <para><literal>HttpSessionContextIntegrationFilter</literal>, so a
  1022. <literal>SecurityContext</literal> can be setup in the
  1023. <literal>SecurityContextHolder</literal> at the beginning of a web
  1024. request, and any changes to the <literal>SecurityContext</literal>
  1025. can be copied to the <literal>HttpSession</literal> when the web
  1026. request ends (ready for use with the next web request)</para>
  1027. </listitem>
  1028. <listitem>
  1029. <para>Authentication processing mechanisms -
  1030. <literal>AuthenticationProcessingFilter</literal>,
  1031. <literal>CasProcessingFilter</literal>,
  1032. <literal>BasicProcessingFilter, HttpRequestIntegrationFilter,
  1033. JbossIntegrationFilter</literal> etc - so that the
  1034. <literal>SecurityContextHolder</literal> can be modified to
  1035. contain a valid <literal>Authentication</literal> request
  1036. token</para>
  1037. </listitem>
  1038. <listitem>
  1039. <para>The
  1040. <literal>SecurityContextHolderAwareRequestFilter</literal>, if you
  1041. are using it to install a Spring Security aware
  1042. <literal>HttpServletRequestWrapper</literal> into your servlet
  1043. container</para>
  1044. </listitem>
  1045. <listitem>
  1046. <para><literal>RememberMeProcessingFilter</literal>, so that if no
  1047. earlier authentication processing mechanism updated the
  1048. <literal>SecurityContextHolder</literal>, and the request presents
  1049. a cookie that enables remember-me services to take place, a
  1050. suitable remembered
  1051. <literal><literal>Authentication</literal></literal> object will
  1052. be put there</para>
  1053. </listitem>
  1054. <listitem>
  1055. <para><literal>AnonymousProcessingFilter</literal>, so that if no
  1056. earlier authentication processing mechanism updated the
  1057. <literal>SecurityContextHolder</literal>, an anonymous
  1058. <literal>Authentication</literal> object will be put there</para>
  1059. </listitem>
  1060. <listitem>
  1061. <para><literal>ExceptionTranslationFilter</literal>, to catch any
  1062. Spring Security exceptions so that either an HTTP error response
  1063. can be returned or an appropriate
  1064. <literal>AuthenticationEntryPoint</literal> can be launched</para>
  1065. </listitem>
  1066. <listitem>
  1067. <para><literal>FilterSecurityInterceptor</literal>, to protect web
  1068. URIs</para>
  1069. </listitem>
  1070. </orderedlist>
  1071. <para>All of the above filters use
  1072. <literal>FilterToBeanProxy</literal> or
  1073. <literal>FilterChainProxy</literal>. It is recommended that a single
  1074. <literal>FilterToBeanProxy</literal> proxy through to a single
  1075. <literal>FilterChainProxy</literal> for each application, with that
  1076. <literal>FilterChainProxy</literal> defining all of Spring Security
  1077. <literal>Filter</literal>s.</para>
  1078. <para>If you're using SiteMesh, ensure Spring Security filters execute
  1079. before the SiteMesh filters are called. This enables the
  1080. <literal>SecurityContextHolder</literal> to be populated in time for
  1081. use by SiteMesh decorators</para>
  1082. </sect1>
  1083. </chapter>
  1084. <chapter id="channel-security">
  1085. <title>Channel Security</title>
  1086. <sect1 id="channel-security-overview">
  1087. <title>Overview</title>
  1088. <para>In addition to coordinating the authentication and authorization
  1089. requirements of your application, Spring Security is also able to
  1090. ensure unauthenticated web requests have certain properties. These
  1091. properties may include being of a particular transport type, having a
  1092. particular <literal>HttpSession</literal> attribute set and so on. The
  1093. most common requirement is for your web requests to be received using
  1094. a particular transport protocol, such as HTTPS.</para>
  1095. <para>An important issue in considering transport security is that of
  1096. session hijacking. Your web container manages a
  1097. <literal>HttpSession</literal> by reference to a
  1098. <literal>jsessionid</literal> that is sent to user agents either via a
  1099. cookie or URL rewriting. If the <literal>jsessionid</literal> is ever
  1100. sent over HTTP, there is a possibility that session identifier can be
  1101. intercepted and used to impersonate the user after they complete the
  1102. authentication process. This is because most web containers maintain
  1103. the same session identifier for a given user, even after they switch
  1104. from HTTP to HTTPS pages.</para>
  1105. <para>If session hijacking is considered too significant a risk for
  1106. your particular application, the only option is to use HTTPS for every
  1107. request. This means the <literal>jsessionid</literal> is never sent
  1108. across an insecure channel. You will need to ensure your
  1109. <literal>web.xml</literal>-defined
  1110. <literal>&lt;welcome-file&gt;</literal> points to an HTTPS location,
  1111. and the application never directs the user to an HTTP location. Spring
  1112. Security provides a solution to assist with the latter.</para>
  1113. </sect1>
  1114. <sect1 id="channel-security-config">
  1115. <title>Configuration</title>
  1116. <para>To utilise Spring Security's channel security services, add the
  1117. following lines to <literal>web.xml</literal>:</para>
  1118. <para><programlisting>
  1119. &lt;filter&gt;
  1120. &lt;filter-name&gt;Spring Security Channel Processing Filter&lt;/filter-name&gt;
  1121. &lt;filter-class&gt;org.springframework.security.util.FilterToBeanProxy&lt;/filter-class&gt;
  1122. &lt;init-param&gt;
  1123. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  1124. &lt;param-value&gt;org.springframework.security.securechannel.ChannelProcessingFilter&lt;/param-value&gt;
  1125. &lt;/init-param&gt;
  1126. &lt;/filter&gt;
  1127. &lt;filter-mapping&gt;
  1128. &lt;filter-name&gt;Spring Security Channel Processing Filter&lt;/filter-name&gt;
  1129. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  1130. &lt;/filter-mapping&gt;
  1131. </programlisting></para>
  1132. <para>As usual when running <literal>FilterToBeanProxy</literal>, you
  1133. will also need to configure the filter in your application
  1134. context:</para>
  1135. <para><programlisting>
  1136. &lt;bean id="channelProcessingFilter" class="org.springframework.security.securechannel.ChannelProcessingFilter"&gt;
  1137. &lt;property name="channelDecisionManager"&gt;&lt;ref bean="channelDecisionManager"/&gt;&lt;/property&gt;
  1138. &lt;property name="filterInvocationDefinitionSource"&gt;
  1139. &lt;value&gt;
  1140. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  1141. \A/secure/.*\Z=REQUIRES_SECURE_CHANNEL
  1142. \A/acegilogin.jsp.*\Z=REQUIRES_SECURE_CHANNEL
  1143. \A/j_spring_security_check.*\Z=REQUIRES_SECURE_CHANNEL
  1144. \A.*\Z=REQUIRES_INSECURE_CHANNEL
  1145. &lt;/value&gt;
  1146. &lt;/property&gt;
  1147. &lt;/bean&gt;
  1148. &lt;bean id="channelDecisionManager" class="org.springframework.security.securechannel.ChannelDecisionManagerImpl"&gt;
  1149. &lt;property name="channelProcessors"&gt;
  1150. &lt;list&gt;
  1151. &lt;ref bean="secureChannelProcessor"/&gt;
  1152. &lt;ref bean="insecureChannelProcessor"/&gt;
  1153. &lt;/list&gt;
  1154. &lt;/property&gt;
  1155. &lt;/bean&gt;
  1156. &lt;bean id="secureChannelProcessor" class="org.springframework.security.securechannel.SecureChannelProcessor"/&gt;
  1157. &lt;bean id="insecureChannelProcessor" class="org.springframework.security.securechannel.InsecureChannelProcessor"/&gt;
  1158. </programlisting></para>
  1159. <para>Like <literal>FilterSecurityInterceptor</literal>, Apache Ant
  1160. style paths are also supported by the
  1161. <literal>ChannelProcessingFilter</literal>.</para>
  1162. <para>The <literal>ChannelProcessingFilter</literal> operates by
  1163. filtering all web requests and determining the configuration
  1164. attributes that apply. It then delegates to the
  1165. <literal>ChannelDecisionManager</literal>. The default implementation,
  1166. <literal>ChannelDecisionManagerImpl</literal>, should suffice in most
  1167. cases. It simply delegates through the list of configured
  1168. <literal>ChannelProcessor</literal> instances. A
  1169. <literal>ChannelProcessor</literal> will review the request, and if it
  1170. is unhappy with the request (eg it was received across the incorrect
  1171. transport protocol), it will perform a redirect, throw an exception or
  1172. take whatever other action is appropriate.</para>
  1173. <para>Included with Spring Security are two concrete
  1174. <literal>ChannelProcessor</literal> implementations:
  1175. <literal>SecureChannelProcessor</literal> ensures requests with a
  1176. configuration attribute of <literal>REQUIRES_SECURE_CHANNEL</literal>
  1177. are received over HTTPS, whilst
  1178. <literal>InsecureChannelProcessor</literal> ensures requests with a
  1179. configuration attribute of
  1180. <literal>REQUIRES_INSECURE_CHANNEL</literal> are received over HTTP.
  1181. Both implementations delegate to a
  1182. <literal>ChannelEntryPoint</literal> if the required transport
  1183. protocol is not used. The two <literal>ChannelEntryPoint</literal>
  1184. implementations included with Spring Security simply redirect the
  1185. request to HTTP and HTTPS as appropriate. Appropriate defaults are
  1186. assigned to the <literal>ChannelProcessor</literal> implementations
  1187. for the configuration attribute keywords they respond to and the
  1188. <literal>ChannelEntryPoint</literal> they delegate to, although you
  1189. have the ability to override these using the application
  1190. context.</para>
  1191. <para>Note that the redirections are absolute (eg
  1192. <literal>http://www.company.com:8080/app/page</literal>), not relative
  1193. (eg <literal>/app/page</literal>). During testing it was discovered
  1194. that Internet Explorer 6 Service Pack 1 has a bug whereby it does not
  1195. respond correctly to a redirection instruction which also changes the
  1196. port to use. Accordingly, absolute URLs are used in conjunction with
  1197. bug detection logic in the <literal>PortResolverImpl</literal> that is
  1198. wired up by default to many Spring Security beans. Please refer to the
  1199. JavaDocs for <literal>PortResolverImpl</literal> for further
  1200. details.</para>
  1201. <para>You should note that using a secure channel is recommended if
  1202. usernames and passwords are to be kept secure during the login
  1203. process. If you do decide to use
  1204. <literal>ChannelProcessingFilter</literal> with form-based login,
  1205. please ensure that your login page is set to
  1206. <literal>REQUIRES_SECURE_CHANNEL</literal>, and that the
  1207. <literal>AuthenticationProcessingFilterEntryPoint.forceHttps</literal>
  1208. property is <literal>true</literal>.</para>
  1209. </sect1>
  1210. <sect1 id="channel-security-conclusion">
  1211. <title>Conclusion</title>
  1212. <para>Once configured, using the channel security filter is very easy.
  1213. Simply request pages without regard to the protocol (ie HTTP or HTTPS)
  1214. or port (eg 80, 8080, 443, 8443 etc). Obviously you'll still need a
  1215. way of making the initial request (probably via the
  1216. <literal>web.xml</literal> <literal>&lt;welcome-file&gt;</literal> or
  1217. a well-known home page URL), but once this is done the filter will
  1218. perform redirects as defined by your application context.</para>
  1219. <para>You can also add your own <literal>ChannelProcessor</literal>
  1220. implementations to the <literal>ChannelDecisionManagerImpl</literal>.
  1221. For example, you might set a <literal>HttpSession</literal> attribute
  1222. when a human user is detected via a "enter the contents of this
  1223. graphic" procedure. Your <literal>ChannelProcessor</literal> would
  1224. respond to say <literal>REQUIRES_HUMAN_USER</literal> configuration
  1225. attributes and redirect to an appropriate entry point to start the
  1226. human user validation process if the <literal>HttpSession</literal>
  1227. attribute is not currently set.</para>
  1228. <para>To decide whether a security check belongs in a
  1229. <literal>ChannelProcessor</literal> or an
  1230. <literal>AccessDecisionVoter</literal>, remember that the former is
  1231. designed to handle unauthenticated requests, whilst the latter is
  1232. designed to handle authenticated requests. The latter therefore has
  1233. access to the granted authorities of the authenticated principal. In
  1234. addition, problems detected by a <literal>ChannelProcessor</literal>
  1235. will generally cause an HTTP/HTTPS redirection so its requirements can
  1236. be met, whilst problems detected by an
  1237. <literal>AccessDecisionVoter</literal> will ultimately result in an
  1238. <literal>AccessDeniedException</literal> (depending on the governing
  1239. <literal>AccessDecisionManager</literal>).</para>
  1240. </sect1>
  1241. </chapter>
  1242. <chapter id="taglib">
  1243. <title>Tag Libraries</title>
  1244. <sect1 id="taglib-overview">
  1245. <title>Overview</title>
  1246. <para>Spring Security comes bundled with several JSP tag libraries
  1247. that eases JSP writing. The tag libraries provide a range of different
  1248. services.</para>
  1249. </sect1>
  1250. <sect1 id="taglib-config">
  1251. <title>Configuration</title>
  1252. <para>All taglib classes are included in the core
  1253. <literal>spring-security-xx.jar</literal> file, with the
  1254. <literal>security.tld</literal> located in the JAR's
  1255. <literal>META-INF</literal> directory. This means for JSP 1.2+ web
  1256. containers you can simply include the JAR in the WAR's
  1257. <literal>WEB-INF/lib</literal> directory and it will be available. If
  1258. you're using a JSP 1.1 container, you'll need to declare the JSP
  1259. taglib in your <literal>web.xml file</literal>, and include
  1260. <literal>security.tld</literal> in the <literal>WEB-INF/lib</literal>
  1261. directory. The following fragment is added to
  1262. <literal>web.xml</literal>:</para>
  1263. <para><programlisting>&lt;taglib&gt;
  1264. &lt;taglib-uri&gt;http://www.springframework.org/security/tags&lt;/taglib-uri&gt;
  1265. &lt;taglib-location&gt;/WEB-INF/security.tld&lt;/taglib-location&gt;
  1266. &lt;/taglib&gt; </programlisting></para>
  1267. </sect1>
  1268. <sect1 id="taglib-usage">
  1269. <title>Usage</title>
  1270. <para>Now that you've configured the tag libraries, refer to the
  1271. individual reference guide sections for details on how to use them.
  1272. Note that when using the tags, you should include the taglib reference
  1273. in your JSP: <programlisting>
  1274. &lt;%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %&gt;
  1275. </programlisting></para>
  1276. </sect1>
  1277. </chapter>
  1278. </part>
  1279. <part id="authentication">
  1280. <title>Authentication</title>
  1281. <partintro>
  1282. <para>In this part of the reference guide we will examine individual
  1283. authentication mechanisms and their corresponding
  1284. <literal>AuthenticationProvider</literal>s. We'll also look at how to
  1285. configure authentication more generally, including if you have several
  1286. authentication approaches that need to be chained together.</para>
  1287. </partintro>
  1288. <chapter id="authentication-common-auth-services">
  1289. <title>Common Authentication Services</title>
  1290. <sect1 id="mechanisms-providers-entry-points">
  1291. <title>Mechanisms, Providers and Entry Points</title>
  1292. <para>If you're using Spring Security-provided authentication
  1293. approaches, you'll usually need to configure a web filter, together
  1294. with an <literal>AuthenticationProvider</literal> and
  1295. <literal>AuthenticationEntryPoint</literal>. In this section we are
  1296. going to explore an example application that needs to support both
  1297. form-based authentication (ie so a nice HTML page is presented to a
  1298. user for them to login) plus BASIC authentication (ie so a web service
  1299. or similar can access protected resources).</para>
  1300. <para>In the web.xml, this application will need a single Acegi
  1301. Security filter in order to use the FilterChainProxy. Nearly every
  1302. Spring Security application will have such an entry, and it looks like
  1303. this:</para>
  1304. <para><programlisting>&lt;filter&gt;
  1305. &lt;filter-name&gt;Spring Security Filter Chain Proxy&lt;/filter-name&gt;
  1306. &lt;filter-class&gt;org.springframework.security.util.FilterToBeanProxy&lt;/filter-class&gt;
  1307. &lt;init-param&gt;
  1308. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  1309. &lt;param-value&gt;org.springframework.security.util.FilterChainProxy&lt;/param-value&gt;
  1310. &lt;/init-param&gt;
  1311. &lt;/filter&gt;
  1312. &lt;filter-mapping&gt;
  1313. &lt;filter-name&gt;Spring Security Filter Chain Proxy&lt;/filter-name&gt;
  1314. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  1315. &lt;/filter-mapping&gt;</programlisting></para>
  1316. <para>The above declarations will cause every web request to be passed
  1317. through to Spring Security's FilterChainProxy. As explained in the
  1318. filters section of this reference guide, the
  1319. <classname>FilterChainProxy</classname> is a generally-useful class
  1320. that enables web requests to be passed to different filters based on
  1321. the URL patterns. Those delegated filters are managed inside the
  1322. application context, so they can benefit from dependency injection.
  1323. Let's have a look at what the FilterChainProxy bean definition would
  1324. look like inside your application context:</para>
  1325. <para><programlisting>&lt;bean id="filterChainProxy"
  1326. class="org.springframework.security.util.FilterChainProxy"&gt;
  1327. &lt;property name="filterInvocationDefinitionSource"&gt;
  1328. &lt;value&gt;
  1329. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  1330. PATTERN_TYPE_APACHE_ANT
  1331. /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,switchUserProcessingFilter
  1332. &lt;/value&gt;
  1333. &lt;/property&gt;
  1334. &lt;/bean&gt;</programlisting></para>
  1335. <para>Internally Spring Security will use a
  1336. <literal>PropertyEditor</literal> to convert the string presented in
  1337. the above XML fragment into a
  1338. <literal>FilterInvocationDefinitionSource</literal> object. What's
  1339. important to note at this stage is that a series of filters will be
  1340. run - in the order specified by the declaration - and each of those
  1341. filters are actually the <literal>&lt;bean id&gt;</literal> of another
  1342. bean inside the application context. So, in our case some extra beans
  1343. will also appear in the application context, and they'll be named
  1344. <literal>httpSessionContextIntegrationFilter</literal>,
  1345. <literal>logoutFilter</literal> and so on. The order that the filters
  1346. should appear is discussed in the filters section of the reference
  1347. guide - although they are correct in the above example.</para>
  1348. <para>In our example we have the
  1349. <literal>AuthenticationProcessingFilter</literal> and
  1350. <literal>BasicProcessingFilter</literal> being used. These are the
  1351. "authentication mechanisms" that respond to form-based authentication
  1352. and BASIC HTTP header-based authentication respectively (we discussed
  1353. the role of authentication mechanisms earlier in this reference
  1354. guide). If you weren't using form or BASIC authentication, neither of
  1355. these beans would be defined. You'd instead define filters applicable
  1356. to your desired authentication environment, such as
  1357. <literal>DigestProcessingFilter</literal> or
  1358. <literal>CasProcessingFilter</literal>. Refer to the individual
  1359. chapters of this part of the reference guide to learn how to configure
  1360. each of these authentication mechanisms.</para>
  1361. <para>Recall that
  1362. <literal>HttpSessionContextIntegrationFilter</literal> keeps the
  1363. contents of the <literal>SecurityContext</literal> between invocations
  1364. inside an HTTP session. This means the authentication mechanisms are
  1365. only used once, being when the principal initially tries to
  1366. authenticate. The rest of the time the authentication mechanisms sit
  1367. there and silently pass the request through to the next filter in the
  1368. chain. That is a practical requirement due to the fact that few
  1369. authentication approaches present credentials on each and every call
  1370. (BASIC authentication being a notable exception), but what happens if
  1371. a principal's account gets cancelled or disabled or otherwise changed
  1372. (eg an increase or decrease in <literal>GrantedAuthority[]</literal>s)
  1373. after the initial authentication step? Let's look at how that is
  1374. handled now.</para>
  1375. <para>The major authorization provider for secure objects has
  1376. previously been introduced as
  1377. <literal>AbstractSecurityInterceptor</literal>. This class needs to
  1378. have access to an <literal>AuthenticationManager</literal>. It also
  1379. has configurable settings to indicate whether an
  1380. <literal>Authentication</literal> object should be re-authenticated on
  1381. each secure object invocation. By default it just accepts any
  1382. <literal>Authentication</literal> inside the
  1383. <literal>SecurityContextHolder</literal> is authenticated if
  1384. <literal>Authentication.isAuthenticated()</literal> returns true. This
  1385. is great for performance, but not ideal if you want to ensure
  1386. up-to-the-moment authentication validity. For such cases you'll
  1387. probably want to set the
  1388. <literal>AbstractSecurityInterceptor.alwaysReauthenticate</literal>
  1389. property to true.</para>
  1390. <para>You might be asking yourself, "what's this
  1391. <literal>AuthenticationManager</literal>?". We haven't explored it
  1392. before, but we have discussed the concept of an
  1393. <literal>AuthenticationProvider</literal>. Quite simply, an
  1394. <interfacename>AuthenticationManager</interfacename> is responsible
  1395. for passing requests through a chain of AuthenticationProviders. It's
  1396. a little like the filter chain we discussed earlier, although there
  1397. are some differences. There is only one
  1398. <interfacename>AuthenticationManager</interfacename> implementation
  1399. shipped with Spring Security, so let's look at how it's configured for
  1400. the example we're using in this chapter:</para>
  1401. <para><programlisting>&lt;bean id="authenticationManager"
  1402. class="org.springframework.security.providers.ProviderManager"&gt;
  1403. &lt;property name="providers"&gt;
  1404. &lt;list&gt;
  1405. &lt;ref local="daoAuthenticationProvider"/&gt;
  1406. &lt;ref local="anonymousAuthenticationProvider"/&gt;
  1407. &lt;ref local="rememberMeAuthenticationProvider"/&gt;
  1408. &lt;/list&gt;
  1409. &lt;/property&gt;
  1410. &lt;/bean&gt;</programlisting></para>
  1411. <para>It's probably worth mentioning at this point that your
  1412. authentication mechanisms (which are usually filters) are also
  1413. injected with a reference to the
  1414. <literal>AuthenticationManager</literal>. So both
  1415. <literal>AbstractSecurityInterceptor</literal> as well as the
  1416. authentication mechanisms will use the above
  1417. <literal>ProviderManager</literal> to poll a list of
  1418. <literal>AuthenticationProvider</literal>s.</para>
  1419. <para>In our example we have three providers. They are tried in the
  1420. order shown (which is implied by the use of a <literal>List</literal>
  1421. instead of a <literal>Set</literal>), with each provider able to
  1422. attempt authentication, or skip authentication by simply returning
  1423. <literal>null</literal>. If all implementations return null, the
  1424. <literal>ProviderManager</literal> will throw a suitable exception. If
  1425. you're interested in learning more about chaining providers, please
  1426. refer to the <literal>ProviderManager</literal> JavaDocs.</para>
  1427. <para>The providers to use will sometimes be interchangeable with the
  1428. authentication mechanisms, whilst at other times they will depend on a
  1429. specific authentication mechanism. For example, the
  1430. <literal>DaoAuthenticationProvider</literal> just needs a string-based
  1431. username and password. Various authentication mechanisms result in the
  1432. collection of a string-based username and password, including (but not
  1433. limited to) BASIC and form authentication. Equally, some
  1434. authentication mechanisms create an authentication request object
  1435. which can only be interpreted by a single type of
  1436. <literal>AuthenticationProvider</literal>. An example of this
  1437. one-to-one mapping would be JA-SIG CAS, which uses the notion of a
  1438. service ticket which can therefore only be authenticated by
  1439. <literal>CasAuthenticationProvider</literal>. A further example of a
  1440. one-to-one mapping would be the LDAP authentication mechanism, which
  1441. can only be processed an the
  1442. <literal>LdapAuthenticationProvider</literal>. The specifics of such
  1443. relationships are detailed in the JavaDocs for each class, plus the
  1444. authentication approach-specific chapters of this reference guide. You
  1445. need not be terribly concerned about this implementation detail,
  1446. because if you forget to register a suitable provider, you'll simply
  1447. receive a <literal>ProviderNotFoundException</literal> when an attempt
  1448. to authenticate is made.</para>
  1449. <para>After configuring the correct authentication mechanisms in the
  1450. <literal>FilterChainProxy</literal>, and ensuring that a corresponding
  1451. <literal>AuthenticationProvider</literal> is registered in the
  1452. <literal>ProviderManager</literal>, your last step is to configure an
  1453. <literal>AuthenticationEntryPoint</literal>. Recall that earlier we
  1454. discussed the role of <literal>ExceptionTranslationFilter</literal>,
  1455. which is used when HTTP-based requests should receive back an HTTP
  1456. header or HTTP redirect in order to start authentication. Continuing
  1457. on with our earlier example:</para>
  1458. <para><programlisting>&lt;bean id="exceptionTranslationFilter"
  1459. class="org.springframework.security.ui.ExceptionTranslationFilter"&gt;
  1460. &lt;property name="authenticationEntryPoint"&gt;&lt;ref local="authenticationProcessingFilterEntryPoint"/&gt;&lt;/property&gt;
  1461. &lt;property name="accessDeniedHandler"&gt;
  1462. &lt;bean class="org.springframework.security.ui.AccessDeniedHandlerImpl"&gt;
  1463. &lt;property name="errorPage" value="/accessDenied.jsp"/&gt;
  1464. &lt;/bean&gt;
  1465. &lt;/property&gt;
  1466. &lt;/bean&gt;
  1467. &lt;bean id="authenticationProcessingFilterEntryPoint"
  1468. class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint"&gt;
  1469. &lt;property name="loginFormUrl"&gt;&lt;value&gt;/acegilogin.jsp&lt;/value&gt;&lt;/property&gt;
  1470. &lt;property name="forceHttps"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  1471. &lt;/bean&gt;</programlisting></para>
  1472. <para>Notice that the <literal>ExceptionTranslationFilter</literal>
  1473. requires two collaborators. The first,
  1474. <literal>AccessDeniedHandlerImpl</literal>, uses a
  1475. <literal>RequestDispatcher</literal> forward to display the specified
  1476. access denied error page. We use a forward so that the
  1477. <literal>SecurityContextHolder</literal> still contains details of the
  1478. principal, which may be useful for display to the user (in old
  1479. releases of Spring Security we relied upon the servlet container to
  1480. handle a 403 error message, which lacked this useful contextual
  1481. information). <literal>AccessDeniedHandlerImpl</literal> will also set
  1482. the HTTP header to 403, which is the official error code to indicate
  1483. access denied. In the case of the
  1484. <literal>AuthentionEntryPoint</literal>, here we're setting what
  1485. action we would like taken when an unauthenticated principal attempts
  1486. to perform a protected operation. Because in our example we're going
  1487. to be using form-based authentication, we specify
  1488. <literal>AuthenticationProcessinFilterEntryPoint</literal> and the URL
  1489. of the login page. Your application will usually only have one entry
  1490. point, and most authentication approaches define their own specific
  1491. <literal>AuthenticationEntryPoint</literal>. Details of which entry
  1492. point to use for each authentication approach is discussed in the
  1493. authentication approach-specific chapters of this reference
  1494. guide.</para>
  1495. </sect1>
  1496. <sect1 id="userdetails-and-associated-types">
  1497. <title>UserDetails and Associated Types</title>
  1498. <para>As mentioned in the first part of the reference guide, most
  1499. authentication providers take advantage of the
  1500. <literal>UserDetails</literal> and
  1501. <literal>UserDetailsService</literal> interfaces. The contract for
  1502. this latter interface consists of a single method:</para>
  1503. <para><programlisting>public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;</programlisting></para>
  1504. <para>The returned <literal>UserDetails</literal> is an interface that
  1505. provides getters that guarantee non-null provision of basic
  1506. authentication information such as the username, password, granted
  1507. authorities and whether the user is enabled or disabled. Most
  1508. authentication providers will use a
  1509. <literal>UserDetailsService</literal>, even if the username and
  1510. password are not actually used as part of the authentication decision.
  1511. Generally such provider will be using the returned
  1512. <literal>UserDetails</literal> object just for its
  1513. <literal>GrantedAuthority[]</literal> information, because some other
  1514. system (like LDAP or X509 or CAS etc) has undertaken the
  1515. responsibility of actually validating the credentials.</para>
  1516. <para>A single concrete implementation of
  1517. <literal>UserDetails</literal> is provided with Spring Security, being
  1518. the <literal>User</literal> class. Spring Security users will need to
  1519. decide when writing their <literal>UserDetailsService</literal> what
  1520. concrete <literal>UserDetails</literal> class to return. In most cases
  1521. <literal>User</literal> will be used directly or subclassed, although
  1522. special circumstances (such as object relational mappers) may require
  1523. users to write their own <literal>UserDetails</literal> implementation
  1524. from scratch. This is not such an unusual situation, and users should
  1525. not hesitate to simply return their normal domain object that
  1526. represents a user of the system. This is especially common given that
  1527. <literal>UserDetails</literal> is often used to store additional
  1528. principal-related properties (such as their telephone number and email
  1529. address), so that they can be easily used by web views.</para>
  1530. <para>Given <literal>UserDetailsService</literal> is so simple to
  1531. implement, it should be easy for users to retrieve authentication
  1532. information using a persistence strategy of their choice. Having said
  1533. that, Spring Security does include a couple of useful base
  1534. implementations, which we'll look at below.</para>
  1535. <sect2 id="in-memory-service">
  1536. <title>In-Memory Authentication</title>
  1537. <para>Whilst it is easy to use create a custom
  1538. <literal>UserDetailsService</literal> implementation that extracts
  1539. information from a persistence engine of choice, many applications
  1540. do not require such complexity. This is particularly true if you're
  1541. undertaking a rapid prototype or just starting integrating Spring
  1542. Security, when you don't really want to spend time configuring
  1543. databases or writing <literal>UserDetailsService</literal>
  1544. implementations. For this sort of situation, a simple option is to
  1545. configure the <literal>InMemoryDaoImpl</literal>
  1546. implementation:</para>
  1547. <para><programlisting>&lt;bean id="inMemoryDaoImpl"
  1548. class="org.springframework.security.userdetails.memory.InMemoryDaoImpl"&gt;
  1549. &lt;property name="userMap"&gt;
  1550. &lt;value&gt;
  1551. rod=koala,ROLE_TELLER,ROLE_SUPERVISOR
  1552. dianne=emu,ROLE_TELLER
  1553. scott=wombat,ROLE_TELLER
  1554. peter=opal,disabled,ROLE_TELLER
  1555. &lt;/value&gt;
  1556. &lt;/property&gt;
  1557. &lt;/bean&gt; </programlisting></para>
  1558. <para>In the above example, the <literal>userMap</literal> property
  1559. contains each of the usernames, passwords, a list of granted
  1560. authorities and an optional enabled/disabled keyword. Commas are
  1561. used to delimit each token. The username must appear to the left of
  1562. the equals sign, and the password must be the first token to the
  1563. right of the equals sign. The <literal>enabled</literal> and
  1564. <literal>disabled</literal> keywords (case insensitive) may appear
  1565. in the second or any subsequent token. Any remaining tokens are
  1566. treated as granted authorities, which are created as
  1567. <literal>GrantedAuthorityImpl</literal> objects (this is just for
  1568. your reference - most applications don't need custom
  1569. <literal>GrantedAuthority</literal> implementations, so using the
  1570. default implementation in this manner is just fine). Note that if a
  1571. user has no password and/or no granted authorities, the user will
  1572. not be created in the in-memory authentication repository.</para>
  1573. <para><literal>InMemoryDaoImpl</literal> also offers a
  1574. <literal>setUserProperties(Properties)</literal> method, which
  1575. allows you to externalise the
  1576. <literal>java.util.Properties</literal> in another Spring configured
  1577. bean or an external properties file. You might like to use Spring's
  1578. <literal>PropertiesFactoryBean</literal>, which is useful for
  1579. loading such external properties files. This setter might prove
  1580. useful for simple applications that have a larger number of users,
  1581. or deployment-time configuration changes, but do not wish to use a
  1582. full database for handling authentication details.</para>
  1583. </sect2>
  1584. <sect2 id="jdbc-service">
  1585. <title>JDBC Authentication</title>
  1586. <para>Spring Security also includes a
  1587. <literal>UserDetailsService</literal> that can obtain authentication
  1588. information from a JDBC data source. Internally Spring JDBC is used,
  1589. so it avoids the complexity of a fully-featured object relational
  1590. mapper (ORM) just to store user details. If your application does
  1591. use an ORM tool, you might prefer to write a custom
  1592. <literal>UserDetailsService</literal> to reuse the mapping files
  1593. you've probably already created. Returning to
  1594. <literal>JdbcDaoImpl</literal>, an example configuration is shown
  1595. below:</para>
  1596. <para><programlisting>&lt;bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"&gt;
  1597. &lt;property name="driverClassName"&gt;&lt;value&gt;org.hsqldb.jdbcDriver&lt;/value&gt;&lt;/property&gt;
  1598. &lt;property name="url"&gt;&lt;value&gt;jdbc:hsqldb:hsql://localhost:9001&lt;/value&gt;&lt;/property&gt;
  1599. &lt;property name="username"&gt;&lt;value&gt;sa&lt;/value&gt;&lt;/property&gt;
  1600. &lt;property name="password"&gt;&lt;value&gt;&lt;/value&gt;&lt;/property&gt;
  1601. &lt;/bean&gt;
  1602. &lt;bean id="jdbcDaoImpl" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl"&gt;
  1603. &lt;property name="dataSource"&gt;&lt;ref bean="dataSource"/&gt;&lt;/property&gt;
  1604. &lt;/bean&gt; </programlisting></para>
  1605. <para>You can use different relational database management systems
  1606. by modifying the <literal>DriverManagerDataSource</literal> shown
  1607. above. You can also use a global data source obtained from JNDI, as
  1608. per normal Spring options. Irrespective of the database used and how
  1609. a <literal>DataSource</literal> is obtained, a standard schema must
  1610. be used as indicated in <literal>dbinit.txt</literal>. You can
  1611. download this file from the Spring Security web site.</para>
  1612. <para>If your default schema is unsuitable for your needs,
  1613. <literal>JdbcDaoImpl</literal> provides two properties that allow
  1614. customisation of the SQL statements. You may also subclass the
  1615. <literal>JdbcDaoImpl</literal> if further customisation is
  1616. necessary. Please refer to the JavaDocs for details, although please
  1617. note that the class is not intended for complex custom subclasses.
  1618. If you have complex needs (such as a special schema or would like a
  1619. certain <literal>UserDetails</literal> implementation returned),
  1620. you'd be better off writing your own
  1621. <literal>UserDetailsService</literal>. The base implementation
  1622. provided with Spring Security is intended for typical situations,
  1623. and does not offer infinite configuration flexibility.</para>
  1624. </sect2>
  1625. </sect1>
  1626. <sect1 id="concurrent-sessions">
  1627. <title>Concurrent Session Handling</title>
  1628. <para>Spring Security is able to prevent a principal from concurrently
  1629. authenticating to the same application more than a specified number of
  1630. times. Many ISVs take advantage of this to enforce licensing, whilst
  1631. network administrators like this feature because it helps prevent
  1632. people from sharing login names. You can, for example, stop user
  1633. "Batman" from logging onto the web application from two different
  1634. sessions.</para>
  1635. <para>To use concurrent session support, you'll need to add the
  1636. following to <literal>web.xml</literal>:</para>
  1637. <para><programlisting>&lt;listener&gt;
  1638. &lt;listener-class&gt;org.springframework.security.ui.session.HttpSessionEventPublisher&lt;/listener-class&gt;
  1639. &lt;/listener&gt; </programlisting></para>
  1640. <para>In addition, you will need to add the
  1641. <literal>org.springframework.security.concurrent.ConcurrentSessionFilter</literal>
  1642. to your <literal>FilterChainProxy</literal>. The
  1643. <classname>ConcurrentSessionFilter</classname> requires two
  1644. properties, <literal>sessionRegistry</literal>, which generally points
  1645. to an instance of <literal>SessionRegistryImpl</literal>, and
  1646. <literal>expiredUrl</literal>, which points to the page to display
  1647. when a session has expired.</para>
  1648. <para>The <literal>web.xml</literal>
  1649. <literal>HttpSessionEventPublisher</literal> causes an
  1650. <literal>ApplicationEvent</literal> to be published to the Spring
  1651. <literal>ApplicationContext</literal> every time a
  1652. <literal>HttpSession</literal> commences or terminates. This is
  1653. critical, as it allows the <literal>SessionRegistryImpl</literal> to
  1654. be notified when a session ends.</para>
  1655. <para>You will also need to wire up the
  1656. <literal>ConcurrentSessionControllerImpl</literal> and refer to it
  1657. from your <literal>ProviderManager</literal> bean:</para>
  1658. <para><programlisting>&lt;bean id="authenticationManager"
  1659. class="org.springframework.security.providers.ProviderManager"&gt;
  1660. &lt;property name="providers"&gt;
  1661. &lt;!-- your providers go here --&gt;
  1662. &lt;/property&gt;
  1663. &lt;property name="sessionController"&gt;&lt;ref bean="concurrentSessionController"/&gt;&lt;/property&gt;
  1664. &lt;/bean&gt;
  1665. &lt;bean id="concurrentSessionController"
  1666. class="org.springframework.security.concurrent.ConcurrentSessionControllerImpl"&gt;
  1667. &lt;property name="maximumSessions"&gt;&lt;value&gt;1&lt;/value&gt;&lt;/property&gt;
  1668. &lt;property name="sessionRegistry"&gt;&lt;ref local="sessionRegistry"/&gt;&lt;/property&gt;
  1669. &lt;/bean&gt;
  1670. &lt;bean id="sessionRegistry" class="org.springframework.security.concurrent.SessionRegistryImpl"/&gt;</programlisting></para>
  1671. </sect1>
  1672. <sect1 id="authentication-taglibs">
  1673. <title>Authentication Tag Libraries</title>
  1674. <para><literal>AuthenticationTag</literal> is used to simply output a
  1675. property of the current principal's
  1676. <literal>Authentication.getPrincipal()</literal> object to the web
  1677. page.</para>
  1678. <para>The following JSP fragment illustrates how to use the
  1679. <literal>AuthenticationTag</literal>:</para>
  1680. <para><programlisting>&lt;security:authentication operation="username"/&gt;</programlisting></para>
  1681. <para>This tag would cause the principal's name to be output. Here we
  1682. are assuming the <literal>Authentication.getPrincipal()</literal> is a
  1683. <literal>UserDetails</literal> object, which is generally the case
  1684. when using the typical
  1685. <literal>DaoAuthenticationProvider</literal>.</para>
  1686. </sect1>
  1687. </chapter>
  1688. <chapter id="dao-provider">
  1689. <title>DAO Authentication Provider</title>
  1690. <sect1 id="dao-provider-overview">
  1691. <title>Overview</title>
  1692. <para>Spring Security includes a production-quality
  1693. <literal>AuthenticationProvider</literal> implementation called
  1694. <literal>DaoAuthenticationProvider</literal>. This authentication
  1695. provider is compatible with all of the authentication mechanisms that
  1696. generate a <literal>UsernamePasswordAuthenticationToken</literal>, and
  1697. is probably the most commonly used provider in the framework. Like
  1698. most of the other authentication providers, the
  1699. DaoAuthenticationProvider leverages a UserDetailsService in order to
  1700. lookup the username, password and GrantedAuthority[]s. Unlike most of
  1701. the other authentication providers that leverage UserDetailsService,
  1702. this authentication provider actually requires the password to be
  1703. presented, and the provider will actually evaluate the validity or
  1704. otherwise of the password presented in an authentication request
  1705. object.</para>
  1706. </sect1>
  1707. <sect1 id="dao-provider-config">
  1708. <title>Configuration</title>
  1709. <para>Aside from adding DaoAuthenticationProvider to your
  1710. ProviderManager list (as discussed at the start of this part of the
  1711. reference guide), and ensuring a suitable authentication mechanism is
  1712. configured to present a UsernamePasswordAuthenticationToken, the
  1713. configuration of the provider itself is rather simple:</para>
  1714. <para><programlisting>&lt;bean id="daoAuthenticationProvider"
  1715. class="org.springframework.security.providers.dao.DaoAuthenticationProvider"&gt;
  1716. &lt;property name="userDetailsService"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
  1717. &lt;property name="saltSource"&gt;&lt;ref bean="saltSource"/&gt;&lt;/property&gt;
  1718. &lt;property name="passwordEncoder"&gt;&lt;ref bean="passwordEncoder"/&gt;&lt;/property&gt;
  1719. &lt;/bean&gt; </programlisting></para>
  1720. <para>The <literal>PasswordEncoder</literal> and
  1721. <literal>SaltSource</literal> are optional. A
  1722. <literal>PasswordEncoder</literal> provides encoding and decoding of
  1723. passwords presented in the <literal>UserDetails</literal> object that
  1724. is returned from the configured <literal>UserDetailsService</literal>.
  1725. A <literal>SaltSource</literal> enables the passwords to be populated
  1726. with a "salt", which enhances the security of the passwords in the
  1727. authentication repository. <literal>PasswordEncoder</literal>
  1728. implementations are provided with Spring Security covering MD5, SHA
  1729. and cleartext encodings. Two <literal>SaltSource</literal>
  1730. implementations are also provided:
  1731. <literal>SystemWideSaltSource</literal> which encodes all passwords
  1732. with the same salt, and <literal>ReflectionSaltSource</literal>, which
  1733. inspects a given property of the returned
  1734. <literal>UserDetails</literal> object to obtain the salt. Please refer
  1735. to the JavaDocs for further details on these optional features.</para>
  1736. <para>In addition to the properties above, the
  1737. <literal>DaoAuthenticationProvider</literal> supports optional caching
  1738. of <literal>UserDetails</literal> objects. The
  1739. <literal>UserCache</literal> interface enables the
  1740. <literal>DaoAuthenticationProvider</literal> to place a
  1741. <literal>UserDetails</literal> object into the cache, and retrieve it
  1742. from the cache upon subsequent authentication attempts for the same
  1743. username. By default the <literal>DaoAuthenticationProvider</literal>
  1744. uses the <literal>NullUserCache</literal>, which performs no caching.
  1745. A usable caching implementation is also provided,
  1746. <literal>EhCacheBasedUserCache</literal>, which is configured as
  1747. follows:</para>
  1748. <para><programlisting>&lt;bean id="daoAuthenticationProvider"
  1749. class="org.springframework.security.providers.dao.DaoAuthenticationProvider"&gt;
  1750. &lt;property name="userDetailsService"&gt;&lt;ref bean="userDetailsService"/&gt;&lt;/property&gt;
  1751. &lt;property name="userCache"&gt;&lt;ref bean="userCache"/&gt;&lt;/property&gt;
  1752. &lt;/bean&gt;
  1753. &lt;bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"&gt;
  1754. &lt;property name="configLocation"&gt;
  1755. &lt;value&gt;classpath:/ehcache-failsafe.xml&lt;/value&gt;
  1756. &lt;/property&gt;
  1757. &lt;/bean&gt;
  1758. &lt;bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;
  1759. &lt;property name="cacheManager"&gt;
  1760. &lt;ref local="cacheManager"/&gt;
  1761. &lt;/property&gt;
  1762. &lt;property name="cacheName"&gt;
  1763. &lt;value&gt;userCache&lt;/value&gt;
  1764. &lt;/property&gt;
  1765. &lt;/bean&gt;
  1766. &lt;bean id="userCache" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache"&gt;
  1767. &lt;property name="cache"&gt;&lt;ref local="userCacheBackend"/&gt;&lt;/property&gt;
  1768. &lt;/bean&gt; </programlisting></para>
  1769. <para>All Spring Security EH-CACHE implementations (including
  1770. <literal>EhCacheBasedUserCache</literal>) require an EH-CACHE
  1771. <literal>Cache</literal> object. The <literal>Cache</literal> object
  1772. can be obtained from wherever you like, although we recommend you use
  1773. Spring's factory classes as shown in the above configuration. If using
  1774. Spring's factory classes, please refer to the Spring documentation for
  1775. further details on how to optimise the cache storage location, memory
  1776. usage, eviction policies, timeouts etc.</para>
  1777. <para>A design decision was made not to support account locking in the
  1778. <literal>DaoAuthenticationProvider</literal>, as doing so would have
  1779. increased the complexity of the <literal>UserDetailsService</literal>
  1780. interface. For instance, a method would be required to increase the
  1781. count of unsuccessful authentication attempts. Such functionality
  1782. could be easily provided by leveraging the application event
  1783. publishing features discussed below.</para>
  1784. <para><literal>DaoAuthenticationProvider</literal> returns an
  1785. <literal>Authentication</literal> object which in turn has its
  1786. <literal>principal</literal> property set. The principal will be
  1787. either a <literal>String</literal> (which is essentially the username)
  1788. or a <literal>UserDetails</literal> object (which was looked up from
  1789. the <literal>UserDetailsService</literal>). By default the
  1790. <literal>UserDetails</literal> is returned, as this enables
  1791. applications to add extra properties potentially of use in
  1792. applications, such as the user's full name, email address etc. If
  1793. using container adapters, or if your applications were written to
  1794. operate with <literal>String</literal>s (as was the case for releases
  1795. prior to Spring Security 0.6), you should set the
  1796. <literal>DaoAuthenticationProvider.forcePrincipalAsString</literal>
  1797. property to <literal>true</literal> in your application context</para>
  1798. </sect1>
  1799. </chapter>
  1800. <chapter id="jaas">
  1801. <title>Java Authentication and Authorization Service (JAAS)
  1802. Provider</title>
  1803. <sect1 id="jaas-overview">
  1804. <title>Overview</title>
  1805. <para>Spring Security provides a package able to delegate
  1806. authentication requests to the Java Authentication and Authorization
  1807. Service (JAAS). This package is discussed in detail below.</para>
  1808. <para>Central to JAAS operation are login configuration files. To
  1809. learn more about JAAS login configuration files, consult the JAAS
  1810. reference documentation available from Sun Microsystems. We expect you
  1811. to have a basic understanding of JAAS and its login configuration file
  1812. syntax in order to understand this section.</para>
  1813. </sect1>
  1814. <sect1 id="jaas-config">
  1815. <title>Configuration</title>
  1816. <para>The <literal>JaasAuthenticationProvider</literal> attempts to
  1817. authenticate a user’s principal and credentials through JAAS.</para>
  1818. <para>Let’s assume we have a JAAS login configuration file,
  1819. <literal>/WEB-INF/login.conf</literal>, with the following
  1820. contents:</para>
  1821. <para><programlisting>JAASTest {
  1822. sample.SampleLoginModule required;
  1823. };</programlisting></para>
  1824. <para>Like all Spring Security beans, the
  1825. <literal>JaasAuthenticationProvider</literal> is configured via the
  1826. application context. The following definitions would correspond to the
  1827. above JAAS login configuration file:</para>
  1828. <para><programlisting>
  1829. &lt;bean id="jaasAuthenticationProvider"
  1830. class="org.springframework.security.providers.jaas.JaasAuthenticationProvider"&gt;
  1831. &lt;property name="loginConfig"&gt;
  1832. &lt;value&gt;/WEB-INF/login.conf&lt;/value&gt;
  1833. &lt;/property&gt;
  1834. &lt;property name="loginContextName"&gt;
  1835. &lt;value&gt;JAASTest&lt;/value&gt;
  1836. &lt;/property&gt;
  1837. &lt;property name="callbackHandlers"&gt;
  1838. &lt;list&gt;
  1839. &lt;bean class="org.springframework.security.providers.jaas.JaasNameCallbackHandler"/&gt;
  1840. &lt;bean class="org.springframework.security.providers.jaas.JaasPasswordCallbackHandler"/&gt;
  1841. &lt;/list&gt;
  1842. &lt;/property&gt;
  1843. &lt;property name="authorityGranters"&gt;
  1844. &lt;list&gt;
  1845. &lt;bean class="org.springframework.security.providers.jaas.TestAuthorityGranter"/&gt;
  1846. &lt;/list&gt;
  1847. &lt;/property&gt;
  1848. &lt;/bean&gt;
  1849. </programlisting></para>
  1850. <para>The <literal>CallbackHandler</literal>s and
  1851. <literal>AuthorityGranter</literal>s are discussed below.</para>
  1852. <sect2 id="jaas-callbackhandler">
  1853. <title id="jaas-callback-handler">JAAS CallbackHandler</title>
  1854. <para>Most JAAS <literal>LoginModule</literal>s require a callback
  1855. of some sort. These callbacks are usually used to obtain the
  1856. username and password from the user.</para>
  1857. <para>In a Spring Security deployment, Spring Security is
  1858. responsible for this user interaction (via the authentication
  1859. mechanism). Thus, by the time the authentication request is
  1860. delegated through to JAAS, Spring Security's authentication
  1861. mechanism will already have fully-populated an
  1862. <literal>Authentication</literal> object containing all the
  1863. information required by the JAAS
  1864. <literal>LoginModule</literal>.</para>
  1865. <para>Therefore, the JAAS package for Spring Security provides two
  1866. default callback handlers,
  1867. <literal>JaasNameCallbackHandler</literal> and
  1868. <literal>JaasPasswordCallbackHandler</literal>. Each of these
  1869. callback handlers implement
  1870. <literal>JaasAuthenticationCallbackHandler</literal>. In most cases
  1871. these callback handlers can simply be used without understanding the
  1872. internal mechanics.</para>
  1873. <para>For those needing full control over the callback behavior,
  1874. internally <literal>JaasAutheticationProvider</literal> wraps these
  1875. <literal>JaasAuthenticationCallbackHandler</literal>s with an
  1876. <literal>InternalCallbackHandler</literal>. The
  1877. <literal>InternalCallbackHandler</literal> is the class that
  1878. actually implements JAAS’ normal <literal>CallbackHandler</literal>
  1879. interface. Any time that the JAAS <literal>LoginModule</literal> is
  1880. used, it is passed a list of application context configured
  1881. <literal>InternalCallbackHandler</literal>s. If the
  1882. <literal>LoginModule</literal> requests a callback against the
  1883. <literal>InternalCallbackHandler</literal>s, the callback is in-turn
  1884. passed to the <literal>JaasAuthenticationCallbackHandler</literal>s
  1885. being wrapped.</para>
  1886. </sect2>
  1887. <sect2 id="jaas-authoritygranter">
  1888. <title id="jaas-authority-granter">JAAS AuthorityGranter</title>
  1889. <para>JAAS works with principals. Even "roles" are represented as
  1890. principals in JAAS. Spring Security, on the other hand, works with
  1891. <literal>Authentication</literal> objects. Each
  1892. <literal>Authentication</literal> object contains a single
  1893. principal, and multiple <literal>GrantedAuthority</literal>[]s. To
  1894. facilitate mapping between these different concepts, Spring
  1895. Security's JAAS package includes an
  1896. <literal>AuthorityGranter</literal> interface.</para>
  1897. <para>An <literal>AuthorityGranter</literal> is responsible for
  1898. inspecting a JAAS principal and returning a
  1899. <literal>String</literal>. The
  1900. <literal>JaasAuthenticationProvider</literal> then creates a
  1901. <literal>JaasGrantedAuthority</literal> (which implements Spring
  1902. Security’s <literal>GrantedAuthority</literal> interface) containing
  1903. both the <literal>AuthorityGranter</literal>-returned
  1904. <literal>String</literal> and the JAAS principal that the
  1905. <literal>AuthorityGranter</literal> was passed. The
  1906. <literal>JaasAuthenticationProvider</literal> obtains the JAAS
  1907. principals by firstly successfully authenticating the user’s
  1908. credentials using the JAAS <literal>LoginModule</literal>, and then
  1909. accessing the <literal>LoginContext</literal> it returns. A call to
  1910. <literal>LoginContext.getSubject().getPrincipals()</literal> is
  1911. made, with each resulting principal passed to each
  1912. <literal>AuthorityGranter</literal> defined against the
  1913. <literal>JaasAuthenticationProvider.setAuthorityGranters(List)</literal>
  1914. property.</para>
  1915. <para>Spring Security does not include any production
  1916. <literal>AuthorityGranter</literal>s given that every JAAS principal
  1917. has an implementation-specific meaning. However, there is a
  1918. <literal>TestAuthorityGranter</literal> in the unit tests that
  1919. demonstrates a simple <literal>AuthorityGranter</literal>
  1920. implementation.</para>
  1921. </sect2>
  1922. </sect1>
  1923. </chapter>
  1924. <chapter id="siteminder">
  1925. <title>Siteminder Authentication Mechanism</title>
  1926. <sect1 id="siteminder-overview">
  1927. <title>Overview</title>
  1928. <para>Siteminder is a commercial single sign on solution by Computer
  1929. Associates.</para>
  1930. <para>Spring Security provides a filter,
  1931. <literal>SiteminderAuthenticationProcessingFilter</literal> and
  1932. provider, <literal>SiteminderAuthenticationProvider</literal> that can
  1933. be used to process requests that have been pre-authenticated by
  1934. Siteminder. This filter assumes that you're using Siteminder for
  1935. <emphasis>authentication</emphasis>, and that you're using Spring
  1936. Security for <emphasis>authorization</emphasis>. The use of Siteminder
  1937. for <emphasis>authorization</emphasis> is not yet directly supported
  1938. by Spring Security.</para>
  1939. <para>When using Siteminder, an agent is setup on your web server to
  1940. intercept a principal's first call to your application. The agent
  1941. redirects the web request to a single sign-on login page, and once
  1942. authenticated, your application receives the request. Inside the HTTP
  1943. request is a header - such as <literal>SM_USER</literal> - which
  1944. identifies the authenticated principal (please refer to your
  1945. organization's "single sign-on" group for header details in your
  1946. particular configuration).</para>
  1947. </sect1>
  1948. <sect1 id="siteminder-config">
  1949. <title>Configuration</title>
  1950. <para>The first step in setting up Spring Security's Siteminder
  1951. support is to define the authentication mechanism that will inspect
  1952. the HTTP header discussed earlier. It will be responsible for
  1953. generating a <literal>UsernamePasswordAuthenticationToken</literal>
  1954. that is later sent to the
  1955. <literal>SiteminderAuthenticationProvider</literal>. Let's look at an
  1956. example:</para>
  1957. <para><programlisting>&lt;bean id="authenticationProcessingFilter"
  1958. class="org.springframework.security.ui.webapp.SiteminderAuthenticationProcessingFilter"&gt;
  1959. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  1960. &lt;property name="authenticationFailureUrl"&gt;&lt;value&gt;/login.jsp?login_error=1&lt;/value&gt;&lt;/property&gt;
  1961. &lt;property name="defaultTargetUrl"&gt;&lt;value&gt;/security.do?method=getMainMenu&lt;/value&gt;&lt;/property&gt;
  1962. &lt;property name="filterProcessesUrl"&gt;&lt;value&gt;/j_spring_security_check&lt;/value&gt;&lt;/property&gt;
  1963. &lt;property name="siteminderUsernameHeaderKey"&gt;&lt;value&gt;SM_USER&lt;/value&gt;&lt;/property&gt;
  1964. &lt;property name="formUsernameParameterKey"&gt;&lt;value&gt;j_username&lt;/value&gt;&lt;/property&gt;
  1965. &lt;/bean&gt;</programlisting></para>
  1966. <para>In our example above, the bean is being provided an
  1967. <literal>AuthenticationManager</literal>, as is normally needed by
  1968. authentication mechanisms. Several URLs are also specified, with the
  1969. values being self-explanatory. It's important to also specify the HTTP
  1970. header that Spring Security should inspect. If you additionally want
  1971. to support form-based authentication (i.e. in your development
  1972. environment where Siteminder is not installed), specify the form's
  1973. username parameter as well - just don't do this in production!</para>
  1974. <para>Note that you'll need a
  1975. <literal><literal>SiteminderAuthenticationProvider</literal></literal>
  1976. configured against your <literal>ProviderManager</literal> in order to
  1977. use the Siteminder authentication mechanism. Normally an
  1978. <literal>AuthenticationProvider</literal> expects the password
  1979. property to match what it retrieves from the
  1980. <literal>UserDetailsSource</literal>, but in this case, authentication
  1981. has already been handled by Siteminder, so password property is not
  1982. even relevant. This may sound like a security weakness, but remember
  1983. that users have to authenticate with Siteminder before your
  1984. application ever receives the requests, so the purpose of your custom
  1985. <literal>UserDetailsService</literal> should simply be to build the
  1986. complete <literal>Authentication</literal> object (ie with suitable
  1987. <literal>GrantedAuthority[]</literal>s).</para>
  1988. <para>Advanced tip and word to the wise: If you additionally want to
  1989. support form-based authentication in your development environment
  1990. (where Siteminder is typically not installed), specify the form's
  1991. username parameter as well. Just don't do this in production!</para>
  1992. </sect1>
  1993. </chapter>
  1994. <chapter id="runas">
  1995. <title>Run-As Authentication Replacement</title>
  1996. <sect1 id="runas-overview">
  1997. <title>Overview</title>
  1998. <para>The <literal>AbstractSecurityInterceptor</literal> is able to
  1999. temporarily replace the <literal>Authentication</literal> object in
  2000. the <literal>SecurityContext</literal> and
  2001. <literal>SecurityContextHolder</literal> during the secure object
  2002. callback phase. This only occurs if the original
  2003. <literal>Authentication</literal> object was successfully processed by
  2004. the <literal>AuthenticationManager</literal> and
  2005. <literal>AccessDecisionManager</literal>. The
  2006. <literal>RunAsManager</literal> will indicate the replacement
  2007. <literal>Authentication</literal> object, if any, that should be used
  2008. during the <literal>SecurityInterceptorCallback</literal>.</para>
  2009. <para>By temporarily replacing the <literal>Authentication</literal>
  2010. object during the secure object callback phase, the secured invocation
  2011. will be able to call other objects which require different
  2012. authentication and authorization credentials. It will also be able to
  2013. perform any internal security checks for specific
  2014. <literal>GrantedAuthority</literal> objects. Because Spring Security
  2015. provides a number of helper classes that automatically configure
  2016. remoting protocols based on the contents of the
  2017. <literal>SecurityContextHolder</literal>, these run-as replacements
  2018. are particularly useful when calling remote web services</para>
  2019. </sect1>
  2020. <sect1 id="runas-config">
  2021. <title>Configuration</title>
  2022. <para>A <literal>RunAsManager</literal> interface is provided by Acegi
  2023. Security:</para>
  2024. <para><programlisting>public Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config);
  2025. public boolean supports(ConfigAttribute attribute);
  2026. public boolean supports(Class clazz);</programlisting></para>
  2027. <para>The first method returns the <literal>Authentication</literal>
  2028. object that should replace the existing
  2029. <literal>Authentication</literal> object for the duration of the
  2030. method invocation. If the method returns <literal>null</literal>, it
  2031. indicates no replacement should be made. The second method is used by
  2032. the <literal>AbstractSecurityInterceptor</literal> as part of its
  2033. startup validation of configuration attributes. The
  2034. <literal>supports(Class)</literal> method is called by a security
  2035. interceptor implementation to ensure the configured
  2036. <literal>RunAsManager</literal> supports the type of secure object
  2037. that the security interceptor will present.</para>
  2038. <para>One concrete implementation of a <literal>RunAsManager</literal>
  2039. is provided with Spring Security. The
  2040. <literal>RunAsManagerImpl</literal> class returns a replacement
  2041. <literal>RunAsUserToken</literal> if any
  2042. <literal>ConfigAttribute</literal> starts with
  2043. <literal>RUN_AS_</literal>. If any such
  2044. <literal>ConfigAttribute</literal> is found, the replacement
  2045. <literal>RunAsUserToken</literal> will contain the same principal,
  2046. credentials and granted authorities as the original
  2047. <literal>Authentication</literal> object, along with a new
  2048. <literal>GrantedAuthorityImpl</literal> for each
  2049. <literal>RUN_AS_</literal> <literal>ConfigAttribute</literal>. Each
  2050. new <literal>GrantedAuthorityImpl</literal> will be prefixed with
  2051. <literal>ROLE_</literal>, followed by the <literal>RUN_AS</literal>
  2052. <literal>ConfigAttribute</literal>. For example, a
  2053. <literal>RUN_AS_SERVER</literal> will result in the replacement
  2054. <literal>RunAsUserToken</literal> containing a
  2055. <literal>ROLE_RUN_AS_SERVER</literal> granted authority.</para>
  2056. <para>The replacement <literal>RunAsUserToken</literal> is just like
  2057. any other <literal>Authentication</literal> object. It needs to be
  2058. authenticated by the <literal>AuthenticationManager</literal>,
  2059. probably via delegation to a suitable
  2060. <literal>AuthenticationProvider</literal>. The
  2061. <literal>RunAsImplAuthenticationProvider</literal> performs such
  2062. authentication. It simply accepts as valid any
  2063. <literal>RunAsUserToken</literal> presented.</para>
  2064. <para>To ensure malicious code does not create a
  2065. <literal>RunAsUserToken</literal> and present it for guaranteed
  2066. acceptance by the <literal>RunAsImplAuthenticationProvider</literal>,
  2067. the hash of a key is stored in all generated tokens. The
  2068. <literal>RunAsManagerImpl</literal> and
  2069. <literal>RunAsImplAuthenticationProvider</literal> is created in the
  2070. bean context with the same key:</para>
  2071. <para><programlisting>
  2072. &lt;bean id="runAsManager" class="org.springframework.security.runas.RunAsManagerImpl"&gt;
  2073. &lt;property name="key"&gt;&lt;value&gt;my_run_as_password&lt;/value&gt;&lt;/property&gt;
  2074. &lt;/bean&gt;
  2075. &lt;bean id="runAsAuthenticationProvider"
  2076. class="org.springframework.security.runas.RunAsImplAuthenticationProvider"&gt;
  2077. &lt;property name="key"&gt;&lt;value&gt;my_run_as_password&lt;/value&gt;&lt;/property&gt;
  2078. &lt;/bean&gt;
  2079. </programlisting></para>
  2080. <para>By using the same key, each <literal>RunAsUserToken</literal>
  2081. can be validated it was created by an approved
  2082. <literal>RunAsManagerImpl</literal>. The
  2083. <literal>RunAsUserToken</literal> is immutable after creation for
  2084. security reasons</para>
  2085. </sect1>
  2086. </chapter>
  2087. <chapter id="form">
  2088. <title>Form Authentication Mechanism</title>
  2089. <sect1 id="form-overview">
  2090. <title>Overview</title>
  2091. <para>HTTP Form Authentication involves using the
  2092. <literal>AuthenticationProcessingFilter</literal> to process a login
  2093. form. This is the most common way that application authenticate end
  2094. users. Form-based authentication is entirely compatible with the DAO
  2095. and JAAS authentication providers.</para>
  2096. </sect1>
  2097. <sect1 id="form-config">
  2098. <title>Configuration</title>
  2099. <para>The login form simply contains <literal>j_username</literal> and
  2100. <literal>j_password</literal> input fields, and posts to a URL that is
  2101. monitored by the filter (by default
  2102. <literal>j_spring_security_check</literal>). The filter is defined in
  2103. <literal>web.xml</literal> behind a
  2104. <literal>FilterToBeanProxy</literal> as follows:</para>
  2105. <para><programlisting>&lt;filter&gt;
  2106. &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt;
  2107. &lt;filter-class&gt;org.springframework.security.util.FilterToBeanProxy&lt;/filter-class&gt;
  2108. &lt;init-param&gt;
  2109. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  2110. &lt;param-value&gt;org.springframework.security.ui.webapp.AuthenticationProcessingFilter&lt;/param-value&gt;
  2111. &lt;/init-param&gt;
  2112. &lt;/filter&gt;
  2113. &lt;filter-mapping&gt;
  2114. &lt;filter-name&gt;Acegi Authentication Processing Filter&lt;/filter-name&gt;
  2115. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  2116. &lt;/filter-mapping&gt;</programlisting></para>
  2117. <para>For a discussion of <literal>FilterToBeanProxy</literal>, please
  2118. refer to the Filters section. The application context will need to
  2119. define the <literal>AuthenticationProcessingFilter</literal>:</para>
  2120. <para><programlisting>&lt;bean id="authenticationProcessingFilter"
  2121. class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter"&gt;
  2122. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  2123. &lt;property name="authenticationFailureUrl"&gt;&lt;value&gt;/acegilogin.jsp?login_error=1&lt;/value&gt;&lt;/property&gt;
  2124. &lt;property name="defaultTargetUrl"&gt;&lt;value&gt;/&lt;/value&gt;&lt;/property&gt;
  2125. &lt;property name="filterProcessesUrl"&gt;&lt;value&gt;/j_spring_security_check&lt;/value&gt;&lt;/property&gt;
  2126. &lt;/bean&gt; </programlisting></para>
  2127. <para>The configured <literal>AuthenticationManager</literal>
  2128. processes each authentication request. If authentication fails, the
  2129. browser will be redirected to the
  2130. <literal>authenticationFailureUrl</literal>. The
  2131. <literal>AuthenticationException</literal> will be placed into the
  2132. <literal>HttpSession</literal> attribute indicated by
  2133. <literal>AbstractProcessingFilter.ACEGI_SECURITY_LAST_EXCEPTION_KEY</literal>,
  2134. enabling a reason to be provided to the user on the error page.</para>
  2135. <para>If authentication is successful, the resulting
  2136. <literal>Authentication</literal> object will be placed into the
  2137. <literal>SecurityContextHolder</literal>.</para>
  2138. <para>Once the <literal>SecurityContextHolder</literal> has been
  2139. updated, the browser will need to be redirected to the target URL. The
  2140. target URL is usually indicated by the <literal>HttpSession</literal>
  2141. attribute specified by
  2142. <literal>AbstractProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY</literal>.
  2143. This attribute is automatically set by the
  2144. <literal>ExceptionTranslationFilter</literal> when an
  2145. <literal>AuthenticationException</literal> occurs, so that after login
  2146. is completed the user can return to what they were trying to access.
  2147. If for some reason the <literal>HttpSession</literal> does not
  2148. indicate the target URL, the browser will be redirected to the
  2149. <literal>defaultTargetUrl</literal> property.</para>
  2150. </sect1>
  2151. </chapter>
  2152. <chapter id="basic">
  2153. <title>BASIC Authentication Mechanism</title>
  2154. <sect1 id="basic-overview">
  2155. <title>Overview</title>
  2156. <para>Spring Security provides a
  2157. <literal>BasicProcessingFilter</literal> which is capable of
  2158. processing basic authentication credentials presented in HTTP headers.
  2159. This can be used for authenticating calls made by Spring remoting
  2160. protocols (such as Hessian and Burlap), as well as normal user agents
  2161. (such as Internet Explorer and Navigator). The standard governing HTTP
  2162. Basic Authentication is defined by RFC 1945, Section 11, and the
  2163. <literal>BasicProcessingFilter</literal> conforms with this RFC. Basic
  2164. Authentication is an attractive approach to authentication, because it
  2165. is very widely deployed in user agents and implementation is extremely
  2166. simple (it's just a Base64 encoding of the username:password,
  2167. specified in an HTTP header).</para>
  2168. </sect1>
  2169. <sect1 id="basic-config">
  2170. <title>Configuration</title>
  2171. <para>To implement HTTP Basic Authentication, it is necessary to
  2172. define <literal>BasicProcessingFilter</literal> in the filter chain.
  2173. The application context will need to define the
  2174. <literal>BasicProcessingFilter</literal> and its required
  2175. collaborator:</para>
  2176. <para><programlisting>
  2177. &lt;bean id="basicProcessingFilter" class="org.springframework.security.ui.basicauth.BasicProcessingFilter"&gt;
  2178. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  2179. &lt;property name="authenticationEntryPoint"&gt;&lt;ref bean="authenticationEntryPoint"/&gt;&lt;/property&gt;
  2180. &lt;/bean&gt;
  2181. &lt;bean id="authenticationEntryPoint"
  2182. class="org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint"&gt;
  2183. &lt;property name="realmName"&gt;&lt;value&gt;Name Of Your Realm&lt;/value&gt;&lt;/property&gt;
  2184. &lt;/bean&gt;
  2185. </programlisting></para>
  2186. <para>The configured <literal>AuthenticationManager</literal>
  2187. processes each authentication request. If authentication fails, the
  2188. configured <literal>AuthenticationEntryPoint</literal> will be used to
  2189. retry the authentication process. Usually you will use the
  2190. <literal>BasicProcessingFilterEntryPoint</literal>, which returns a
  2191. 401 response with a suitable header to retry HTTP Basic
  2192. authentication. If authentication is successful, the resulting
  2193. <literal>Authentication</literal> object will be placed into the
  2194. <literal>SecurityContextHolder</literal>.</para>
  2195. <para>If the authentication event was successful, or authentication
  2196. was not attempted because the HTTP header did not contain a supported
  2197. authentication request, the filter chain will continue as normal. The
  2198. only time the filter chain will be interrupted is if authentication
  2199. fails and the <literal>AuthenticationEntryPoint</literal> is called,
  2200. as discussed in the previous paragraph</para>
  2201. </sect1>
  2202. </chapter>
  2203. <chapter id="digest">
  2204. <title>Digest Authentication</title>
  2205. <sect1 id="digest-overview">
  2206. <title>Overview</title>
  2207. <para>Spring Security provides a
  2208. <literal>DigestProcessingFilter</literal> which is capable of
  2209. processing digest authentication credentials presented in HTTP
  2210. headers. Digest Authentication attempts to solve many of the
  2211. weaknesses of Basic authentication, specifically by ensuring
  2212. credentials are never sent in clear text across the wire. Many user
  2213. agents support Digest Authentication, including FireFox and Internet
  2214. Explorer. The standard governing HTTP Digest Authentication is defined
  2215. by RFC 2617, which updates an earlier version of the Digest
  2216. Authentication standard prescribed by RFC 2069. Most user agents
  2217. implement RFC 2617. Spring Security
  2218. <literal>DigestProcessingFilter</literal> is compatible with the
  2219. "<literal>auth</literal>" quality of protection
  2220. (<literal>qop</literal>) prescribed by RFC 2617, which also provides
  2221. backward compatibility with RFC 2069. Digest Authentication is a
  2222. highly attractive option if you need to use unencrypted HTTP (ie no
  2223. TLS/HTTPS) and wish to maximise security of the authentication
  2224. process. Indeed Digest Authentication is a mandatory requirement for
  2225. the WebDAV protocol, as noted by RFC 2518 Section 17.1, so we should
  2226. expect to see it increasingly deployed and replacing Basic
  2227. Authentication.</para>
  2228. <para>Digest Authentication is definitely the most secure choice
  2229. between Form Authentication, Basic Authentication and Digest
  2230. Authentication, although extra security also means more complex user
  2231. agent implementations. Central to Digest Authentication is a "nonce".
  2232. This is a value the server generates. Spring Security's nonce adopts
  2233. the following format:</para>
  2234. <para><programlisting>base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
  2235. expirationTime: The date and time when the nonce expires, expressed in milliseconds
  2236. key: A private key to prevent modification of the nonce token
  2237. </programlisting></para>
  2238. <para>The <literal>DigestProcessingFilterEntryPoint</literal> has a
  2239. property specifying the <literal>key</literal> used for generating the
  2240. nonce tokens, along with a <literal>nonceValiditySeconds</literal>
  2241. property for determining the expiration time (default 300, which
  2242. equals five minutes). Whist ever the nonce is valid, the digest is
  2243. computed by concatenating various strings including the username,
  2244. password, nonce, URI being requested, a client-generated nonce (merely
  2245. a random value which the user agent generates each request), the realm
  2246. name etc, then performing an MD5 hash. Both the server and user agent
  2247. perform this digest computation, resulting in different hash codes if
  2248. they disagree on an included value (eg password). In Spring Security
  2249. implementation, if the server-generated nonce has merely expired (but
  2250. the digest was otherwise valid), the
  2251. <literal>DigestProcessingFilterEntryPoint</literal> will send a
  2252. <literal>"stale=true"</literal> header. This tells the user agent
  2253. there is no need to disturb the user (as the password and username etc
  2254. is correct), but simply to try again using a new nonce.</para>
  2255. <para>An appropriate value for
  2256. <literal>DigestProcessingFilterEntryPoint</literal>'s
  2257. <literal>nonceValiditySeconds</literal> parameter will depend on your
  2258. application. Extremely secure applications should note that an
  2259. intercepted authentication header can be used to impersonate the
  2260. principal until the <literal>expirationTime</literal> contained in the
  2261. nonce is reached. This is the key principle when selecting an
  2262. appropriate setting, but it would be unusual for immensely secure
  2263. applications to not be running over TLS/HTTPS in the first
  2264. instance.</para>
  2265. <para>Because of the more complex implementation of Digest
  2266. Authentication, there are often user agent issues. For example,
  2267. Internet Explorer fails to present an "<literal>opaque</literal>"
  2268. token on subsequent requests in the same session. Spring Security
  2269. filters therefore encapsulate all state information into the
  2270. "<literal>nonce</literal>" token instead. In our testing, Spring
  2271. Security implementation works reliably with FireFox and Internet
  2272. Explorer, correctly handling nonce timeouts etc.</para>
  2273. </sect1>
  2274. <sect1 id="digest-config">
  2275. <title>Configuration</title>
  2276. <para>Now that we've reviewed the theory, let's see how to use it. To
  2277. implement HTTP Digest Authentication, it is necessary to define
  2278. <literal>DigestProcessingFilter</literal> in the fitler chain. The
  2279. application context will need to define the
  2280. <literal>DigestProcessingFilter</literal> and its required
  2281. collaborators:</para>
  2282. <para><programlisting>
  2283. &lt;bean id="digestProcessingFilter" class="org.springframework.security.ui.digestauth.DigestProcessingFilter"&gt;
  2284. &lt;property name="userDetailsService"&gt;&lt;ref local="jdbcDaoImpl"/&gt;&lt;/property&gt;
  2285. &lt;property name="authenticationEntryPoint"&gt;&lt;ref local="digestProcessingFilterEntryPoint"/&gt;&lt;/property&gt;
  2286. &lt;property name="userCache"&gt;&lt;ref local="userCache"/&gt;&lt;/property&gt;
  2287. &lt;/bean&gt;
  2288. &lt;bean id="digestProcessingFilterEntryPoint"
  2289. class="org.springframework.security.ui.digestauth.DigestProcessingFilterEntryPoint"&gt;
  2290. &lt;property name="realmName"&gt;&lt;value&gt;Contacts Realm via Digest Authentication&lt;/value&gt;&lt;/property&gt;
  2291. &lt;property name="key"&gt;&lt;value&gt;acegi&lt;/value&gt;&lt;/property&gt;
  2292. &lt;property name="nonceValiditySeconds"&gt;&lt;value&gt;10&lt;/value&gt;&lt;/property&gt;
  2293. &lt;/bean&gt;
  2294. </programlisting></para>
  2295. <para>The configured <literal>UserDetailsService</literal> is needed
  2296. because <literal>DigestProcessingFilter</literal> must have direct
  2297. access to the clear text password of a user. Digest Authentication
  2298. will NOT work if you are using encoded passwords in your DAO. The DAO
  2299. collaborator, along with the <literal>UserCache</literal>, are
  2300. typically shared directly with a
  2301. <literal>DaoAuthenticationProvider</literal>. The
  2302. <literal>authenticationEntryPoint</literal> property must be
  2303. <literal>DigestProcessingFilterEntryPoint</literal>, so that
  2304. <literal>DigestProcessingFilter</literal> can obtain the correct
  2305. <literal>realmName</literal> and <literal>key</literal> for digest
  2306. calculations.</para>
  2307. <para>Like <literal>BasicAuthenticationFilter</literal>, if
  2308. authentication is successful an <literal>Authentication</literal>
  2309. request token will be placed into the
  2310. <literal>SecurityContextHolder</literal>. If the authentication event
  2311. was successful, or authentication was not attempted because the HTTP
  2312. header did not contain a Digest Authentication request, the filter
  2313. chain will continue as normal. The only time the filter chain will be
  2314. interrupted is if authentication fails and the
  2315. <literal>AuthenticationEntryPoint</literal> is called, as discussed in
  2316. the previous paragraph.</para>
  2317. <para>Digest Authentication's RFC offers a range of additional
  2318. features to further increase security. For example, the nonce can be
  2319. changed on every request. Despite this, Spring Security implementation
  2320. was designed to minimise the complexity of the implementation (and the
  2321. doubtless user agent incompatibilities that would emerge), and avoid
  2322. needing to store server-side state. You are invited to review RFC 2617
  2323. if you wish to explore these features in more detail. As far as we are
  2324. aware, Spring Security's implementation does comply with the minimum
  2325. standards of this RFC.</para>
  2326. </sect1>
  2327. </chapter>
  2328. <chapter id="anonymous">
  2329. <title>Anonymous Authentication</title>
  2330. <sect1 id="anonymous-overview">
  2331. <title>Overview</title>
  2332. <para>Particularly in the case of web request URI security, sometimes
  2333. it is more convenient to assign configuration attributes against every
  2334. possible secure object invocation. Put differently, sometimes it is
  2335. nice to say <literal>ROLE_SOMETHING</literal> is required by default
  2336. and only allow certain exceptions to this rule, such as for login,
  2337. logout and home pages of an application. There are also other
  2338. situations where anonymous authentication would be desired, such as
  2339. when an auditing interceptor queries the
  2340. <literal>SecurityContextHolder</literal> to identify which principal
  2341. was responsible for a given operation. Such classes can be authored
  2342. with more robustness if they know the
  2343. <literal>SecurityContextHolder</literal> always contains an
  2344. <literal>Authentication</literal> object, and never
  2345. <literal>null</literal>.</para>
  2346. </sect1>
  2347. <sect1 id="anonymous-config">
  2348. <title>Configuration</title>
  2349. <para>Spring Security provides three classes that together provide an
  2350. anonymous authentication feature.
  2351. <literal>AnonymousAuthenticationToken</literal> is an implementation
  2352. of <literal>Authentication</literal>, and stores the
  2353. <literal>GrantedAuthority</literal>[]s which apply to the anonymous
  2354. principal. There is a corresponding
  2355. <literal>AnonymousAuthenticationProvider</literal>, which is chained
  2356. into the <literal>ProviderManager</literal> so that
  2357. <literal>AnonymousAuthenticationTokens</literal> are accepted.
  2358. Finally, there is an AnonymousProcessingFilter, which is chained after
  2359. the normal authentication mechanisms and automatically add an
  2360. <literal>AnonymousAuthenticationToken</literal> to the
  2361. <literal>SecurityContextHolder</literal> if there is no existing
  2362. <literal>Authentication</literal> held there. The definition of the
  2363. filter and authentication provider appears as follows:</para>
  2364. <para><programlisting>
  2365. &lt;bean id="anonymousProcessingFilter"
  2366. class="org.springframework.security.providers.anonymous.AnonymousProcessingFilter"&gt;
  2367. &lt;property name="key"&gt;&lt;value&gt;foobar&lt;/value&gt;&lt;/property&gt;
  2368. &lt;property name="userAttribute"&gt;&lt;value&gt;anonymousUser,ROLE_ANONYMOUS&lt;/value&gt;&lt;/property&gt;
  2369. &lt;/bean&gt;
  2370. &lt;bean id="anonymousAuthenticationProvider"
  2371. class="org.springframework.security.providers.anonymous.AnonymousAuthenticationProvider"&gt;
  2372. &lt;property name="key"&gt;&lt;value&gt;foobar&lt;/value&gt;&lt;/property&gt;
  2373. &lt;/bean&gt;
  2374. </programlisting></para>
  2375. <para>The <literal>key</literal> is shared between the filter and
  2376. authentication provider, so that tokens created by the former are
  2377. accepted by the latter. The <literal>userAttribute</literal> is
  2378. expressed in the form of
  2379. <literal>usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]</literal>.
  2380. This is the same syntax as used after the equals sign for
  2381. <literal>InMemoryDaoImpl</literal>'s <literal>userMap</literal>
  2382. property.</para>
  2383. <para>As explained earlier, the benefit of anonymous authentication is
  2384. that all URI patterns can have security applied to them. For
  2385. example:</para>
  2386. <para><programlisting>
  2387. &lt;bean id="filterInvocationInterceptor"
  2388. class="org.springframework.security.intercept.web.FilterSecurityInterceptor"&gt;
  2389. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  2390. &lt;property name="accessDecisionManager"&gt;&lt;ref local="httpRequestAccessDecisionManager"/&gt;&lt;/property&gt;
  2391. &lt;property name="objectDefinitionSource"&gt;
  2392. &lt;value&gt;
  2393. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  2394. PATTERN_TYPE_APACHE_ANT
  2395. /index.jsp=ROLE_ANONYMOUS,ROLE_USER
  2396. /hello.htm=ROLE_ANONYMOUS,ROLE_USER
  2397. /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER
  2398. /acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER
  2399. /**=ROLE_USER
  2400. &lt;/value&gt;
  2401. &lt;/property&gt;
  2402. &lt;/bean&gt;
  2403. </programlisting>Rounding out the anonymous authentication discussion
  2404. is the <literal>AuthenticationTrustResolver</literal> interface, with
  2405. its corresponding <literal>AuthenticationTrustResolverImpl</literal>
  2406. implementation. This interface provides an
  2407. <literal>isAnonymous(Authentication)</literal> method, which allows
  2408. interested classes to take into account this special type of
  2409. authentication status. The
  2410. <literal>ExceptionTranslationFilter</literal> uses this interface in
  2411. processing <literal>AccessDeniedException</literal>s. If an
  2412. <literal>AccessDeniedException</literal> is thrown, and the
  2413. authentication is of an anonymous type, instead of throwing a 403
  2414. (forbidden) response, the filter will instead commence the
  2415. <literal>AuthenticationEntryPoint</literal> so the principal can
  2416. authenticate properly. This is a necessary distinction, otherwise
  2417. principals would always be deemed "authenticated" and never be given
  2418. an opportunity to login via form, basic, digest or some other normal
  2419. authentication mechanism</para>
  2420. </sect1>
  2421. </chapter>
  2422. <chapter id="remember-me">
  2423. <title>Remember-Me Authentication</title>
  2424. <sect1 id="remember-me-overview">
  2425. <title>Overview</title>
  2426. <para>Remember-me authentication refers to web sites being able to
  2427. remember the identity of a principal between sessions. This is
  2428. typically accomplished by sending a cookie to the browser, with the
  2429. cookie being detected during future sessions and causing automated
  2430. login to take place. Spring Security provides the necessary hooks so
  2431. that such operations can take place, along with providing a concrete
  2432. implementation that uses hashing to preserve the security of
  2433. cookie-based tokens.</para>
  2434. </sect1>
  2435. <sect1 id="remember-me-config">
  2436. <title>Configuration</title>
  2437. <para>Remember-me authentication is not used with basic
  2438. authentication, given it is often not used with
  2439. <literal>HttpSession</literal>s. Remember-me is used with
  2440. <literal>AuthenticationProcessingFilter</literal>, and is implemented
  2441. via hooks in the <literal>AbstractProcessingFilter</literal>
  2442. superclass. The hooks will invoke a concrete
  2443. <literal>RememberMeServices</literal> at the appropriate times. The
  2444. interface looks like this:</para>
  2445. <para><programlisting>public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
  2446. public void loginFail(HttpServletRequest request, HttpServletResponse response);
  2447. public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication);</programlisting></para>
  2448. <para>Please refer to JavaDocs for a fuller discussion on what the
  2449. methods do, although note at this stage
  2450. <literal>AbstractProcessingFilter</literal> only calls the
  2451. <literal>loginFail()</literal> and <literal>loginSuccess()</literal>
  2452. methods. The <literal>autoLogin()</literal> method is called by
  2453. <literal>RememberMeProcessingFilter</literal> whenever the
  2454. <literal>SecurityContextHolder</literal> does not contain an
  2455. <literal>Authentication</literal>. This interface therefore provides
  2456. the underlaying remember-me implementation with sufficient
  2457. notification of authentication-related events, and delegates to the
  2458. implementation whenever a candidate web request might contain a cookie
  2459. and wish to be remembered.</para>
  2460. <para>This design allows any number of remember-me implementation
  2461. strategies. In the interests of simplicity and avoiding the need for
  2462. DAO implementations that specify write and create methods, Acegi
  2463. Security's only concrete implementation,
  2464. <literal>TokenBasedRememberMeServices</literal>, uses hashing to
  2465. achieve a useful remember-me strategy. In essence a cookie is sent to
  2466. the browser upon successful interactive authentication, with that
  2467. cookie being composed as follows:</para>
  2468. <para><programlisting>base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key))
  2469. username: As identifiable to TokenBasedRememberMeServices.getUserDetailsService()
  2470. password: That matches the relevant UserDetails retrieved from TokenBasedRememberMeServices.getUserDetailsService()
  2471. expirationTime: The date and time when the remember-me token expires, expressed in milliseconds
  2472. key: A private key to prevent modification of the remember-me token
  2473. </programlisting></para>
  2474. <para>As such the remember-me token is valid only for the period
  2475. specified, and provided that the username, password and key does not
  2476. change. Notably, this has a potential security issue in that a
  2477. captured remember-me token will be usable from any user agent until
  2478. such time as the token expires. This is the same issue as with digest
  2479. authentication. If a principal is aware a token has been captured,
  2480. they can easily change their password and immediately invalidate all
  2481. remember-me tokens on issue. However, if more significant security is
  2482. needed a rolling token approach should be used (this would require a
  2483. database) or remember-me services should simply not be used.</para>
  2484. <para><literal>TokenBasedRememberMeServices</literal> generates a
  2485. <literal>RememberMeAuthenticationToken</literal>, which is processed
  2486. by <literal>RememberMeAuthenticationProvider</literal>. A
  2487. <literal>key</literal> is shared between this authentication provider
  2488. and the <literal>TokenBasedRememberMeServices</literal>. In addition,
  2489. <literal>TokenBasedRememberMeServices</literal> requires A
  2490. UserDetailsService from which it can retrieve the username and
  2491. password for signature comparison purposes, and generate the
  2492. <literal>RememberMeAuthenticationToken</literal> to contain the
  2493. correct <literal>GrantedAuthority</literal>[]s. Some sort of logout
  2494. command should be provided by the application (typically via a JSP)
  2495. that invalidates the cookie upon user request. See the Contacts Sample
  2496. application's <literal>logout.jsp</literal> for an example.</para>
  2497. <para>The beans required in an application context to enable
  2498. remember-me services are as follows:</para>
  2499. <para><programlisting>
  2500. &lt;bean id="rememberMeProcessingFilter"
  2501. class="org.springframework.security.ui.rememberme.RememberMeProcessingFilter"&gt;
  2502. &lt;property name="rememberMeServices"&gt;&lt;ref local="rememberMeServices"/&gt;&lt;/property&gt;
  2503. &lt;/bean&gt;
  2504. &lt;bean id="rememberMeServices" class="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices"&gt;
  2505. &lt;property name="userDetailsService"&gt;&lt;ref local="jdbcDaoImpl"/&gt;&lt;/property&gt;
  2506. &lt;property name="key"&gt;&lt;value&gt;springRocks&lt;/value&gt;&lt;/property&gt;
  2507. &lt;/bean&gt;
  2508. &lt;bean id="rememberMeAuthenticationProvider"
  2509. class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider"&gt;
  2510. &lt;property name="key"&gt;&lt;value&gt;springRocks&lt;/value&gt;&lt;/property&gt;
  2511. &lt;/bean&gt;
  2512. </programlisting>Don't forget to add your
  2513. <literal>RememberMeServices</literal> implementation to your
  2514. <literal>AuthenticationProcessingFilter.setRememberMeServices()</literal>
  2515. property, include the
  2516. <literal>RememberMeAuthenticationProvider</literal> in your
  2517. <literal>AuthenticationManager.setProviders()</literal> list, and add
  2518. a call to <literal>RememberMeProcessingFilter</literal> into your
  2519. <literal>FilterChainProxy</literal> (typically immediately after your
  2520. <literal>AuthenticationProcessingFilter</literal>)</para>
  2521. </sect1>
  2522. </chapter>
  2523. <chapter id="x509">
  2524. <title>X509 Authentication</title>
  2525. <sect1 id="x509-overview">
  2526. <title>Overview</title>
  2527. <para>The most common use of X509 certificate authentication is in
  2528. verifying the identity of a server when using SSL, most commonly when
  2529. using HTTPS from a browser. The browser will automatically check that
  2530. the certificate presented by a server has been issued (ie digitally
  2531. signed) by one of a list of trusted certificate authorities which it
  2532. maintains.</para>
  2533. <para>You can also use SSL with <quote>mutual authentication</quote>;
  2534. the server will then request a valid certificate from the client as
  2535. part of the SSL handshake. The server will authenticate the client by
  2536. checking that it's certificate is signed by an acceptable authority.
  2537. If a valid certificate has been provided, it can be obtained through
  2538. the servlet API in an application. Spring Security X509 module
  2539. extracts the certificate using a filter and passes it to the
  2540. configured X509 authentication provider to allow any additional
  2541. application-specific checks to be applied. It also maps the
  2542. certificate to an application user and loads that user's set of
  2543. granted authorities for use with the standard Spring Security
  2544. infrastructure.</para>
  2545. <para>You should be familiar with using certificates and setting up
  2546. client authentication for your servlet container before attempting to
  2547. use it with Spring Security. Most of the work is in creating and
  2548. installing suitable certificates and keys. For example, if you're
  2549. using Tomcat then read the instructions here <ulink
  2550. url="http://jakarta.apache.org/tomcat/tomcat-5.0-doc/ssl-howto.html"></ulink>.
  2551. It's important that you get this working before trying it out with
  2552. Spring Security</para>
  2553. </sect1>
  2554. <sect1 id="x509-with-acegi">
  2555. <title>Using X509 with Spring Security</title>
  2556. <para>With X509 authentication, there is no explicit login procedure
  2557. so the implementation is relatively simple; there is no need to
  2558. redirect requests in order to interact with the user. As a result,
  2559. some of the classes behave slightly differently from their equivalents
  2560. in other packages. For example, the default <quote>entry point</quote>
  2561. class, which is normally responsible for starting the authentication
  2562. process, is only invoked if the certificate is rejected and it always
  2563. returns an error to the user. With a suitable bean configuration, the
  2564. normal sequence of events is as follows <orderedlist>
  2565. <listitem>
  2566. <para>The <classname>X509ProcessingFilter</classname> extracts
  2567. the certificate from the request and uses it as the credentials
  2568. for an authentication request. The generated authentication
  2569. request is an <classname>X509AuthenticationToken</classname>.
  2570. The request is passed to the authentication manager.</para>
  2571. </listitem>
  2572. <listitem>
  2573. <para>The <classname>X509AuthenticationProvider</classname>
  2574. receives the token. Its main concern is to obtain the user
  2575. information (in particular the user's granted authorities) that
  2576. matches the certificate. It delegates this responsibility to an
  2577. <interfacename>X509AuthoritiesPopulator</interfacename>.</para>
  2578. </listitem>
  2579. <listitem>
  2580. <para>The populator's single method,
  2581. <methodname>getUserDetails(X509Certificate
  2582. userCertificate)</methodname> is invoked. Implementations should
  2583. return a <classname>UserDetails</classname> instance containing
  2584. the array of <classname>GrantedAuthority</classname> objects for
  2585. the user. This method can also choose to reject the certificate
  2586. (for example if it doesn't contain a matching user name). In
  2587. such cases it should throw a
  2588. <exceptionname>BadCredentialsException</exceptionname>. A
  2589. DAO-based implementation,
  2590. <classname>DaoX509AuthoritiesPopulator</classname>, is provided
  2591. which extracts the user's name from the subject <quote>common
  2592. name</quote> (CN) in the certificate. It also allows you to set
  2593. your own regular expression to match a different part of the
  2594. subject's distinguished name. A UserDetailsService is used to
  2595. load the user information.<!-- TODO: Give email matching as an example --></para>
  2596. </listitem>
  2597. <listitem>
  2598. <para>If everything has gone smoothly then there should be a
  2599. valid <classname>Authentication</classname> object in the secure
  2600. context and the invocation will procede as normal. If no
  2601. certificate was found, or the certificate was rejected, then the
  2602. <classname>ExceptionTranslationFilter</classname> will invoke
  2603. the <classname>X509ProcessingFilterEntryPoint</classname> which
  2604. returns a 403 error (forbidden) to the user.</para>
  2605. </listitem>
  2606. </orderedlist></para>
  2607. </sect1>
  2608. <sect1 id="x509-config">
  2609. <title>Configuration</title>
  2610. <para>There is a version of the <link
  2611. linkend="contacts-sample">Contacts Sample Application</link> which
  2612. uses X509. Copy the beans and filter setup from this as a starting
  2613. point for configuring your own application. A set of example
  2614. certificates is also included which you can use to configure your
  2615. server. These are <itemizedlist>
  2616. <listitem>
  2617. <para><filename>user.p12</filename>: A PKCS12 format file
  2618. containing the client key and certificate. These should be
  2619. installed in your browser. It maps to a use in the
  2620. application.</para>
  2621. </listitem>
  2622. <listitem>
  2623. <para><filename>server.p12</filename>: The server certificate
  2624. and key for HTTPS connections.</para>
  2625. </listitem>
  2626. <listitem>
  2627. <para><filename>ca.jks</filename>: A Java keystore containing
  2628. the certificate for the authority which issued the user's
  2629. certificate. This will be used by the container to validate
  2630. client certificates.</para>
  2631. </listitem>
  2632. </itemizedlist> For JBoss 3.2.7 (with Tomcat 5.0), the SSL
  2633. configuration in the <filename>server.xml</filename> file looks like
  2634. this <programlisting>
  2635. &lt;!-- SSL/TLS Connector configuration --&gt;
  2636. &lt;Connector port="8443" address="${jboss.bind.address}"
  2637. maxThreads="100" minSpareThreads="5" maxSpareThreads="15"
  2638. scheme="https" secure="true"
  2639. sslProtocol = "TLS"
  2640. clientAuth="true" keystoreFile="${jboss.server.home.dir}/conf/server.p12"
  2641. keystoreType="PKCS12" keystorePass="password"
  2642. truststoreFile="${jboss.server.home.dir}/conf/ca.jks"
  2643. truststoreType="JKS" truststorePass="password"
  2644. /&gt;
  2645. </programlisting><parameter>clientAuth</parameter> can also be set to
  2646. <parameter>want</parameter> if you still want SSL connections to
  2647. succeed even if the client doesn't provide a certificate. Obviously
  2648. these clients won't be able to access any objects secured by Spring
  2649. Security (unless you use a non-X509 authentication mechanism, such as
  2650. BASIC authentication, to authenticate the user)</para>
  2651. </sect1>
  2652. </chapter>
  2653. <chapter id="ldap">
  2654. <title>LDAP Authentication</title>
  2655. <sect1 id="ldap-overview">
  2656. <title>Overview</title>
  2657. <para>LDAP is often used by organizations as a central repository for
  2658. user information and as an authentication service. It can also be used
  2659. to store the role information for application users.</para>
  2660. <para>There are many different scenarios for how an LDAP server may be
  2661. configured so Spring Security's LDAP provider is fully configurable.
  2662. It uses separate strategy interfaces for authentication and role
  2663. retrieval and provides default implementations which can be configured
  2664. to handle a wide range of situations.</para>
  2665. <para>You should be familiar with LDAP before trying to use it with
  2666. Spring Security. The following link provides a good introduction to
  2667. the concepts involved and a guide to setting up a directory using the
  2668. free LDAP server OpenLDAP: <ulink
  2669. url="http://www.zytrax.com/books/ldap/"></ulink>. Some familiarity
  2670. with the JNDI APIs used to access LDAP from Java may also be useful.
  2671. We don't use any third-party LDAP libraries (Mozilla/Netscape, JLDAP
  2672. etc.) in the LDAP provider.</para>
  2673. </sect1>
  2674. <sect1 id="ldap-with-acegi">
  2675. <title>Using LDAP with Spring Security</title>
  2676. <para>The main LDAP provider class is
  2677. <classname>org.springframework.security.providers.ldap.LdapAuthenticationProvider</classname>.
  2678. This bean doesn't actually do much itself other than implement the
  2679. <methodname>retrieveUser</methodname> method required by its base
  2680. class,
  2681. <classname>AbstractUserDetailsAuthenticationProvider</classname>. It
  2682. delegates the work to two other beans, an
  2683. <interfacename>LdapAuthenticator</interfacename> and an
  2684. <interfacename>LdapAuthoritiesPopulator</interfacename> which are
  2685. responsible for authenticating the user and retrieving the user's set
  2686. of <interfacename>GrantedAuthority</interfacename>s
  2687. respectively.</para>
  2688. <sect2 id="ldap-ldap-authenticators">
  2689. <title>LdapAuthenticator Implementations</title>
  2690. <para>The authenticator is also responsible for retrieving any
  2691. required user attributes. This is because the permissions on the
  2692. attributes may depend on the type of authentication being used. For
  2693. example, if binding as the user, it may be necessary to read them
  2694. with the user's own permissions.</para>
  2695. <para>There are currently two authentication strategies supplied
  2696. with Spring Security: <itemizedlist>
  2697. <listitem>
  2698. <para>Authentication directly to the LDAP server ("bind"
  2699. authentication).</para>
  2700. </listitem>
  2701. <listitem>
  2702. <para>Password comparison, where the password supplied by the
  2703. user is compared with the one stored in the repository. This
  2704. can either be done by retrieving the value of the password
  2705. attribute and checking it locally or by performing an LDAP
  2706. "compare" operation, where the supplied password is passed to
  2707. the server for comparison and the real password value is never
  2708. retrieved.</para>
  2709. </listitem>
  2710. </itemizedlist></para>
  2711. <sect3 id="ldap-ldap-authenticators-common">
  2712. <title>Common Functionality</title>
  2713. <para>Before it is possible to authenticate a user (by either
  2714. strategy), the distinguished name (DN) has to be obtained from the
  2715. login name supplied to the application. This can be done either by
  2716. simple pattern-matching (by setting the
  2717. <property>setUserDnPatterns</property> array property) or by
  2718. setting the <property>userSearch</property> property. For the DN
  2719. pattern-matching approach, a standard Java pattern format is used,
  2720. and the login name will be substituted for the parameter
  2721. <parameter>{0}</parameter>. The pattern should be relative to the
  2722. DN that the configured
  2723. <interfacename>InitialDirContextFactory</interfacename> will bind
  2724. to (see the section on <link
  2725. linkend="ldap-dircontextfactory">connecting to the LDAP
  2726. server</link> for more information on this). For example, if you
  2727. are using an LDAP server specified by the URL
  2728. <literal>ldap://monkeymachine.co.uk/dc=springframework,dc=org</literal>,
  2729. and have a pattern <literal>uid={0},ou=greatapes</literal>, then a
  2730. login name of "gorilla" will map to a DN
  2731. <literal>uid=gorilla,ou=greatapes,dc=springframework,dc=org</literal>.
  2732. Each configured DN pattern will be tried in turn until a match is
  2733. found. For information on using a search, see the section on <link
  2734. linkend="ldap-searchobjects">search objects</link> below. A
  2735. combination of the two approaches can also be used - the patterns
  2736. will be checked first and if no matching DN is found, the search
  2737. will be used.</para>
  2738. </sect3>
  2739. <sect3 id="ldap-ldap-authenticators-bind">
  2740. <title>BindAuthenticator</title>
  2741. <para>The class
  2742. <classname>org.springframework.security.providers.ldap.authenticator.BindAuthenticator</classname>
  2743. implements the bind authentication strategy. It simply attempts to
  2744. bind as the user.</para>
  2745. </sect3>
  2746. <sect3 id="ldap-ldap-authenticators-password">
  2747. <title>PasswordComparisonAuthenticator</title>
  2748. <para>The class
  2749. <classname>org.springframework.security.providers.ldap.authenticator.PasswordComparisonAuthenticator</classname>
  2750. implements the password comparison authentication strategy.</para>
  2751. </sect3>
  2752. <sect3 id="ldap-ldap-authenticators-active-directory">
  2753. <title>Active Directory Authentication</title>
  2754. <para>In addition to standard LDAP authentication (binding with a
  2755. DN), Active Directory has its own non-standard syntax for user
  2756. authentication.</para>
  2757. </sect3>
  2758. </sect2>
  2759. <sect2 id="ldap-dircontextfactory">
  2760. <title>Connecting to the LDAP Server</title>
  2761. <para>The beans discussed above have to be able to connect to the
  2762. server. They both have to be supplied with an
  2763. <interfacename>InitialDirContextFactory</interfacename> instance.
  2764. Unless you have special requirements, this will usually be a
  2765. <classname>DefaultInitialDirContextFactory</classname> bean, which
  2766. can be configured with the URL of your LDAP server and optionally
  2767. with the username and password of a "manager" user which will be
  2768. used by default when binding to the server (instead of binding
  2769. anonymously). It currently supports "simple" LDAP
  2770. authentication.</para>
  2771. <para><classname>DefaultInitialDirContextFactory</classname> uses
  2772. Sun's JNDI LDAP implementation by default (the one that comes with
  2773. the JDK). It also supports the built in connection pooling offered
  2774. by Sun's provider. Connections which are obtained either anonymously
  2775. or with the "manager" user's identity will be pooled automatically.
  2776. Connections obtained with a specific user's identity will not be
  2777. pooled. Connection pooling can be disabled completely by setting the
  2778. <property>useConnectionPool</property> property to false.</para>
  2779. <para>See the <ulink
  2780. url="http://acegisecurity.org/multiproject/acegi-security/xref/org/acegisecurity/providers/ldap/DefaultInitialDirContextFactory.html">class
  2781. Javadoc and source</ulink> for more information on this bean and its
  2782. properties.</para>
  2783. </sect2>
  2784. <sect2 id="ldap-searchobjects">
  2785. <title>LDAP Search Objects</title>
  2786. <para>Often more a more complicated strategy than simple DN-matching
  2787. is required to locate a user entry in the directory. This can be
  2788. encapsulated in an <interfacename>LdapUserSearch</interfacename>
  2789. instance which can be supplied to the authenticator implementations,
  2790. for example, to allow them to locate a user. The supplied
  2791. implementation is
  2792. <classname>FilterBasedLdapUserSearch</classname>.</para>
  2793. <sect3 id="ldap-searchobjects-filter">
  2794. <title
  2795. id="ldap-searchobjects-filter-based"><classname>FilterBasedLdapUserSearch</classname></title>
  2796. <para>This bean uses an LDAP filter to match the user object in
  2797. the directory. The process is explained in the Javadoc for the
  2798. corresponding search method on the <ulink
  2799. url="http://java.sun.com/j2se/1.4.2/docs/api/javax/naming/directory/DirContext.html#search(javax.naming.Name,%20java.lang.String,%20java.lang.Object[],%20javax.naming.directory.SearchControls)">JDK
  2800. DirContext class</ulink>. As explained there, the search filter
  2801. can be supplied with parameters. For this class, the only valid
  2802. parameter is <parameter>{0}</parameter> which will be replaced
  2803. with the user's login name.</para>
  2804. </sect3>
  2805. </sect2>
  2806. </sect1>
  2807. <sect1 id="ldap-config">
  2808. <title>Configuration</title>
  2809. <para>There is a version of the <link
  2810. linkend="contacts-sample">Contacts Sample Application</link> which
  2811. uses LDAP. You can copy the beans and filter setup from this as a
  2812. starting point for configuring your own application.</para>
  2813. <para>A typical configuration, using some of the beans we've discussed
  2814. above, might look like this: <programlisting>
  2815. &lt;bean id="initialDirContextFactory"
  2816. class="org.springframework.security.ldap.DefaultInitialDirContextFactory"&gt;
  2817. &lt;constructor-arg value="ldap://monkeymachine:389/dc=springframework,dc=org"/&gt;
  2818. &lt;property name="managerDn"&gt;&lt;value&gt;cn=manager,dc=springframework,dc=org&lt;/value&gt;&lt;/property&gt;
  2819. &lt;property name="managerPassword"&gt;&lt;value&gt;password&lt;/value&gt;&lt;/property&gt;
  2820. &lt;/bean&gt;
  2821. &lt;bean id="userSearch"
  2822. class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch"&gt;
  2823. &lt;constructor-arg index="0"&gt;
  2824. &lt;value&gt;&lt;/value&gt;
  2825. &lt;/constructor-arg&gt;
  2826. &lt;constructor-arg index="1"&gt;
  2827. &lt;value&gt;(uid={0})&lt;/value&gt;
  2828. &lt;/constructor-arg&gt;
  2829. &lt;constructor-arg index="2"&gt;
  2830. &lt;ref local="initialDirContextFactory" /&gt;
  2831. &lt;/constructor-arg&gt;
  2832. &lt;property name="searchSubtree"&gt;
  2833. &lt;value&gt;true&lt;/value&gt;
  2834. &lt;/property&gt;
  2835. &lt;/bean&gt;
  2836. &lt;bean id="ldapAuthProvider"
  2837. class="org.springframework.security.providers.ldap.LdapAuthenticationProvider"&gt;
  2838. &lt;constructor-arg&gt;
  2839. &lt;bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator"&gt;
  2840. &lt;constructor-arg&gt;&lt;ref local="initialDirContextFactory"/&gt;&lt;/constructor-arg&gt;
  2841. &lt;property name="userDnPatterns"&gt;&lt;list&gt;&lt;value&gt;uid={0},ou=people&lt;/value&gt;&lt;/list&gt;&lt;/property&gt;
  2842. &lt;/bean&gt;
  2843. &lt;/constructor-arg&gt;
  2844. &lt;constructor-arg&gt;
  2845. &lt;bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator"&gt;
  2846. &lt;constructor-arg&gt;&lt;ref local="initialDirContextFactory"/&gt;&lt;/constructor-arg&gt;
  2847. &lt;constructor-arg&gt;&lt;value&gt;ou=groups&lt;/value&gt;&lt;/constructor-arg&gt;
  2848. &lt;property name="groupRoleAttribute"&gt;&lt;value&gt;ou&lt;/value&gt;&lt;/property&gt;
  2849. &lt;/bean&gt;
  2850. &lt;/constructor-arg&gt;
  2851. &lt;/bean&gt;
  2852. </programlisting> This would set up the provider to access an LDAP
  2853. server with URL
  2854. <literal>ldap://monkeymachine:389/dc=springframework,dc=org</literal>.
  2855. Authentication will be performed by attempting to bind with the DN
  2856. <literal>uid=&lt;user-login-name&gt;,ou=people,dc=springframework,dc=org</literal>.
  2857. After successful authentication, roles will be assigned to the user by
  2858. searching under the DN
  2859. <literal>ou=groups,dc=springframework,dc=org</literal> with the
  2860. default filter <literal>(member=&lt;user's-DN&gt;)</literal>. The role
  2861. name will be taken from the <quote>ou</quote> attribute of each
  2862. match.</para>
  2863. <para>We've also included the configuration for a user search object,
  2864. which uses the filter
  2865. <literal>(uid=&lt;user-login-name&gt;)</literal>. This could be used
  2866. instead of the DN-pattern (or in addition to it), by setting the
  2867. authenticator's <property>userSearch</property> property. The
  2868. authenticator would then call the search object to obtain the correct
  2869. user's DN before attempting to bind as this user.</para>
  2870. </sect1>
  2871. </chapter>
  2872. <chapter id="cas">
  2873. <title>CAS Authentication</title>
  2874. <sect1 id="cas-overview">
  2875. <title>Overview</title>
  2876. <para>JA-SIG produces an enterprise-wide single sign on system known
  2877. as CAS. Unlike other initiatives, JA-SIG's Central Authentication
  2878. Service is open source, widely used, simple to understand, platform
  2879. independent, and supports proxy capabilities. Spring Security fully
  2880. supports CAS, and provides an easy migration path from
  2881. single-application deployments of Spring Security through to
  2882. multiple-application deployments secured by an enterprise-wide CAS
  2883. server.</para>
  2884. <para>You can learn more about CAS at
  2885. <literal>http://www.ja-sig.org/products/cas/</literal>. You will need
  2886. to visit this URL to download the CAS Server files. Whilst Spring
  2887. Security includes two CAS libraries in the "-with-dependencies" ZIP
  2888. file, you will still need the CAS Java Server Pages and
  2889. <literal>web.xml</literal> to customise and deploy your CAS
  2890. server.</para>
  2891. </sect1>
  2892. <sect1 id="cas-how-it-works">
  2893. <title>How CAS Works</title>
  2894. <para>Whilst the CAS web site above contains two documents that detail
  2895. the architecture of CAS, we present the general overview again here
  2896. within the context of Spring Security. The following refers to both
  2897. CAS 2.0 (produced by Yale) and CAS 3.0 (produced by JA-SIG), being the
  2898. versions of CAS that Spring Security supports.</para>
  2899. <para>Somewhere in your enterprise you will need to setup a CAS
  2900. server. The CAS server is simply a standard WAR file, so there isn't
  2901. anything difficult about setting up your server. Inside the WAR file
  2902. you will customise the login and other single sign on pages displayed
  2903. to users.</para>
  2904. <para>If you are deploying CAS 2.0, you will also need to specify in
  2905. the web.xml a <literal>PasswordHandler</literal>. The
  2906. <literal>PasswordHandler</literal> has a simple method that returns a
  2907. boolean as to whether a given username and password is valid. Your
  2908. <literal>PasswordHandler</literal> implementation will need to link
  2909. into some type of backend authentication repository, such as an LDAP
  2910. server or database.</para>
  2911. <para>If you are already running an existing CAS 2.0 server instance,
  2912. you will have already established a
  2913. <literal>PasswordHandler</literal>. If you do not already have a
  2914. <literal>PasswordHandler</literal>, you might prefer to use Spring
  2915. Security's <literal>CasPasswordHandler</literal> class. This class
  2916. delegates through to the standard Spring Security
  2917. <literal>AuthenticationManager</literal>, enabling you to use a
  2918. security configuration you might already have in place. You do not
  2919. need to use the <literal>CasPasswordHandler</literal> class on your
  2920. CAS server if you do not wish. Spring Security will function as a CAS
  2921. client successfully irrespective of the
  2922. <literal>PasswordHandler</literal> you've chosen for your CAS
  2923. server.</para>
  2924. <para>If you are deploying CAS 3.0, you will also need to specify an
  2925. <literal>AuthenticationHandler</literal> in the
  2926. deployerConfigContext.xml included with CAS. The
  2927. <literal>AuthenticationHandler</literal> has a simple method that
  2928. returns a boolean as to whether a given set of Credentials is valid.
  2929. Your <literal>AuthenticationHandler</literal> implementation will need
  2930. to link into some type of backend authentication repository, such as
  2931. an LDAP server or database. CAS itself includes numerous
  2932. <literal>AuthenticationHandler</literal>s out of the box to assist
  2933. with this.</para>
  2934. <para>If you are already running an existing CAS 3.0 server instance,
  2935. you will have already established an
  2936. <literal>AuthenticationHandler</literal>. If you do not already have
  2937. an <literal>AuthenticationHandler</literal>, you might prefer to use
  2938. Spring Security <literal>CasAuthenticationHandler</literal> class.
  2939. This class delegates through to the standard Spring Security
  2940. <literal>AuthenticationManager</literal>, enabling you to use a
  2941. security configuration you might already have in place. You do not
  2942. need to use the <literal>CasAuthenticationHandler</literal> class on
  2943. your CAS server if you do not wish. Spring Security will function as a
  2944. CAS client successfully irrespective of the
  2945. <literal>AuthenticationHandler</literal> you've chosen for your CAS
  2946. server.</para>
  2947. <para>Apart from the CAS server itself, the other key player is of
  2948. course the secure web applications deployed throughout your
  2949. enterprise. These web applications are known as "services". There are
  2950. two types of services: standard services and proxy services. A proxy
  2951. service is able to request resources from other services on behalf of
  2952. the user. This will be explained more fully later.</para>
  2953. <para>Services can be developed in a large variety of languages, due
  2954. to CAS 2.0's very light XML-based protocol. The JA-SIG CAS home page
  2955. contains a clients archive which demonstrates CAS clients in Java,
  2956. Active Server Pages, Perl, Python and others. Naturally, Java support
  2957. is very strong given the CAS server is written in Java. You do not
  2958. need to use any of CAS' client classes in applications secured by
  2959. Spring Security. This is handled transparently for you.</para>
  2960. <para>The basic interaction between a web browser, CAS server and n
  2961. Spring Security-secured service is as follows:</para>
  2962. <orderedlist>
  2963. <listitem>
  2964. <para>The web user is browsing the service's public pages. CAS or
  2965. Spring Security is not involved.</para>
  2966. </listitem>
  2967. <listitem>
  2968. <para>The user eventually requests a page that is either secure or
  2969. one of the beans it uses is secure. Spring Security's
  2970. <literal>ExceptionTranslationFilter</literal> will detect the
  2971. <literal>AuthenticationException</literal>.</para>
  2972. </listitem>
  2973. <listitem>
  2974. <para>Because the user's <literal>Authentication</literal> object
  2975. (or lack thereof) caused an
  2976. <literal>AuthenticationException</literal>, the
  2977. <literal>ExceptionTranslationFilter</literal> will call the
  2978. configured <literal>AuthenticationEntryPoint</literal>. If using
  2979. CAS, this will be the
  2980. <literal>CasProcessingFilterEntryPoint</literal> class.</para>
  2981. </listitem>
  2982. <listitem>
  2983. <para>The <literal>CasProcessingFilterEntry</literal> point will
  2984. redirect the user's browser to the CAS server. It will also
  2985. indicate a <literal>service</literal> parameter, which is the
  2986. callback URL for Spring Security service. For example, the URL to
  2987. which the browser is redirected might be
  2988. <literal>https://my.company.com/cas/login?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check</literal>.</para>
  2989. </listitem>
  2990. <listitem>
  2991. <para>After the user's browser redirects to CAS, they will be
  2992. prompted for their username and password. If the user presents a
  2993. session cookie which indicates they've previously logged on, they
  2994. will not be prompted to login again (there is an exception to this
  2995. procedure, which we'll cover later). CAS will use the
  2996. <literal>PasswordHandler</literal> (or
  2997. <literal>AuthenticationHandler</literal> if using CAS 3.0)
  2998. discussed above to decide whether the username and password is
  2999. valid.</para>
  3000. </listitem>
  3001. <listitem>
  3002. <para>Upon successful login, CAS will redirect the user's browser
  3003. back to the original service. It will also include a
  3004. <literal>ticket</literal> parameter, which is an opaque string
  3005. representing the "service ticket". Continuing our earlier example,
  3006. the URL the browser is redirected to might be
  3007. <literal>https://server3.company.com/webapp/j_spring_cas_security_check?ticket=ST-0-ER94xMJmn6pha35CQRoZ</literal>.</para>
  3008. </listitem>
  3009. <listitem>
  3010. <para>Back in the service web application, the
  3011. <literal>CasProcessingFilter</literal> is always listening for
  3012. requests to <literal>/j_spring_cas_security_check</literal> (this
  3013. is configurable, but we'll use the defaults in this introduction).
  3014. The processing filter will construct a
  3015. <literal>UsernamePasswordAuthenticationToken</literal>
  3016. representing the service ticket. The principal will be equal to
  3017. <literal>CasProcessingFilter.CAS_STATEFUL_IDENTIFIER</literal>,
  3018. whilst the credentials will be the service ticket opaque value.
  3019. This authentication request will then be handed to the configured
  3020. <literal>AuthenticationManager</literal>.</para>
  3021. </listitem>
  3022. <listitem>
  3023. <para>The <literal>AuthenticationManager</literal> implementation
  3024. will be the <literal>ProviderManager</literal>, which is in turn
  3025. configured with the <literal>CasAuthenticationProvider</literal>.
  3026. The <literal>CasAuthenticationProvider</literal> only responds to
  3027. <literal>UsernamePasswordAuthenticationToken</literal>s containing
  3028. the CAS-specific principal (such as
  3029. <literal>CasProcessingFilter.CAS_STATEFUL_IDENTIFIER</literal>)
  3030. and <literal>CasAuthenticationToken</literal>s (discussed
  3031. later).</para>
  3032. </listitem>
  3033. <listitem>
  3034. <para><literal>CasAuthenticationProvider</literal> will validate
  3035. the service ticket using a <literal>TicketValidator</literal>
  3036. implementation. Spring Security includes one implementation, the
  3037. <literal>CasProxyTicketValidator</literal>. This implementation a
  3038. ticket validation class included in the CAS client library. The
  3039. <literal>CasProxyTicketValidator</literal> makes an HTTPS request
  3040. to the CAS server in order to validate the service ticket. The
  3041. <literal>CasProxyTicketValidator</literal> may also include a
  3042. proxy callback URL, which is included in this example:
  3043. <literal>https://my.company.com/cas/proxyValidate?service=https%3A%2F%2Fserver3.company.com%2Fwebapp%2Fj_spring_cas_security_check&amp;ticket=ST-0-ER94xMJmn6pha35CQRoZ&amp;pgtUrl=https://server3.company.com/webapp/casProxy/receptor</literal>.</para>
  3044. </listitem>
  3045. <listitem>
  3046. <para>Back on the CAS server, the proxy validation request will be
  3047. received. If the presented service ticket matches the service URL
  3048. the ticket was issued to, CAS will provide an affirmative response
  3049. in XML indicating the username. If any proxy was involved in the
  3050. authentication (discussed below), the list of proxies is also
  3051. included in the XML response.</para>
  3052. </listitem>
  3053. <listitem>
  3054. <para>[OPTIONAL] If the request to the CAS validation service
  3055. included the proxy callback URL (in the <literal>pgtUrl</literal>
  3056. parameter), CAS will include a <literal>pgtIou</literal> string in
  3057. the XML response. This <literal>pgtIou</literal> represents a
  3058. proxy-granting ticket IOU. The CAS server will then create its own
  3059. HTTPS connection back to the <literal>pgtUrl</literal>. This is to
  3060. mutually authenticate the CAS server and the claimed service URL.
  3061. The HTTPS connection will be used to send a proxy granting ticket
  3062. to the original web application. For example,
  3063. <literal>https://server3.company.com/webapp/casProxy/receptor?pgtIou=PGTIOU-0-R0zlgrl4pdAQwBvJWO3vnNpevwqStbSGcq3vKB2SqSFFRnjPHt&amp;pgtId=PGT-1-si9YkkHLrtACBo64rmsi3v2nf7cpCResXg5MpESZFArbaZiOKH</literal>.
  3064. We suggest you use CAS' <literal>ProxyTicketReceptor</literal>
  3065. servlet to receive these proxy-granting tickets, if they are
  3066. required.</para>
  3067. </listitem>
  3068. <listitem>
  3069. <para>The <literal>CasProxyTicketValidator</literal> will parse
  3070. the XML received from the CAS server. It will return to the
  3071. <literal>CasAuthenticationProvider</literal> a
  3072. <literal>TicketResponse</literal>, which includes the username
  3073. (mandatory), proxy list (if any were involved), and proxy-granting
  3074. ticket IOU (if the proxy callback was requested).</para>
  3075. </listitem>
  3076. <listitem>
  3077. <para>Next <literal>CasAuthenticationProvider</literal> will call
  3078. a configured <literal>CasProxyDecider</literal>. The
  3079. <literal>CasProxyDecider</literal> indicates whether the proxy
  3080. list in the <literal>TicketResponse</literal> is acceptable to the
  3081. service. Several implementations are provided with Spring
  3082. Security: <literal>RejectProxyTickets</literal>,
  3083. <literal>AcceptAnyCasProxy</literal> and
  3084. <literal>NamedCasProxyDecider</literal>. These names are largely
  3085. self-explanatory, except <literal>NamedCasProxyDecider</literal>
  3086. which allows a <literal>List</literal> of trusted proxies to be
  3087. provided.</para>
  3088. </listitem>
  3089. <listitem>
  3090. <para><literal>CasAuthenticationProvider</literal> will next
  3091. request a <literal>CasAuthoritiesPopulator</literal> to advise the
  3092. <literal>GrantedAuthority</literal> objects that apply to the user
  3093. contained in the <literal>TicketResponse</literal>. Spring
  3094. Security includes a <literal>DaoCasAuthoritiesPopulator</literal>
  3095. which simply uses the <literal>UserDetailsService</literal>
  3096. infrastructure to find the <literal>UserDetails</literal> and
  3097. their associated <literal>GrantedAuthority</literal>s. Note that
  3098. the password and enabled/disabled status of
  3099. <literal>UserDetails</literal> returned by the
  3100. <literal>UserDetailsService</literal> are ignored, as the CAS
  3101. server is responsible for authentication decisions.
  3102. <literal>DaoCasAuthoritiesPopulator</literal> is only concerned
  3103. with retrieving the <literal>GrantedAuthority</literal>s.</para>
  3104. </listitem>
  3105. <listitem>
  3106. <para>If there were no problems,
  3107. <literal>CasAuthenticationProvider</literal> constructs a
  3108. <literal>CasAuthenticationToken</literal> including the details
  3109. contained in the <literal>TicketResponse</literal> and the
  3110. <literal>GrantedAuthority</literal>s. The
  3111. <literal>CasAuthenticationToken</literal> contains the hash of a
  3112. key, so that the <literal>CasAuthenticationProvider</literal>
  3113. knows it created it.</para>
  3114. </listitem>
  3115. <listitem>
  3116. <para>Control then returns to
  3117. <literal>CasProcessingFilter</literal>, which places the created
  3118. <literal>CasAuthenticationToken</literal> into the
  3119. <literal>HttpSession</literal> attribute named
  3120. <literal>HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY</literal>.</para>
  3121. </listitem>
  3122. <listitem>
  3123. <para>The user's browser is redirected to the original page that
  3124. caused the <literal>AuthenticationException</literal>.</para>
  3125. </listitem>
  3126. <listitem>
  3127. <para>As the <literal>Authentication</literal> object is now in
  3128. the well-known location, it is handled like any other
  3129. authentication approach. Usually the
  3130. <literal>HttpSessionContextIntegrationFilter</literal> will be
  3131. used to associate the <literal>Authentication</literal> object
  3132. with the <literal>SecurityContextHolder</literal> for the duration
  3133. of each request.</para>
  3134. </listitem>
  3135. </orderedlist>
  3136. <para>It's good that you're still here! It might sound involved, but
  3137. you can relax as Spring Security classes hide much of the complexity.
  3138. Let's now look at how this is configured</para>
  3139. </sect1>
  3140. <sect1 id="cas-server">
  3141. <title>Optional CAS Server Setup</title>
  3142. <para>Spring Security can even act as the backend which a CAS version
  3143. 2.0 or 3.0 server utilises. The configuration approach is described
  3144. below. Of course, if you have an existing CAS environment you might
  3145. just like to use it instead.</para>
  3146. <sect2 id="cas-server-2">
  3147. <title>CAS Version 2.0</title>
  3148. <para>As mentioned above, Spring Security includes a
  3149. <literal>PasswordHandler</literal> that bridges your existing
  3150. <literal>AuthenticationManager</literal> into CAS 2.0. You do not
  3151. need to use this <literal>PasswordHandler</literal> to use Spring
  3152. Security on the client side (any CAS
  3153. <literal>PasswordHandler</literal> will do).</para>
  3154. <para>To install, you will need to download and extract the CAS
  3155. server archive. We used version 2.0.12. There will be a
  3156. <literal>/web</literal> directory in the root of the deployment.
  3157. Copy an <literal>applicationContext.xml</literal> containing your
  3158. <literal>AuthenticationManager</literal> as well as the
  3159. <literal>CasPasswordHandler</literal> into the
  3160. <literal>/web/WEB-INF</literal> directory. A sample
  3161. <literal>applicationContext.xml</literal> is included below:</para>
  3162. <programlisting>
  3163. &lt;bean id="inMemoryDaoImpl" class="org.springframework.security.userdetails.memory.InMemoryDaoImpl"&gt;
  3164. &lt;property name="userMap"&gt;
  3165. &lt;value&gt;
  3166. rod=koala,ROLES_IGNORED_BY_CAS
  3167. dianne=emu,ROLES_IGNORED_BY_CAS
  3168. scott=wombat,ROLES_IGNORED_BY_CAS
  3169. peter=opal,disabled,ROLES_IGNORED_BY_CAS
  3170. &lt;/value&gt;
  3171. &lt;/property&gt;
  3172. &lt;/bean&gt;
  3173. &lt;bean id="daoAuthenticationProvider"
  3174. class="org.springframework.security.providers.dao.DaoAuthenticationProvider"&gt;
  3175. &lt;property name="userDetailsService"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
  3176. &lt;/bean&gt;
  3177. &lt;bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager"&gt;
  3178. &lt;property name="providers"&gt;
  3179. &lt;list&gt;
  3180. &lt;ref bean="daoAuthenticationProvider"/&gt;
  3181. &lt;/list&gt;
  3182. &lt;/property&gt;
  3183. &lt;/bean&gt;
  3184. &lt;bean id="casPasswordHandler" class="org.springframework.security.adapters.cas.CasPasswordHandler"&gt;
  3185. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  3186. &lt;/bean&gt;
  3187. </programlisting>
  3188. <para>Note the granted authorities are ignored by CAS because it has
  3189. no way of communicating the granted authorities to calling
  3190. applications. CAS is only concerned with username and passwords (and
  3191. the enabled/disabled status).</para>
  3192. <para>Next you will need to edit the existing
  3193. <literal>/web/WEB-INF/web.xml</literal> file. Add (or edit in the
  3194. case of the <literal>authHandler</literal> property) the following
  3195. lines:</para>
  3196. <para><programlisting>
  3197. &lt;context-param&gt;
  3198. &lt;param-name&gt;edu.yale.its.tp.cas.authHandler&lt;/param-name&gt;
  3199. &lt;param-value&gt;org.springframework.security.adapters.cas.CasPasswordHandlerProxy&lt;/param-value&gt;
  3200. &lt;/context-param&gt;
  3201. &lt;context-param&gt;
  3202. &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
  3203. &lt;param-value&gt;/WEB-INF/applicationContext.xml&lt;/param-value&gt;
  3204. &lt;/context-param&gt;
  3205. &lt;listener&gt;
  3206. &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
  3207. &lt;/listener&gt;
  3208. </programlisting></para>
  3209. <para>Copy the <literal>spring.jar</literal> and
  3210. <literal>acegi-security.jar</literal> files into
  3211. <literal>/web/WEB-INF/lib</literal>. Now use the <literal>ant
  3212. dist</literal> task in the <literal>build.xml</literal> in the root
  3213. of the directory structure. This will create
  3214. <literal>/lib/cas.war</literal>, which is ready for deployment to
  3215. your servlet container.</para>
  3216. <para>Note CAS heavily relies on HTTPS. You can't even test the
  3217. system without an HTTPS certificate. Whilst you should refer to your
  3218. web container's documentation on setting up HTTPS, if you need some
  3219. additional help or a test certificate you might like to check the
  3220. <literal>samples/contacts/etc/ssl</literal> directory</para>
  3221. </sect2>
  3222. <sect2 id="cas-server-3">
  3223. <title>CAS Version 3.0</title>
  3224. <para>As mentioned above, Spring Security includes an
  3225. <literal>AuthenticationHandler</literal> that bridges your existing
  3226. <literal>AuthenticationManager</literal> into CAS 3.0. You do not
  3227. need to use this <literal>AuthenticationHandler</literal> to use
  3228. Spring Security on the client side (any CAS
  3229. <literal>AuthenticationHandler</literal> will do).</para>
  3230. <para>To install, you will need to download and extract the CAS
  3231. server archive. We used version 3.0.4. There will be a
  3232. <literal>/webapp</literal> directory in the root of the deployment.
  3233. Edit the an <literal>deployerConfigContext.xml</literal> so that it
  3234. contains your <literal>AuthenticationManager</literal> as well as
  3235. the <literal>CasAuthenticationHandler</literal>. A sample
  3236. <literal>applicationContext.xml</literal> is included below:</para>
  3237. <programlisting>
  3238. &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  3239. &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt;
  3240. &lt;beans&gt;
  3241. &lt;bean
  3242. id="authenticationManager"
  3243. class="org.jasig.cas.authentication.AuthenticationManagerImpl"&gt;
  3244. &lt;property name="credentialsToPrincipalResolvers"&gt;
  3245. &lt;list&gt;
  3246. &lt;bean class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver" /&gt;
  3247. &lt;bean class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" /&gt;
  3248. &lt;/list&gt;
  3249. &lt;/property&gt;
  3250. &lt;property name="authenticationHandlers"&gt;
  3251. &lt;list&gt;
  3252. &lt;bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" /&gt;
  3253. &lt;bean class="org.springframework.security.adapters.cas3.CasAuthenticationHandler"&gt;
  3254. &lt;property name="authenticationManager" ref="authenticationManager" /&gt;
  3255. &lt;/bean&gt;
  3256. &lt;/list&gt;
  3257. &lt;/property&gt;
  3258. &lt;/bean&gt;
  3259. &lt;bean id="inMemoryDaoImpl" class="org.springframework.security.userdetails.memory.InMemoryDaoImpl"&gt;
  3260. &lt;property name="userMap"&gt;
  3261. &lt;value&gt;
  3262. rod=koala,ROLES_IGNORED_BY_CAS
  3263. dianne=emu,ROLES_IGNORED_BY_CAS
  3264. scott=wombat,ROLES_IGNORED_BY_CAS
  3265. peter=opal,disabled,ROLES_IGNORED_BY_CAS
  3266. &lt;/value&gt;
  3267. &lt;/property&gt;
  3268. &lt;/bean&gt;
  3269. &lt;bean id="daoAuthenticationProvider"
  3270. class="org.springframework.security.providers.dao.DaoAuthenticationProvider"&gt;
  3271. &lt;property name="userDetailsService"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
  3272. &lt;/bean&gt;
  3273. &lt;bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager"&gt;
  3274. &lt;property name="providers"&gt;
  3275. &lt;list&gt;
  3276. &lt;ref bean="daoAuthenticationProvider"/&gt;
  3277. &lt;/list&gt;
  3278. &lt;/property&gt;
  3279. &lt;/bean&gt;
  3280. &lt;/beans&gt;
  3281. </programlisting>
  3282. <para>Note the granted authorities are ignored by CAS because it has
  3283. no way of communicating the granted authorities to calling
  3284. applications. CAS is only concerned with username and passwords (and
  3285. the enabled/disabled status).</para>
  3286. <para>Copy <literal>acegi-security.jar</literal> and
  3287. <literal>acegi-security-cas.jar</literal> files into
  3288. <literal>/localPlugins/lib</literal>. Now use the <literal>ant
  3289. war</literal> task in the <literal>build.xml</literal> in the
  3290. /localPlugins directory. This will create
  3291. <literal>/localPlugins/target/cas.war</literal>, which is ready for
  3292. deployment to your servlet container.</para>
  3293. <para>Note CAS heavily relies on HTTPS. You can't even test the
  3294. system without an HTTPS certificate. Whilst you should refer to your
  3295. web container's documentation on setting up HTTPS, if you need some
  3296. additional help or a test certificate you might like to check the
  3297. CAS documentation on setting up SSL:
  3298. <literal>http://www.ja-sig.org/products/cas/server/ssl/index.html</literal></para>
  3299. </sect2>
  3300. </sect1>
  3301. <sect1 id="cas-client">
  3302. <title>Configuration of CAS Client</title>
  3303. <para>The web application side of CAS is made easy due to Spring
  3304. Security. It is assumed you already know the basics of using Spring
  3305. Security, so these are not covered again below. Only the CAS-specific
  3306. beans are mentioned.</para>
  3307. <para>You will need to add a <literal>ServiceProperties</literal> bean
  3308. to your application context. This represents your service:</para>
  3309. <para><programlisting>
  3310. &lt;bean id="serviceProperties" class="org.springframework.security.ui.cas.ServiceProperties"&gt;
  3311. &lt;property name="service"&gt;&lt;value&gt;https://localhost:8443/contacts-cas/j_spring_cas_security_check&lt;/value&gt;&lt;/property&gt;
  3312. &lt;property name="sendRenew"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  3313. &lt;/bean&gt;
  3314. </programlisting></para>
  3315. <para>The <literal>service</literal> must equal a URL that will be
  3316. monitored by the <literal>CasProcessingFilter</literal>. The
  3317. <literal>sendRenew</literal> defaults to false, but should be set to
  3318. true if your application is particularly sensitive. What this
  3319. parameter does is tell the CAS login service that a single sign on
  3320. login is unacceptable. Instead, the user will need to re-enter their
  3321. username and password in order to gain access to the service.</para>
  3322. <para>The following beans should be configured to commence the CAS
  3323. authentication process:</para>
  3324. <para><programlisting>
  3325. &lt;bean id="casProcessingFilter" class="org.springframework.security.ui.cas.CasProcessingFilter"&gt;
  3326. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  3327. &lt;property name="authenticationFailureUrl"&gt;&lt;value&gt;/casfailed.jsp&lt;/value&gt;&lt;/property&gt;
  3328. &lt;property name="defaultTargetUrl"&gt;&lt;value&gt;/&lt;/value&gt;&lt;/property&gt;
  3329. &lt;property name="filterProcessesUrl"&gt;&lt;value&gt;/j_spring_cas_security_check&lt;/value&gt;&lt;/property&gt;
  3330. &lt;/bean&gt;
  3331. &lt;bean id="exceptionTranslationFilter" class="org.springframework.security.ui.ExceptionTranslationFilter"&gt;
  3332. &lt;property name="authenticationEntryPoint"&gt;&lt;ref local="casProcessingFilterEntryPoint"/&gt;&lt;/property&gt;
  3333. &lt;/bean&gt;
  3334. &lt;bean id="casProcessingFilterEntryPoint"
  3335. class="org.springframework.security.ui.cas.CasProcessingFilterEntryPoint"&gt;
  3336. &lt;property name="loginUrl"&gt;&lt;value&gt;https://localhost:8443/cas/login&lt;/value&gt;&lt;/property&gt;
  3337. &lt;property name="serviceProperties"&gt;&lt;ref bean="serviceProperties"/&gt;&lt;/property&gt;
  3338. &lt;/bean&gt;
  3339. </programlisting></para>
  3340. <para>You will also need to add the
  3341. <literal>CasProcessingFilter</literal> to web.xml:</para>
  3342. <para><programlisting>
  3343. &lt;filter&gt;
  3344. &lt;filter-name&gt;Spring Security CAS Processing Filter&lt;/filter-name&gt;
  3345. &lt;filter-class&gt;org.springframework.security.util.FilterToBeanProxy&lt;/filter-class&gt;
  3346. &lt;init-param&gt;
  3347. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  3348. &lt;param-value&gt;org.springframework.security.ui.cas.CasProcessingFilter&lt;/param-value&gt;
  3349. &lt;/init-param&gt;
  3350. &lt;/filter&gt;
  3351. &lt;filter-mapping&gt;
  3352. &lt;filter-name&gt;Spring Security CAS Processing Filter&lt;/filter-name&gt;
  3353. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  3354. &lt;/filter-mapping&gt;
  3355. </programlisting></para>
  3356. <para>The <literal>CasProcessingFilter</literal> has very similar
  3357. properties to the <literal>AuthenticationProcessingFilter</literal>
  3358. (used for form-based logins). Each property is
  3359. self-explanatory.</para>
  3360. <para>For CAS to operate, the
  3361. <literal>ExceptionTranslationFilter</literal> must have its
  3362. <literal>authenticationEntryPoint</literal> property set to the
  3363. <literal>CasProcessingFilterEntryPoint</literal> bean.</para>
  3364. <para>The <literal>CasProcessingFilterEntryPoint</literal> must refer
  3365. to the <literal>ServiceProperties</literal> bean (discussed above),
  3366. which provides the URL to the enterprise's CAS login server. This is
  3367. where the user's browser will be redirected.</para>
  3368. <para>Next you need to add an <literal>AuthenticationManager</literal>
  3369. that uses <literal>CasAuthenticationProvider</literal> and its
  3370. collaborators:</para>
  3371. <para><programlisting>
  3372. &lt;bean id="authenticationManager" class="org.springframework.security.providers.ProviderManager"&gt;
  3373. &lt;property name="providers"&gt;
  3374. &lt;list&gt;
  3375. &lt;ref bean="casAuthenticationProvider"/&gt;
  3376. &lt;/list&gt;
  3377. &lt;/property&gt;
  3378. &lt;/bean&gt;
  3379. &lt;bean id="casAuthenticationProvider"
  3380. class="org.springframework.security.providers.cas.CasAuthenticationProvider"&gt;
  3381. &lt;property name="casAuthoritiesPopulator"&gt;&lt;ref bean="casAuthoritiesPopulator"/&gt;&lt;/property&gt;
  3382. &lt;property name="casProxyDecider"&gt;&lt;ref bean="casProxyDecider"/&gt;&lt;/property&gt;
  3383. &lt;property name="ticketValidator"&gt;&lt;ref bean="casProxyTicketValidator"/&gt;&lt;/property&gt;
  3384. &lt;property name="statelessTicketCache"&gt;&lt;ref bean="statelessTicketCache"/&gt;&lt;/property&gt;
  3385. &lt;property name="key"&gt;&lt;value&gt;my_password_for_this_auth_provider_only&lt;/value&gt;&lt;/property&gt;
  3386. &lt;/bean&gt;
  3387. &lt;bean id="casProxyTicketValidator"
  3388. class="org.springframework.security.providers.cas.ticketvalidator.CasProxyTicketValidator"&gt;
  3389. &lt;property name="casValidate"&gt;&lt;value&gt;https://localhost:8443/cas/proxyValidate&lt;/value&gt;&lt;/property&gt;
  3390. &lt;property name="proxyCallbackUrl"&gt;&lt;value&gt;https://localhost:8443/contacts-cas/casProxy/receptor&lt;/value&gt;&lt;/property&gt;
  3391. &lt;property name="serviceProperties"&gt;&lt;ref bean="serviceProperties"/&gt;&lt;/property&gt;
  3392. &lt;!-- &lt;property name="trustStore"&gt;&lt;value&gt;/some/path/to/your/lib/security/cacerts&lt;/value&gt;&lt;/property&gt; --&gt;
  3393. &lt;/bean&gt;
  3394. &lt;bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"&gt;
  3395. &lt;property name="configLocation"&gt;
  3396. &lt;value&gt;classpath:/ehcache-failsafe.xml&lt;/value&gt;
  3397. &lt;/property&gt;
  3398. &lt;/bean&gt;
  3399. &lt;bean id="ticketCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;
  3400. &lt;property name="cacheManager"&gt;
  3401. &lt;ref local="cacheManager"/&gt;
  3402. &lt;/property&gt;
  3403. &lt;property name="cacheName"&gt;
  3404. &lt;value&gt;ticketCache&lt;/value&gt;
  3405. &lt;/property&gt;
  3406. &lt;/bean&gt;
  3407. &lt;bean id="statelessTicketCache" class="org.springframework.security.providers.cas.cache.EhCacheBasedTicketCache"&gt;
  3408. &lt;property name="cache"&gt;&lt;ref local="ticketCacheBackend"/&gt;&lt;/property&gt;
  3409. &lt;/bean&gt;
  3410. &lt;bean id="casAuthoritiesPopulator"
  3411. class="org.springframework.security.providers.cas.populator.DaoCasAuthoritiesPopulator"&gt;
  3412. &lt;property name="userDetailsService"&gt;&lt;ref bean="inMemoryDaoImpl"/&gt;&lt;/property&gt;
  3413. &lt;/bean&gt;
  3414. &lt;bean id="casProxyDecider" class="org.springframework.security.providers.cas.proxy.RejectProxyTickets"/&gt;
  3415. </programlisting></para>
  3416. <para>The beans are all reasonable self-explanatory if you refer back
  3417. to the "How CAS Works" section. Careful readers might notice one
  3418. surprise: the <literal>statelessTicketCache</literal> property of the
  3419. <literal>CasAuthenticationProvider</literal>. This is discussed in
  3420. detail in the "Advanced CAS Usage" section.</para>
  3421. <para>Note the <literal>CasProxyTicketValidator</literal> has a
  3422. remarked out <literal>trustStore</literal> property. This property
  3423. might be helpful if you experience HTTPS certificate issues. Also note
  3424. the <literal>proxyCallbackUrl</literal> is set so the service can
  3425. receive a proxy-granting ticket. As mentioned above, this is optional
  3426. and unnecessary if you do not require proxy-granting tickets. If you
  3427. do use this feature, you will need to configure a suitable servlet to
  3428. receive the proxy-granting tickets. We suggest you use CAS'
  3429. <literal>ProxyTicketReceptor</literal> by adding the following to your
  3430. web application's <literal>web.xml</literal>:</para>
  3431. <para><programlisting>
  3432. &lt;servlet&gt;
  3433. &lt;servlet-name&gt;casproxy&lt;/servlet-name&gt;
  3434. &lt;servlet-class&gt;edu.yale.its.tp.cas.proxy.ProxyTicketReceptor&lt;/servlet-class&gt;
  3435. &lt;/servlet&gt;
  3436. &lt;servlet-mapping&gt;
  3437. &lt;servlet-name&gt;casproxy&lt;/servlet-name&gt;
  3438. &lt;url-pattern&gt;/casProxy/*&lt;/url-pattern&gt;
  3439. &lt;/servlet-mapping&gt;
  3440. </programlisting></para>
  3441. <para>This completes the configuration of CAS. If you haven't made any
  3442. mistakes, your web application should happily work within the
  3443. framework of CAS single sign on. No other parts of Spring Security
  3444. need to be concerned about the fact CAS handled authentication.</para>
  3445. <para>There is also a <literal>contacts-cas.war</literal> file in the
  3446. sample applications directory. This sample application uses the above
  3447. settings and can be deployed to see CAS in operation</para>
  3448. </sect1>
  3449. <sect1 id="cas-advanced">
  3450. <title>Advanced Issues</title>
  3451. <para>The <literal>CasAuthenticationProvider</literal> distinguishes
  3452. between stateful and stateless clients. A stateful client is
  3453. considered any that originates via the
  3454. <literal>CasProcessingFilter</literal>. A stateless client is any that
  3455. presents an authentication request via the
  3456. <literal>UsernamePasswordAuthenticationToken</literal> with a
  3457. principal equal to
  3458. <literal>CasProcessingFilter.CAS_STATELESS_IDENTIFIER</literal>.</para>
  3459. <para>Stateless clients are likely to be via remoting protocols such
  3460. as Hessian and Burlap. The <literal>BasicProcessingFilter</literal> is
  3461. still used in this case, but the remoting protocol client is expected
  3462. to present a username equal to the static string above, and a password
  3463. equal to a CAS service ticket. Clients should acquire a CAS service
  3464. ticket directly from the CAS server.</para>
  3465. <para>Because remoting protocols have no way of presenting themselves
  3466. within the context of an <literal>HttpSession</literal>, it isn't
  3467. possible to rely on the <literal>HttpSession</literal>'s
  3468. <literal>HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY</literal>
  3469. attribute to locate the <literal>CasAuthenticationToken</literal>.
  3470. Furthermore, because the CAS server invalidates a service ticket after
  3471. it has been validated by the <literal>TicketValidator</literal>,
  3472. presenting the same service ticket on subsequent requests will not
  3473. work. It is similarly very difficult to obtain a proxy-granting ticket
  3474. for a remoting protocol client, as they are often deployed on client
  3475. machines which rarely have HTTPS URLs that would be accessible to the
  3476. CAS server.</para>
  3477. <para>One obvious option is to not use CAS at all for remoting
  3478. protocol clients. However, this would eliminate many of the desirable
  3479. features of CAS.</para>
  3480. <para>As a middle-ground, the
  3481. <literal>CasAuthenticationProvider</literal> uses a
  3482. <literal>StatelessTicketCache</literal>. This is used solely for
  3483. requests with a principal equal to
  3484. <literal>CasProcessingFilter.CAS_STATELESS_IDENTIFIER</literal>. What
  3485. happens is the <literal>CasAuthenticationProvider</literal> will store
  3486. the resulting <literal>CasAuthenticationToken</literal> in the
  3487. <literal>StatelessTicketCache</literal>, keyed on the service ticket.
  3488. Accordingly, remoting protocol clients can present the same service
  3489. ticket and the <literal>CasAuthenticationProvider</literal> will not
  3490. need to contact the CAS server for validation (aside from the first
  3491. request).</para>
  3492. <para>The other aspect of advanced CAS usage involves creating proxy
  3493. tickets from the proxy-granting ticket. As indicated above, we
  3494. recommend you use CAS' <literal>ProxyTicketReceptor</literal> to
  3495. receive these tickets. The <literal>ProxyTicketReceptor</literal>
  3496. provides a static method that enables you to obtain a proxy ticket by
  3497. presenting the proxy-granting IOU ticket. You can obtain the
  3498. proxy-granting IOU ticket by calling
  3499. <literal>CasAuthenticationToken.getProxyGrantingTicketIou()</literal>.</para>
  3500. <para>It is hoped you find CAS integration easy and useful with Spring
  3501. Security classes. Welcome to enterprise-wide single sign on!</para>
  3502. </sect1>
  3503. </chapter>
  3504. <chapter id="ca">
  3505. <title>Container Adapter Authentication</title>
  3506. <sect1 id="ca-overview">
  3507. <title>Overview</title>
  3508. <para>Very early versions of Spring Security exclusively used
  3509. Container Adapters for interfacing authentication with end users.
  3510. Whilst this worked well, it required considerable time to support
  3511. multiple container versions and the configuration itself was
  3512. relatively time-consuming for developers. For this reason the HTTP
  3513. Form Authentication and HTTP Basic Authentication approaches were
  3514. developed, and are today recommended for almost all
  3515. applications.</para>
  3516. <para>Container Adapters enable Spring Security to integrate directly
  3517. with the containers used to host end user applications. This
  3518. integration means that applications can continue to leverage the
  3519. authentication and authorization capabilities built into containers
  3520. (such as <literal>isUserInRole()</literal> and form-based or basic
  3521. authentication), whilst benefiting from the enhanced security
  3522. interception capabilities provided by Spring Security (it should be
  3523. noted that Spring Security also offers
  3524. <literal>ContextHolderAwareRequestWrapper</literal> to deliver
  3525. <literal>isUserInRole()</literal> and similar Servlet Specification
  3526. compatibility methods).</para>
  3527. <para>The integration between a container and Spring Security is
  3528. achieved through an adapter. The adapter provides a
  3529. container-compatible user authentication provider, and needs to return
  3530. a container-compatible user object.</para>
  3531. <para>The adapter is instantiated by the container and is defined in a
  3532. container-specific configuration file. The adapter then loads a Spring
  3533. application context which defines the normal authentication manager
  3534. settings, such as the authentication providers that can be used to
  3535. authenticate the request. The application context is usually named
  3536. <literal>acegisecurity.xml</literal> and is placed in a
  3537. container-specific location.</para>
  3538. <para>Spring Security currently supports Jetty, Catalina (Tomcat),
  3539. JBoss and Resin. Additional container adapters can easily be
  3540. written</para>
  3541. </sect1>
  3542. <sect1 id="ca-adapter">
  3543. <title>Adapter Authentication Provider</title>
  3544. <para>As is always the case, the container adapter generated
  3545. <literal>Authentication</literal> object still needs to be
  3546. authenticated by an <literal>AuthenticationManager</literal> when
  3547. requested to do so by the
  3548. <literal>AbstractSecurityInterceptor</literal>. The
  3549. <literal>AuthenticationManager</literal> needs to be certain the
  3550. adapter-provided <literal>Authentication</literal> object is valid and
  3551. was actually authenticated by a trusted adapter.</para>
  3552. <para>Adapters create <literal>Authentication</literal> objects which
  3553. are immutable and implement the <literal>AuthByAdapter</literal>
  3554. interface. These objects store the hash of a key that is defined by
  3555. the adapter. This allows the <literal>Authentication</literal> object
  3556. to be validated by the <literal>AuthByAdapterProvider</literal>. This
  3557. authentication provider is defined as follows:</para>
  3558. <para><programlisting>&lt;bean id="authByAdapterProvider"
  3559. class="org.springframework.security.adapters.AuthByAdapterProvider"&gt;
  3560. &lt;property name="key"&gt;&lt;value&gt;my_password&lt;/value&gt;&lt;/property&gt;
  3561. &lt;/bean&gt; </programlisting></para>
  3562. <para>The key must match the key that is defined in the
  3563. container-specific configuration file that starts the adapter. The
  3564. <literal>AuthByAdapterProvider</literal> automatically accepts as
  3565. valid any <literal>AuthByAdapter</literal> implementation that returns
  3566. the expected hash of the key.</para>
  3567. <para>To reiterate, this means the adapter will perform the initial
  3568. authentication using providers such as
  3569. <literal>DaoAuthenticationProvider</literal>, returning an
  3570. <literal>AuthByAdapter</literal> instance that contains a hash code of
  3571. the key. Later, when an application calls a security interceptor
  3572. managed resource, the <literal>AuthByAdapter</literal> instance in the
  3573. <literal>SecurityContext</literal> in the
  3574. <literal>SecurityContextHolder</literal> will be tested by the
  3575. application's <literal>AuthByAdapterProvider</literal>. There is no
  3576. requirement for additional authentication providers such as
  3577. <literal>DaoAuthenticationProvider</literal> within the
  3578. application-specific application context, as the only type of
  3579. <literal>Authentication</literal> instance that will be presented by
  3580. the application is from the container adapter.</para>
  3581. <para>Classloader issues are frequent with containers and the use of
  3582. container adapters illustrates this further. Each container requires a
  3583. very specific configuration. The installation instructions are
  3584. provided below. Once installed, please take the time to try the sample
  3585. application to ensure your container adapter is properly
  3586. configured.</para>
  3587. <para>When using container adapters with the
  3588. <literal>DaoAuthenticationProvider</literal>, ensure you set its
  3589. <literal>forcePrincipalAsString</literal> property to
  3590. <literal>true</literal>.</para>
  3591. </sect1>
  3592. <sect1 id="ca-jetty">
  3593. <title>Jetty</title>
  3594. <para>The following was tested with Jetty 4.2.18.</para>
  3595. <para><literal>$JETTY_HOME</literal> refers to the root of your Jetty
  3596. installation.</para>
  3597. <para>Edit your <literal>$JETTY_HOME/etc/jetty.xml</literal> file so
  3598. the <literal>&lt;Configure class&gt;</literal> section has a new
  3599. <literal>addRealm</literal> call:</para>
  3600. <para><programlisting>
  3601. &lt;Call name="addRealm"&gt;
  3602. &lt;Arg&gt;
  3603. &lt;New class="org.springframework.security.adapters.jetty.JettySpringSecurityUserRealm"&gt;
  3604. &lt;Arg&gt;Spring Powered Realm&lt;/Arg&gt;
  3605. &lt;Arg&gt;my_password&lt;/Arg&gt;
  3606. &lt;Arg&gt;etc/acegisecurity.xml&lt;/Arg&gt;
  3607. &lt;/New&gt;
  3608. &lt;/Arg&gt;
  3609. &lt;/Call&gt;
  3610. </programlisting></para>
  3611. <para>Copy <literal>acegisecurity.xml</literal> into
  3612. <literal>$JETTY_HOME/etc</literal>.</para>
  3613. <para>Copy the following files into
  3614. <literal>$JETTY_HOME/ext</literal>:<itemizedlist>
  3615. <listitem>
  3616. <para><literal>aopalliance.jar</literal></para>
  3617. </listitem>
  3618. <listitem>
  3619. <para><literal>commons-logging.jar</literal></para>
  3620. </listitem>
  3621. <listitem>
  3622. <para><literal>spring.jar</literal></para>
  3623. </listitem>
  3624. <listitem>
  3625. <para><literal>acegi-security-jetty-XX.jar</literal></para>
  3626. </listitem>
  3627. <listitem>
  3628. <para><literal>commons-codec.jar</literal></para>
  3629. </listitem>
  3630. <listitem>
  3631. <para><literal>burlap.jar</literal></para>
  3632. </listitem>
  3633. <listitem>
  3634. <para><literal>hessian.jar</literal></para>
  3635. </listitem>
  3636. </itemizedlist></para>
  3637. <para>None of the above JAR files (or
  3638. <literal>acegi-security-XX.jar</literal>) should be in your
  3639. application's <literal>WEB-INF/lib</literal>. The realm name indicated
  3640. in your <literal>web.xml</literal> does matter with Jetty. The
  3641. <literal>web.xml</literal> must express the same
  3642. <literal>&lt;realm-name&gt;</literal> as your
  3643. <literal>jetty.xml</literal> (in the example above, "Spring Powered
  3644. Realm").</para>
  3645. </sect1>
  3646. <sect1 id="ca-jboss">
  3647. <title>JBoss</title>
  3648. <para>The following was tested with JBoss 3.2.6.</para>
  3649. <para><literal>$JBOSS_HOME</literal> refers to the root of your JBoss
  3650. installation.</para>
  3651. <para>There are two different ways of making spring context available
  3652. to the Jboss integration classes.</para>
  3653. <para>The first approach is by editing your
  3654. <literal>$JBOSS_HOME/server/your_config/conf/login-config.xml</literal>
  3655. file so that it contains a new entry under the
  3656. <literal>&lt;Policy&gt;</literal> section:</para>
  3657. <para><programlisting>
  3658. &lt;application-policy name = "SpringPoweredRealm"&gt;
  3659. &lt;authentication&gt;
  3660. &lt;login-module code = "org.springframework.security.adapters.jboss.JbossSpringSecurityLoginModule"
  3661. flag = "required"&gt;
  3662. &lt;module-option name = "appContextLocation"&gt;acegisecurity.xml&lt;/module-option&gt;
  3663. &lt;module-option name = "key"&gt;my_password&lt;/module-option&gt;
  3664. &lt;/login-module&gt;
  3665. &lt;/authentication&gt;
  3666. &lt;/application-policy&gt;
  3667. </programlisting></para>
  3668. <para>Copy <literal>acegisecurity.xml</literal> into
  3669. <literal>$JBOSS_HOME/server/your_config/conf</literal>.</para>
  3670. <para>In this configuration <literal>acegisecurity.xml</literal>
  3671. contains the spring context definition including all the
  3672. authentication manager beans. You have to bear in mind though, that
  3673. <literal>SecurityContext</literal> is created and destroyed on each
  3674. login request, so the login operation might become costly.
  3675. Alternatively, the second approach is to use Spring singleton
  3676. capabilities through
  3677. <literal>org.springframework.beans.factory.access.SingletonBeanFactoryLocator</literal>.
  3678. The required configuration for this approach is:</para>
  3679. <para><programlisting>
  3680. &lt;application-policy name = "SpringPoweredRealm"&gt;
  3681. &lt;authentication&gt;
  3682. &lt;login-module code = "org.springframework.security.adapters.jboss.JbossSpringSecurityLoginModule"
  3683. flag = "required"&gt;
  3684. &lt;module-option name = "singletonId"&gt;springRealm&lt;/module-option&gt;
  3685. &lt;module-option name = "key"&gt;my_password&lt;/module-option&gt;
  3686. &lt;module-option name = "authenticationManager"&gt;authenticationManager&lt;/module-option&gt;
  3687. &lt;/login-module&gt;
  3688. &lt;/authentication&gt;
  3689. &lt;/application-policy&gt;
  3690. </programlisting></para>
  3691. <para>In the above code fragment,
  3692. <literal>authenticationManager</literal> is a helper property that
  3693. defines the expected name of the
  3694. <literal>AuthenticationManager</literal> in case you have several
  3695. defined in the IoC container. The <literal>singletonId</literal>
  3696. property references a bean defined in a
  3697. <literal>beanRefFactory.xml</literal> file. This file needs to be
  3698. available from anywhere on the JBoss classpath, including
  3699. <literal>$JBOSS_HOME/server/your_config/conf</literal>. The
  3700. <literal>beanRefFactory.xml</literal> contains the following
  3701. declaration:</para>
  3702. <para><programlisting>
  3703. &lt;beans&gt;
  3704. &lt;bean id="springRealm" singleton="true" lazy-init="true" class="org.springframework.context.support.ClassPathXmlApplicationContext"&gt;
  3705. &lt;constructor-arg&gt;
  3706. &lt;list&gt;
  3707. &lt;value&gt;acegisecurity.xml&lt;/value&gt;
  3708. &lt;/list&gt;
  3709. &lt;/constructor-arg&gt;
  3710. &lt;/bean&gt;
  3711. &lt;/beans&gt;
  3712. </programlisting></para>
  3713. <para>Finally, irrespective of the configuration approach you need to
  3714. copy the following files into
  3715. <literal>$JBOSS_HOME/server/your_config/lib</literal>:<itemizedlist>
  3716. <listitem>
  3717. <para><literal>aopalliance.jar</literal></para>
  3718. </listitem>
  3719. <listitem>
  3720. <para><literal>spring.jar</literal></para>
  3721. </listitem>
  3722. <listitem>
  3723. <para><literal>acegi-security-jboss-XX.jar</literal></para>
  3724. </listitem>
  3725. <listitem>
  3726. <para><literal>commons-codec.jar</literal></para>
  3727. </listitem>
  3728. <listitem>
  3729. <para><literal>burlap.jar</literal></para>
  3730. </listitem>
  3731. <listitem>
  3732. <para><literal>hessian.jar</literal></para>
  3733. </listitem>
  3734. </itemizedlist></para>
  3735. <para>None of the above JAR files (or
  3736. <literal>acegi-security-XX.jar</literal>) should be in your
  3737. application's <literal>WEB-INF/lib</literal>. The realm name indicated
  3738. in your <literal>web.xml</literal> does not matter with JBoss.
  3739. However, your web application's
  3740. <literal>WEB-INF/jboss-web.xml</literal> must express the same
  3741. <literal>&lt;security-domain&gt;</literal> as your
  3742. <literal>login-config.xml</literal>. For example, to match the above
  3743. example, your <literal>jboss-web.xml</literal> would look like
  3744. this:</para>
  3745. <para><programlisting>
  3746. &lt;jboss-web&gt;
  3747. &lt;security-domain&gt;java:/jaas/SpringPoweredRealm&lt;/security-domain&gt;
  3748. &lt;/jboss-web&gt;</programlisting></para>
  3749. <para>JBoss is a widely-used container adapter (mostly due to the need
  3750. to support legacy EJBs), so please let us know if you have any
  3751. difficulties.</para>
  3752. </sect1>
  3753. <sect1 id="ca-resin">
  3754. <title>Resin</title>
  3755. <para>The following was tested with Resin 3.0.6.</para>
  3756. <para><literal>$RESIN_HOME</literal> refers to the root of your Resin
  3757. installation.</para>
  3758. <para>Resin provides several ways to support the container adapter. In
  3759. the instructions below we have elected to maximise consistency with
  3760. other container adapter configurations. This will allow Resin users to
  3761. simply deploy the sample application and confirm correct
  3762. configuration. Developers comfortable with Resin are naturally able to
  3763. use its capabilities to package the JARs with the web application
  3764. itself, and/or support single sign-on.</para>
  3765. <para>Copy the following files into
  3766. <literal>$RESIN_HOME/lib</literal>:<itemizedlist>
  3767. <listitem>
  3768. <para><literal>aopalliance.jar</literal></para>
  3769. </listitem>
  3770. <listitem>
  3771. <para><literal>commons-logging.jar</literal></para>
  3772. </listitem>
  3773. <listitem>
  3774. <para><literal>spring.jar</literal></para>
  3775. </listitem>
  3776. <listitem>
  3777. <para><literal>acegi-security-resin-XX.jar</literal></para>
  3778. </listitem>
  3779. <listitem>
  3780. <para><literal>commons-codec.jar</literal></para>
  3781. </listitem>
  3782. <listitem>
  3783. <para><literal>burlap.jar</literal></para>
  3784. </listitem>
  3785. <listitem>
  3786. <para><literal>hessian.jar</literal></para>
  3787. </listitem>
  3788. </itemizedlist></para>
  3789. <para>Unlike the container-wide <literal>acegisecurity.xml</literal>
  3790. files used by other container adapters, each Resin web application
  3791. will contain its own
  3792. <literal>WEB-INF/resin-acegisecurity.xml</literal> file. Each web
  3793. application will also contain a <literal>resin-web.xml</literal> file
  3794. which Resin uses to start the container adapter:</para>
  3795. <para><programlisting>
  3796. &lt;web-app&gt;
  3797. &lt;authenticator&gt;
  3798. &lt;type&gt;org.springframework.security.adapters.resin.ResinAcegiAuthenticator&lt;/type&gt;
  3799. &lt;init&gt;
  3800. &lt;app-context-location&gt;WEB-INF/resin-acegisecurity.xml&lt;/app-context-location&gt;
  3801. &lt;key&gt;my_password&lt;/key&gt;
  3802. &lt;/init&gt;
  3803. &lt;/authenticator&gt;
  3804. &lt;/web-app&gt;
  3805. </programlisting></para>
  3806. <para>With the basic configuration provided above, none of the JAR
  3807. files listed (or <literal>acegi-security-XX.jar</literal>) should be
  3808. in your application's <literal>WEB-INF/lib</literal>. The realm name
  3809. indicated in your <literal>web.xml</literal> does not matter with
  3810. Resin, as the relevant authentication class is indicated by the
  3811. <literal>&lt;authenticator&gt;</literal> setting</para>
  3812. </sect1>
  3813. <sect1 id="ca-tomcat">
  3814. <title>Tomcat</title>
  3815. <para>The following was tested with Jakarta Tomcat 4.1.30 and
  3816. 5.0.19.</para>
  3817. <para><literal>$CATALINA_HOME</literal> refers to the root of your
  3818. Catalina (Tomcat) installation.</para>
  3819. <para>Edit your <literal>$CATALINA_HOME/conf/server.xml</literal> file
  3820. so the <literal>&lt;Engine&gt;</literal> section contains only one
  3821. active <literal>&lt;Realm&gt;</literal> entry. An example realm
  3822. entry:</para>
  3823. <para><programlisting> &lt;Realm
  3824. className="org.springframework.security.adapters.catalina.CatalinaSpringSecurityUserRealm"
  3825. appContextLocation="conf/acegisecurity.xml"
  3826. key="my_password" /&gt;</programlisting></para>
  3827. <para>Be sure to remove any other <literal>&lt;Realm&gt;</literal>
  3828. entry from your <literal>&lt;Engine&gt;</literal> section.</para>
  3829. <para>Copy <literal>acegisecurity.xml</literal> into
  3830. <literal>$CATALINA_HOME/conf</literal>.</para>
  3831. <para>Copy <literal>spring-security-catalina-XX.jar</literal> into
  3832. <literal>$CATALINA_HOME/server/lib</literal>.</para>
  3833. <para>Copy the following files into
  3834. <literal>$CATALINA_HOME/common/lib</literal>:</para>
  3835. <itemizedlist>
  3836. <listitem>
  3837. <para><literal>aopalliance.jar</literal></para>
  3838. </listitem>
  3839. <listitem>
  3840. <para><literal>spring.jar</literal></para>
  3841. </listitem>
  3842. <listitem>
  3843. <para><literal>commons-codec.jar</literal></para>
  3844. </listitem>
  3845. <listitem>
  3846. <para><literal>burlap.jar</literal></para>
  3847. </listitem>
  3848. <listitem>
  3849. <para><literal>hessian.jar</literal></para>
  3850. </listitem>
  3851. </itemizedlist>
  3852. <para>None of the above JAR files (or
  3853. <literal>spring-security-XX.jar</literal>) should be in your
  3854. application's <literal>WEB-INF/lib</literal>. The realm name indicated
  3855. in your <literal>web.xml</literal> does not matter with
  3856. Catalina.</para>
  3857. <para>We have received reports of problems using this Container
  3858. Adapter with Mac OS X. A work-around is to use a script such as
  3859. follows:</para>
  3860. <para><programlisting>#!/bin/sh
  3861. export CATALINA_HOME="/Library/Tomcat"
  3862. export JAVA_HOME="/Library/Java/Home"
  3863. cd /
  3864. $CATALINA_HOME/bin/startup.sh</programlisting></para>
  3865. <para>Finally, restart Tomcat.</para>
  3866. </sect1>
  3867. </chapter>
  3868. </part>
  3869. <part id="authorization">
  3870. <title>Authorization</title>
  3871. <partintro>
  3872. <para>The advanced authorization capabilities within Spring Security
  3873. represent one of the most compelling reasons for its popularity.
  3874. Irrespective of how you choose to authenticate - whether using a Spring
  3875. Security-provided mechanism and provider, or integrating with a
  3876. container or other non-Spring Security authentication authority - you
  3877. will find the authorization services can be used within your application
  3878. in a consistent and simple way.</para>
  3879. <para>In this part we'll explore the different
  3880. <literal>AbstractSecurityInterceptor</literal> implementations, which
  3881. were introduced in Part I. We then move on to explore how to fine-tune
  3882. authorization through use of domain access control lists.</para>
  3883. </partintro>
  3884. <chapter id="authorization-common">
  3885. <title>Common Authorization Concepts</title>
  3886. <sect1 id="authorities">
  3887. <title>Authorities</title>
  3888. <para>As briefly mentioned in the Authentication section, all
  3889. <literal>Authentication</literal> implementations are required to
  3890. store an array of <literal>GrantedAuthority</literal> objects. These
  3891. represent the authorities that have been granted to the principal. The
  3892. <literal>GrantedAuthority</literal> objects are inserted into the
  3893. <literal>Authentication</literal> object by the
  3894. <literal>AuthenticationManager</literal> and are later read by
  3895. <literal>AccessDecisionManager</literal>s when making authorization
  3896. decisions.</para>
  3897. <para><literal>GrantedAuthority</literal> is an interface with only
  3898. one method:</para>
  3899. <para><programlisting>public String getAuthority();</programlisting></para>
  3900. <para>This method allows <literal>AccessDecisionManager</literal>s to
  3901. obtain a precise <literal>String</literal> representation of the
  3902. <literal>GrantedAuthority</literal>. By returning a representation as
  3903. a <literal>String</literal>, a <literal>GrantedAuthority</literal> can
  3904. be easily "read" by most <literal>AccessDecisionManager</literal>s. If
  3905. a <literal>GrantedAuthority</literal> cannot be precisely represented
  3906. as a <literal>String</literal>, the
  3907. <literal>GrantedAuthority</literal> is considered "complex" and
  3908. <literal>getAuthority()</literal> must return
  3909. <literal>null</literal>.</para>
  3910. <para>An example of a "complex" <literal>GrantedAuthority</literal>
  3911. would be an implementation that stores a list of operations and
  3912. authority thresholds that apply to different customer account numbers.
  3913. Representing this complex <literal>GrantedAuthority</literal> as a
  3914. <literal>String</literal> would be quite complex, and as a result the
  3915. <literal>getAuthority()</literal> method should return
  3916. <literal>null</literal>. This will indicate to any
  3917. <literal>AccessDecisionManager</literal> that it will need to
  3918. specifically support the <literal>GrantedAuthority</literal>
  3919. implementation in order to understand its contents.</para>
  3920. <para>Spring Security includes one concrete
  3921. <literal>GrantedAuthority</literal> implementation,
  3922. <literal>GrantedAuthorityImpl</literal>. This allows any
  3923. user-specified <literal>String</literal> to be converted into a
  3924. <literal>GrantedAuthority</literal>. All
  3925. <literal>AuthenticationProvider</literal>s included with the security
  3926. architecture use <literal>GrantedAuthorityImpl</literal> to populate
  3927. the <literal>Authentication</literal> object.</para>
  3928. </sect1>
  3929. <sect1 id="pre-invocation">
  3930. <title>Pre-Invocation Handling</title>
  3931. <para>The <literal>AccessDecisionManager</literal> is called by the
  3932. <literal>AbstractSecurityInterceptor</literal> and is responsible for
  3933. making final access control decisions. The
  3934. <literal>AccessDecisionManager</literal> interface contains three
  3935. methods:</para>
  3936. <para><programlisting>public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config) throws AccessDeniedException;
  3937. public boolean supports(ConfigAttribute attribute);
  3938. public boolean supports(Class clazz);</programlisting></para>
  3939. <para>As can be seen from the first method, the
  3940. <literal>AccessDecisionManager</literal> is passed via method
  3941. parameters all information that is likely to be of value in assessing
  3942. an authorization decision. In particular, passing the secure
  3943. <literal>Object</literal> enables those arguments contained in the
  3944. actual secure object invocation to be inspected. For example, let's
  3945. assume the secure object was a <literal>MethodInvocation</literal>. It
  3946. would be easy to query the <literal>MethodInvocation</literal> for any
  3947. <literal>Customer</literal> argument, and then implement some sort of
  3948. security logic in the <literal>AccessDecisionManager</literal> to
  3949. ensure the principal is permitted to operate on that customer.
  3950. Implementations are expected to throw an
  3951. <literal>AccessDeniedException</literal> if access is denied.</para>
  3952. <para>The <literal>supports(ConfigAttribute)</literal> method is
  3953. called by the <literal>AbstractSecurityInterceptor</literal> at
  3954. startup time to determine if the
  3955. <literal>AccessDecisionManager</literal> can process the passed
  3956. <literal>ConfigAttribute</literal>. The
  3957. <literal>supports(Class)</literal> method is called by a security
  3958. interceptor implementation to ensure the configured
  3959. <literal>AccessDecisionManager</literal> supports the type of secure
  3960. object that the security interceptor will present.</para>
  3961. <para>Whilst users can implement their own
  3962. <literal>AccessDecisionManager</literal> to control all aspects of
  3963. authorization, Spring Security includes several
  3964. <literal>AccessDecisionManager</literal> implementations that are
  3965. based on voting. Figure 4 illustrates the relevant classes.</para>
  3966. <para><mediaobject>
  3967. <imageobject role="html">
  3968. <imagedata align="center"
  3969. fileref="images/AccessDecisionVoting.gif"
  3970. format="GIF" />
  3971. </imageobject>
  3972. <caption>
  3973. <para>Figure 4: Voting Decision Manager</para>
  3974. </caption>
  3975. </mediaobject></para>
  3976. <para>Using this approach, a series of
  3977. <literal>AccessDecisionVoter</literal> implementations are polled on
  3978. an authorization decision. The
  3979. <literal>AccessDecisionManager</literal> then decides whether or not
  3980. to throw an <literal>AccessDeniedException</literal> based on its
  3981. assessment of the votes.</para>
  3982. <para>The <literal>AccessDecisionVoter</literal> interface has three
  3983. methods:</para>
  3984. <para><programlisting>public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config);
  3985. public boolean supports(ConfigAttribute attribute);
  3986. public boolean supports(Class clazz);</programlisting></para>
  3987. <para>Concrete implementations return an <literal>int</literal>, with
  3988. possible values being reflected in the
  3989. <literal>AccessDecisionVoter</literal> static fields
  3990. <literal>ACCESS_ABSTAIN</literal>, <literal>ACCESS_DENIED</literal>
  3991. and <literal>ACCESS_GRANTED</literal>. A voting implementation will
  3992. return <literal>ACCESS_ABSTAIN</literal> if it has no opinion on an
  3993. authorization decision. If it does have an opinion, it must return
  3994. either <literal>ACCESS_DENIED</literal> or
  3995. <literal>ACCESS_GRANTED</literal>.</para>
  3996. <para>There are three concrete
  3997. <literal>AccessDecisionManager</literal>s provided with Spring
  3998. Security that tally the votes. The <literal>ConsensusBased</literal>
  3999. implementation will grant or deny access based on the consensus of
  4000. non-abstain votes. Properties are provided to control behavior in the
  4001. event of an equality of votes or if all votes are abstain. The
  4002. <literal>AffirmativeBased</literal> implementation will grant access
  4003. if one or more <literal>ACCESS_GRANTED</literal> votes were received
  4004. (ie a deny vote will be ignored, provided there was at least one grant
  4005. vote). Like the <literal>ConsensusBased</literal> implementation,
  4006. there is a parameter that controls the behavior if all voters abstain.
  4007. The <literal>UnanimousBased</literal> provider expects unanimous
  4008. <literal>ACCESS_GRANTED</literal> votes in order to grant access,
  4009. ignoring abstains. It will deny access if there is any
  4010. <literal>ACCESS_DENIED</literal> vote. Like the other implementations,
  4011. there is a parameter that controls the behaviour if all voters
  4012. abstain.</para>
  4013. <para>It is possible to implement a custom
  4014. <literal>AccessDecisionManager</literal> that tallies votes
  4015. differently. For example, votes from a particular
  4016. <literal>AccessDecisionVoter</literal> might receive additional
  4017. weighting, whilst a deny vote from a particular voter may have a veto
  4018. effect.</para>
  4019. <para>There are two concrete <literal>AccessDecisionVoter</literal>
  4020. implementations provided with Spring Security. The
  4021. <literal>RoleVoter</literal> class will vote if any ConfigAttribute
  4022. begins with <literal>ROLE_</literal>. It will vote to grant access if
  4023. there is a <literal>GrantedAuthority</literal> which returns a
  4024. <literal>String</literal> representation (via the
  4025. <literal>getAuthority()</literal> method) exactly equal to one or more
  4026. <literal>ConfigAttributes</literal> starting with
  4027. <literal>ROLE_</literal>. If there is no exact match of any
  4028. <literal>ConfigAttribute</literal> starting with
  4029. <literal>ROLE_</literal>, the <literal>RoleVoter</literal> will vote
  4030. to deny access. If no <literal>ConfigAttribute</literal> begins with
  4031. <literal>ROLE_</literal>, the voter will abstain.
  4032. <literal>RoleVoter</literal> is case sensitive on comparisons as well
  4033. as the <literal>ROLE_</literal> prefix.</para>
  4034. <para><literal>BasicAclEntryVoter</literal> is the other concrete
  4035. voter included with Spring Security. It integrates with Spring
  4036. Security's <literal>AclManager</literal> (discussed later). This voter
  4037. is designed to have multiple instances in the same application
  4038. context, such as:</para>
  4039. <para><programlisting>&lt;bean id="aclContactReadVoter"
  4040. class="org.springframework.security.vote.BasicAclEntryVoter"&gt;
  4041. &lt;property name="processConfigAttribute"&gt;&lt;value&gt;ACL_CONTACT_READ&lt;/value&gt;&lt;/property&gt;
  4042. &lt;property name="processDomainObjectClass"&gt;&lt;value&gt;sample.contact.Contact&lt;/value&gt;&lt;/property&gt;
  4043. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  4044. &lt;property name="requirePermission"&gt;
  4045. &lt;list&gt;
  4046. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  4047. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.READ"/&gt;
  4048. &lt;/list&gt;
  4049. &lt;/property&gt;
  4050. &lt;/bean&gt;
  4051. &lt;bean id="aclContactDeleteVoter" class="org.springframework.security.vote.BasicAclEntryVoter"&gt;
  4052. &lt;property name="processConfigAttribute"&gt;&lt;value&gt;ACL_CONTACT_DELETE&lt;/value&gt;&lt;/property&gt;
  4053. &lt;property name="processDomainObjectClass"&gt;&lt;value&gt;sample.contact.Contact&lt;/value&gt;&lt;/property&gt;
  4054. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  4055. &lt;property name="requirePermission"&gt;
  4056. &lt;list&gt;
  4057. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  4058. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.DELETE"/&gt;
  4059. &lt;/list&gt;
  4060. &lt;/property&gt;
  4061. &lt;/bean&gt; </programlisting></para>
  4062. <para>In the above example, you'd define
  4063. <literal>ACL_CONTACT_READ</literal> or
  4064. <literal>ACL_CONTACT_DELETE</literal> against some methods on a
  4065. <literal>MethodSecurityInterceptor</literal> or
  4066. <literal>AspectJSecurityInterceptor</literal>. When those methods are
  4067. invoked, the above applicable voter defined above would vote to grant
  4068. or deny access. The voter would look at the method invocation to
  4069. locate the first argument of type
  4070. <literal>sample.contact.Contact</literal>, and then pass that
  4071. <literal>Contact</literal> to the <literal>AclManager</literal>. The
  4072. <literal>AclManager</literal> will then return an access control list
  4073. (ACL) that applies to the current <literal>Authentication</literal>.
  4074. Assuming that ACL contains one of the listed
  4075. <literal>requirePermission</literal>s, the voter will vote to grant
  4076. access. If the ACL does not contain one of the permissions defined
  4077. against the voter, the voter will vote to deny access.
  4078. <literal>BasicAclEntryVoter</literal> is an important class as it
  4079. allows you to build truly complex applications with domain object
  4080. security entirely defined in the application context. If you're
  4081. interested in learning more about Spring Security's ACL capabilities
  4082. and how best to apply them, please see the ACL and "After Invocation"
  4083. sections of this reference guide, and the Contacts sample
  4084. application.</para>
  4085. <para>It is also possible to implement a custom
  4086. <literal>AccessDecisionVoter</literal>. Several examples are provided
  4087. in Spring Security unit tests, including
  4088. <literal>ContactSecurityVoter</literal> and
  4089. <literal>DenyVoter</literal>. The
  4090. <literal>ContactSecurityVoter</literal> abstains from voting decisions
  4091. where a <literal>CONTACT_OWNED_BY_CURRENT_USER</literal>
  4092. <literal>ConfigAttribute</literal> is not found. If voting, it queries
  4093. the <literal>MethodInvocation</literal> to extract the owner of the
  4094. <literal>Contact</literal> object that is subject of the method call.
  4095. It votes to grant access if the <literal>Contact</literal> owner
  4096. matches the principal presented in the
  4097. <literal>Authentication</literal> object. It could have just as easily
  4098. compared the <literal>Contact</literal> owner with some
  4099. <literal>GrantedAuthority</literal> the
  4100. <literal>Authentication</literal> object presented. All of this is
  4101. achieved with relatively few lines of code and demonstrates the
  4102. flexibility of the authorization model.</para>
  4103. <para>TODO: Remove references to the old ACL package when it's
  4104. deprecated, and have all references to the replacement package limited
  4105. to the chapter describing the new ACL implementation.</para>
  4106. </sect1>
  4107. <sect1 id="after-invocation">
  4108. <title>After Invocation Handling</title>
  4109. <para>Whilst the <literal>AccessDecisionManager</literal> is called by
  4110. the <literal>AbstractSecurityInterceptor</literal> before proceeding
  4111. with the secure object invocation, some applications need a way of
  4112. modifying the object actually returned by the secure object
  4113. invocation. Whilst you could easily implement your own AOP concern to
  4114. achieve this, Spring Security provides a convenient hook that has
  4115. several concrete implementations that integrate with its ACL
  4116. capabilities.</para>
  4117. <para>Figure 5 illustrates Spring Security's
  4118. <literal>AfterInvocationManager</literal> and its concrete
  4119. implementations.</para>
  4120. <para><mediaobject>
  4121. <imageobject>
  4122. <imagedata align="center" fileref="images/AfterInvocation.gif"
  4123. format="GIF" />
  4124. </imageobject>
  4125. <caption>
  4126. <para>Figure 5: After Invocation Implementation</para>
  4127. </caption>
  4128. </mediaobject></para>
  4129. <para>Like many other parts of Spring Security,
  4130. <literal>AfterInvocationManager</literal> has a single concrete
  4131. implementation, <literal>AfterInvocationProviderManager</literal>,
  4132. which polls a list of <literal>AfterInvocationProvider</literal>s.
  4133. Each <literal>AfterInvocationProvider</literal> is allowed to modify
  4134. the return object or throw an
  4135. <literal>AccessDeniedException</literal>. Indeed multiple providers
  4136. can modify the object, as the result of the previous provider is
  4137. passed to the next in the list. Let's now consider our ACL-aware
  4138. implementations of <literal>AfterInvocationProvider</literal>.</para>
  4139. <para>Please be aware that if you're using
  4140. <literal>AfterInvocationManager</literal>, you will still need
  4141. configuration attributes that allow the
  4142. <literal>MethodSecurityInterceptor</literal>'s
  4143. <literal>AccessDecisionManager</literal> to allow an operation. If
  4144. you're using the typical Spring Security included
  4145. <literal>AccessDecisionManager</literal> implementations, having no
  4146. configuration attributes defined for a particular secure method
  4147. invocation will cause each <literal>AccessDecisionVoter</literal> to
  4148. abstain from voting. In turn, if the
  4149. <literal>AccessDecisionManager</literal> property
  4150. "<literal>allowIfAllAbstainDecisions</literal>" is
  4151. <literal>false</literal>, an <literal>AccessDeniedException</literal>
  4152. will be thrown. You may avoid this potential issue by either (i)
  4153. setting "<literal>allowIfAllAbstainDecisions</literal>" to
  4154. <literal>true</literal> (although this is generally not recommended)
  4155. or (ii) simply ensure that there is at least one configuration
  4156. attribute that an <literal>AccessDecisionVoter</literal> will vote to
  4157. grant access for. This latter (recommended) approach is usually
  4158. achieved through a <literal>ROLE_USER</literal> or
  4159. <literal>ROLE_AUTHENTICATED</literal> configuration attribute</para>
  4160. <sect2 id="after-invocation-acl-aware">
  4161. <title>ACL-Aware AfterInvocationProviders</title>
  4162. <para>PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new
  4163. ACL module. The new ACL module is a significant rewrite of the
  4164. existing ACL module. The new module can be found under the
  4165. <literal>org.springframework.security.acls</literal> package, with
  4166. the old ACL module under
  4167. <literal>org.springframework.security.acl</literal>. We encourage
  4168. users to consider testing with the new ACL module and build
  4169. applications with it. The old ACL module should be considered
  4170. deprecated and may be removed from a future release. The following
  4171. information relates to the new ACL package, and is thus
  4172. recommended.</para>
  4173. <para>A common services layer method we've all written at one stage
  4174. or another looks like this:</para>
  4175. <para><programlisting>public Contact getById(Integer id);</programlisting></para>
  4176. <para>Quite often, only principals with permission to read the
  4177. <literal>Contact</literal> should be allowed to obtain it. In this
  4178. situation the <literal>AccessDecisionManager</literal> approach
  4179. provided by the <literal>AbstractSecurityInterceptor</literal> will
  4180. not suffice. This is because the identity of the
  4181. <literal>Contact</literal> is all that is available before the
  4182. secure object is invoked. The
  4183. <literal>AclAfterInvocationProvider</literal> delivers a solution,
  4184. and is configured as follows:</para>
  4185. <para><programlisting>&lt;bean id="afterAclRead"
  4186. class="org.springframework.security.afterinvocation.AclEntryAfterInvocationProvider"&gt;
  4187. &lt;constructor-arg&gt;
  4188. &lt;ref bean="aclService"/&gt;
  4189. &lt;/constructor-arg&gt;
  4190. &lt;constructor-arg&gt;
  4191. &lt;list&gt;
  4192. &lt;ref local="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/&gt;
  4193. &lt;ref local="org.springframework.security.acls.domain.BasePermission.READ"/&gt;
  4194. &lt;/list&gt;
  4195. &lt;/constructor-arg&gt;
  4196. &lt;/bean&gt; </programlisting></para>
  4197. <para>In the above example, the <literal>Contact</literal> will be
  4198. retrieved and passed to the
  4199. <literal>AclEntryAfterInvocationProvider</literal>. The provider
  4200. will thrown an <literal>AccessDeniedException</literal> if one of
  4201. the listed <literal>requirePermission</literal>s is not held by the
  4202. <literal>Authentication</literal>. The
  4203. <literal>AclEntryAfterInvocationProvider</literal> queries the
  4204. <literal>Acl</literal>Service to determine the ACL that applies for
  4205. this domain object to this <literal>Authentication</literal>.</para>
  4206. <para>Similar to the
  4207. <literal>AclEntryAfterInvocationProvider</literal> is
  4208. <literal>AclEntryAfterInvocationCollectionFilteringProvider</literal>.
  4209. It is designed to remove <literal>Collection</literal> or array
  4210. elements for which a principal does not have access. It never thrown
  4211. an <literal>AccessDeniedException</literal> - simply silently
  4212. removes the offending elements. The provider is configured as
  4213. follows:</para>
  4214. <para><programlisting>&lt;bean id="afterAclCollectionRead"
  4215. class="org.springframework.security.afterinvocation.AclEntryAfterInvocationCollectionFilteringProvider"&gt;
  4216. &lt;constructor-arg&gt;
  4217. &lt;ref bean="aclService"/&gt;
  4218. &lt;/constructor-arg&gt;
  4219. &lt;constructor-arg&gt;
  4220. &lt;list&gt;
  4221. &lt;ref local="org.springframework.security.acls.domain.BasePermission.ADMINISTRATION"/&gt;
  4222. &lt;ref local="org.springframework.security.acls.domain.BasePermission.READ"/&gt;
  4223. &lt;/list&gt;
  4224. &lt;/constructor-arg&gt;
  4225. &lt;/bean&gt; </programlisting></para>
  4226. <para>As you can imagine, the returned <literal>Object</literal>
  4227. must be a <literal>Collection</literal> or array for this provider
  4228. to operate. It will remove any element if the
  4229. <literal>AclManager</literal> indicates the
  4230. <literal>Authentication</literal> does not hold one of the listed
  4231. <literal>requirePermission</literal>s.</para>
  4232. <para>The Contacts sample application demonstrates these two
  4233. <literal>AfterInvocationProvider</literal>s.</para>
  4234. </sect2>
  4235. <sect2 id="after-invocation-acl-aware-old">
  4236. <title>ACL-Aware AfterInvocationProviders (old ACL module)</title>
  4237. <para>PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new
  4238. ACL module. The new ACL module is a significant rewrite of the
  4239. existing ACL module. The new module can be found under the
  4240. <literal>org.springframework.security.acls</literal> package, with
  4241. the old ACL module under
  4242. <literal>org.springframework.security.acl</literal>. We encourage
  4243. users to consider testing with the new ACL module and build
  4244. applications with it. The old ACL module should be considered
  4245. deprecated and may be removed from a future release.</para>
  4246. <para>A common services layer method we've all written at one stage
  4247. or another looks like this:</para>
  4248. <para><programlisting>public Contact getById(Integer id);</programlisting></para>
  4249. <para>Quite often, only principals with permission to read the
  4250. <literal>Contact</literal> should be allowed to obtain it. In this
  4251. situation the <literal>AccessDecisionManager</literal> approach
  4252. provided by the <literal>AbstractSecurityInterceptor</literal> will
  4253. not suffice. This is because the identity of the
  4254. <literal>Contact</literal> is all that is available before the
  4255. secure object is invoked. The
  4256. <literal>BasicAclAfterInvocationProvider</literal> delivers a
  4257. solution, and is configured as follows:</para>
  4258. <para><programlisting>&lt;bean id="afterAclRead"
  4259. class="org.springframework.security.afterinvocation.BasicAclEntryAfterInvocationProvider"&gt;
  4260. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  4261. &lt;property name="requirePermission"&gt;
  4262. &lt;list&gt;
  4263. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  4264. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.READ"/&gt;
  4265. &lt;/list&gt;
  4266. &lt;/property&gt;
  4267. &lt;/bean&gt; </programlisting></para>
  4268. <para>In the above example, the <literal>Contact</literal> will be
  4269. retrieved and passed to the
  4270. <literal>BasicAclEntryAfterInvocationProvider</literal>. The
  4271. provider will thrown an <literal>AccessDeniedException</literal> if
  4272. one of the listed <literal>requirePermission</literal>s is not held
  4273. by the <literal>Authentication</literal>. The
  4274. <literal>BasicAclEntryAfterInvocationProvider</literal> queries the
  4275. <literal>AclManager</literal> to determine the ACL that applies for
  4276. this domain object to this <literal>Authentication</literal>.</para>
  4277. <para>Similar to the
  4278. <literal>BasicAclEntryAfterInvocationProvider</literal> is
  4279. <literal>BasicAclEntryAfterInvocationCollectionFilteringProvider</literal>.
  4280. It is designed to remove <literal>Collection</literal> or array
  4281. elements for which a principal does not have access. It never thrown
  4282. an <literal>AccessDeniedException</literal> - simply silently
  4283. removes the offending elements. The provider is configured as
  4284. follows:</para>
  4285. <para><programlisting>&lt;bean id="afterAclCollectionRead"
  4286. class="org.springframework.security.afterinvocation.BasicAclEntryAfterInvocationCollectionFilteringProvider"&gt;
  4287. &lt;property name="aclManager"&gt;&lt;ref local="aclManager"/&gt;&lt;/property&gt;
  4288. &lt;property name="requirePermission"&gt;
  4289. &lt;list&gt;
  4290. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.ADMINISTRATION"/&gt;
  4291. &lt;ref local="org.springframework.security.acl.basic.SimpleAclEntry.READ"/&gt;
  4292. &lt;/list&gt;
  4293. &lt;/property&gt;
  4294. &lt;/bean&gt; </programlisting></para>
  4295. <para>As you can imagine, the returned <literal>Object</literal>
  4296. must be a <literal>Collection</literal> or array for this provider
  4297. to operate. It will remove any element if the
  4298. <literal>AclManager</literal> indicates the
  4299. <literal>Authentication</literal> does not hold one of the listed
  4300. <literal>requirePermission</literal>s.</para>
  4301. <para>The Contacts sample application demonstrates these two
  4302. <literal>AfterInvocationProvider</literal>s.</para>
  4303. </sect2>
  4304. </sect1>
  4305. <sect1 id="authorization-taglibs">
  4306. <title>Authorization Tag Libraries</title>
  4307. <para><literal>AuthorizeTag</literal> is used to include content if
  4308. the current principal holds certain
  4309. <literal>GrantedAuthority</literal>s.</para>
  4310. <para>The following JSP fragment illustrates how to use the
  4311. <literal>AuthorizeTag</literal>:</para>
  4312. <para><programlisting>&lt;security:authorize ifAllGranted="ROLE_SUPERVISOR"&gt;
  4313. &lt;td&gt;
  4314. &lt;A HREF="del.htm?id=&lt;c:out value="${contact.id}"/&gt;"&gt;Del&lt;/A&gt;
  4315. &lt;/td&gt;
  4316. &lt;/security:authorize&gt; </programlisting></para>
  4317. <para>This tag would cause the tag's body to be output if the
  4318. principal has been granted ROLE_SUPERVISOR.</para>
  4319. <para>The <literal>security:authorize</literal> tag declares the
  4320. following attributes:</para>
  4321. <para><itemizedlist spacing="compact">
  4322. <listitem>
  4323. <para><literal>ifAllGranted</literal>: All the listed roles must
  4324. be granted for the tag to output its body.</para>
  4325. </listitem>
  4326. <listitem>
  4327. <para><literal>ifAnyGranted</literal>: Any of the listed roles
  4328. must be granted for the tag to output its body.</para>
  4329. </listitem>
  4330. <listitem>
  4331. <para><literal>ifNotGranted</literal>: None of the listed roles
  4332. must be granted for the tag to output its body.</para>
  4333. </listitem>
  4334. </itemizedlist></para>
  4335. <para>You'll note that in each attribute you can list multiple roles.
  4336. Simply separate the roles using a comma. The
  4337. <literal>authorize</literal> tag ignores whitespace in
  4338. attributes.</para>
  4339. <para>The tag library logically ANDs all of it's parameters together.
  4340. This means that if you combine two or more attributes, all attributes
  4341. must be true for the tag to output it's body. Don't add an
  4342. <literal>ifAllGranted="ROLE_SUPERVISOR"</literal>, followed by an
  4343. <literal>ifNotGranted="ROLE_SUPERVISOR"</literal>, or you'll be
  4344. surprised to never see the tag's body.</para>
  4345. <para>By requiring all attributes to return true, the authorize tag
  4346. allows you to create more complex authorization scenarios. For
  4347. example, you could declare an
  4348. <literal>ifAllGranted="ROLE_SUPERVISOR"</literal> and an
  4349. <literal>ifNotGranted="ROLE_NEWBIE_SUPERVISOR"</literal> in the same
  4350. tag, in order to prevent new supervisors from seeing the tag body.
  4351. However it would no doubt be simpler to use
  4352. <literal>ifAllGranted="ROLE_EXPERIENCED_SUPERVISOR"</literal> rather
  4353. than inserting NOT conditions into your design.</para>
  4354. <para>One last item: the tag verifies the authorizations in a specific
  4355. order: first <literal>ifNotGranted</literal>, then
  4356. <literal>ifAllGranted</literal>, and finally, <literal>if
  4357. AnyGranted</literal>.</para>
  4358. <para><literal>AccessControlListTag</literal> is used to include
  4359. content if the current principal has an ACL to the indicated domain
  4360. object.</para>
  4361. <para>The following JSP fragment illustrates how to use the
  4362. <literal>AccessControlListTag</literal>:</para>
  4363. <para><programlisting>&lt;security:accesscontrollist domainObject="${contact}" hasPermission="8,16"&gt;
  4364. &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;
  4365. &lt;/security:accesscontrollist&gt;</programlisting></para>
  4366. <para>This tag would cause the tag's body to be output if the
  4367. principal holds either permission 16 or permission 1 for the "contact"
  4368. domain object. The numbers are actually integers that are used with
  4369. <literal>BasePermission</literal> bit masking. Please refer to the ACL
  4370. section of this reference guide to understand more about the ACL
  4371. capabilities of Spring Security.</para>
  4372. <para><literal>AclTag</literal> is part of the old ACL module and
  4373. should be considered deprecated. For the sake of historical reference,
  4374. works exactly the samae as
  4375. <literal>AccessControlListTag</literal>.</para>
  4376. </sect1>
  4377. </chapter>
  4378. <chapter id="secure-object-impls">
  4379. <title>Secure Object Implementations</title>
  4380. <sect1 id="aop-alliance">
  4381. <title>AOP Alliance (MethodInvocation) Security Interceptor</title>
  4382. <para>To secure <literal>MethodInvocation</literal>s, developers
  4383. simply add a properly configured
  4384. <literal>MethodSecurityInterceptor</literal> into the application
  4385. context. Next the beans requiring security are chained into the
  4386. interceptor. This chaining is accomplished using Spring’s
  4387. <literal>ProxyFactoryBean</literal> or
  4388. <literal>BeanNameAutoProxyCreator</literal>, as commonly used by many
  4389. other parts of Spring (refer to the sample application for examples).
  4390. Alternatively, Spring Security provides a
  4391. <literal>MethodDefinitionSourceAdvisor</literal> which may be used
  4392. with Spring's <literal>DefaultAdvisorAutoProxyCreator</literal> to
  4393. automatically chain the security interceptor in front of any beans
  4394. defined against the <literal>MethodSecurityInterceptor</literal>. The
  4395. <literal>MethodSecurityInterceptor</literal> itself is configured as
  4396. follows:</para>
  4397. <programlisting>&lt;bean id="bankManagerSecurity"
  4398. class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;
  4399. &lt;property name="validateConfigAttributes"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
  4400. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  4401. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  4402. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  4403. &lt;property name="afterInvocationManager"&gt;&lt;ref bean="afterInvocationManager"/&gt;&lt;/property&gt;
  4404. &lt;property name="objectDefinitionSource"&gt;
  4405. &lt;value&gt;
  4406. org.springframework.security.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER
  4407. org.springframework.security.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
  4408. &lt;/value&gt;
  4409. &lt;/property&gt;
  4410. &lt;/bean&gt; </programlisting>
  4411. <para>As shown above, the <literal>MethodSecurityInterceptor</literal>
  4412. is configured with a reference to an
  4413. <literal>AuthenticationManager</literal>,
  4414. <literal>AccessDecisionManager</literal> and
  4415. <literal>RunAsManager</literal>, which are each discussed in separate
  4416. sections below. In this case we've also defined an
  4417. <literal>AfterInvocationManager</literal>, although this is entirely
  4418. optional. The <literal>MethodSecurityInterceptor</literal> is also
  4419. configured with configuration attributes that apply to different
  4420. method signatures. A full discussion of configuration attributes is
  4421. provided in the High Level Design section of this document.</para>
  4422. <para>The <literal>MethodSecurityInterceptor</literal> can be
  4423. configured with configuration attributes in three ways. The first is
  4424. via a property editor and the application context, which is shown
  4425. above. The second is via defining the configuration attributes in your
  4426. source code using Jakarta Commons Attributes or Java 5 Annotations.
  4427. The third is via writing your own
  4428. <literal>ObjectDefinitionSource</literal>, although this is beyond the
  4429. scope of this document. Irrespective of the approach used, the
  4430. <literal>ObjectDefinitionSource</literal> is responsible for returning
  4431. a <literal>ConfigAttributeDefinition</literal> object that contains
  4432. all of the configuration attributes associated with a single secure
  4433. method.</para>
  4434. <para>It should be noted that the
  4435. <literal>MethodSecurityInterceptor.setObjectDefinitionSource()</literal>
  4436. method actually expects an instance of
  4437. <literal>MethodDefinitionSource</literal>. This is a marker interface
  4438. which subclasses <literal>ObjectDefinitionSource</literal>. It simply
  4439. denotes the <literal>ObjectDefinitionSource</literal> understands
  4440. <literal>MethodInvocation</literal>s. In the interests of simplicity
  4441. we'll continue to refer to the
  4442. <literal>MethodDefinitionSource</literal> as an
  4443. <literal>ObjectDefinitionSource</literal>, as the distinction is of
  4444. little relevance to most users of the
  4445. <literal>MethodSecurityInterceptor</literal>.</para>
  4446. <para>If using the application context property editor approach (as
  4447. shown above), commas are used to delimit the different configuration
  4448. attributes that apply to a given method pattern. Each configuration
  4449. attribute is assigned into its own <literal>SecurityConfig</literal>
  4450. object. The <literal>SecurityConfig</literal> object is discussed in
  4451. the High Level Design section.</para>
  4452. <para>If you are using the Jakarta Commons Attributes approach, your
  4453. bean context will be configured differently:</para>
  4454. <programlisting>&lt;bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes"/&gt;
  4455. &lt;bean id="objectDefinitionSource"
  4456. class="org.springframework.security.intercept.method.MethodDefinitionAttributes"&gt;
  4457. &lt;property name="attributes"&gt;&lt;ref local="attributes"/&gt;&lt;/property&gt;
  4458. &lt;/bean&gt;
  4459. &lt;bean id="bankManagerSecurity"
  4460. class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;
  4461. &lt;property name="validateConfigAttributes"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  4462. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  4463. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  4464. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  4465. &lt;property name="objectDefinitionSource"&gt;&lt;ref bean="objectDefinitionSource"/&gt;&lt;/property&gt;
  4466. &lt;/bean&gt; </programlisting>
  4467. <para>In addition, your source code will contain Jakarta Commons
  4468. Attributes tags that refer to a concrete implementation of
  4469. <literal>ConfigAttribute</literal>. The following example uses the
  4470. <literal>SecurityConfig</literal> implementation to represent the
  4471. configuration attributes, and results in the same security
  4472. configuration as provided by the property editor approach
  4473. above:</para>
  4474. <programlisting>public interface BankManager {
  4475. /**
  4476. * @@SecurityConfig("ROLE_SUPERVISOR")
  4477. * @@SecurityConfig("RUN_AS_SERVER")
  4478. */
  4479. public void deleteSomething(int id);
  4480. /**
  4481. * @@SecurityConfig("ROLE_SUPERVISOR")
  4482. * @@SecurityConfig("RUN_AS_SERVER")
  4483. */
  4484. public void deleteAnother(int id);
  4485. /**
  4486. * @@SecurityConfig("ROLE_TELLER")
  4487. * @@SecurityConfig("ROLE_SUPERVISOR")
  4488. * @@SecurityConfig("BANKSECURITY_CUSTOMER")
  4489. * @@SecurityConfig("RUN_AS_SERVER")
  4490. */
  4491. public float getBalance(int id);
  4492. }</programlisting>
  4493. <para>If you are using the Spring Security Java 5 Annotations
  4494. approach, your bean context will be configured as follows:</para>
  4495. <programlisting>&lt;bean id="attributes"
  4496. class="org.springframework.security.annotation.SecurityAnnotationAttributes"/&gt;
  4497. &lt;bean id="objectDefinitionSource"
  4498. class="org.springframework.security.intercept.method.MethodDefinitionAttributes"&gt;
  4499. &lt;property name="attributes"&gt;&lt;ref local="attributes"/&gt;&lt;/property&gt;
  4500. &lt;/bean&gt;
  4501. &lt;bean id="bankManagerSecurity"
  4502. class="org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor"&gt;
  4503. &lt;property name="validateConfigAttributes"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  4504. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  4505. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  4506. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  4507. &lt;property name="objectDefinitionSource"&gt;&lt;ref bean="objectDefinitionSource"/&gt;&lt;/property&gt;
  4508. &lt;/bean&gt; </programlisting>
  4509. <para>In addition, your source code will contain Spring Security Java
  4510. 5 Security Annotations that represent the
  4511. <literal>ConfigAttribute</literal>. The following example uses the
  4512. <literal>@Secured</literal> annotations to represent the configuration
  4513. attributes, and results in the same security configuration as provided
  4514. by the property editor approach:</para>
  4515. <programlisting>import org.springframework.security.annotation.Secured;
  4516. public interface BankManager {
  4517. /**
  4518. * Delete something
  4519. */
  4520. @Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" })
  4521. public void deleteSomething(int id);
  4522. /**
  4523. * Delete another
  4524. */
  4525. @Secured({"ROLE_SUPERVISOR","RUN_AS_SERVER" })
  4526. public void deleteAnother(int id);
  4527. /**
  4528. * Get balance
  4529. */
  4530. @Secured({"ROLE_TELLER","ROLE_SUPERVISOR","BANKSECURITY_CUSTOMER","RUN_AS_SERVER" })
  4531. public float getBalance(int id);
  4532. }</programlisting>
  4533. <para>You might have noticed the
  4534. <literal>validateConfigAttributes</literal> property in the above
  4535. <literal>MethodSecurityInterceptor</literal> examples. When set to
  4536. <literal>true</literal> (the default), at startup time the
  4537. <literal>MethodSecurityInterceptor</literal> will evaluate if the
  4538. provided configuration attributes are valid. It does this by checking
  4539. each configuration attribute can be processed by either the
  4540. <literal>AccessDecisionManager</literal> or the
  4541. <literal>RunAsManager</literal>. If neither of these can process a
  4542. given configuration attribute, an exception is thrown. If using the
  4543. Jakarta Commons Attributes method of configuration, you should set
  4544. <literal>validateConfigAttributes</literal> to
  4545. <literal>false</literal>.</para>
  4546. <para>Please note that when using
  4547. <literal>BeanNameAutoProxyCreator</literal> to create the required
  4548. proxy for security, the configuration must contain the property
  4549. <literal>proxyTargetClass</literal> set to <literal>true</literal>.
  4550. Otherwise, the method passed to
  4551. <literal>MethodSecurityInterceptor.invoke</literal> is the proxy's
  4552. caller, not the proxy's target. Note that this introduces a
  4553. requirement on CGLIB. See an example of using
  4554. <literal>BeanNameAutoProxyCreator</literal> below:</para>
  4555. <programlisting>&lt;bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"&gt;
  4556. &lt;property name="interceptorNames"&gt;
  4557. &lt;list&gt;&lt;value&gt;methodSecurityInterceptor&lt;/value&gt;&lt;/list&gt;
  4558. &lt;/property&gt;
  4559. &lt;property name="beanNames"&gt;
  4560. &lt;list&gt;&lt;value&gt;targetObjectName&lt;/value&gt;&lt;/list&gt;
  4561. &lt;/property&gt;
  4562. &lt;property name="proxyTargetClass" value="true"/&gt;
  4563. &lt;/bean&gt; </programlisting>
  4564. </sect1>
  4565. <sect1 id="aspectj">
  4566. <title>AspectJ (JoinPoint) Security Interceptor</title>
  4567. <para>The AspectJ security interceptor is very similar to the AOP
  4568. Alliance security interceptor discussed in the previous section.
  4569. Indeed we will only discuss the differences in this section.</para>
  4570. <para>The AspectJ interceptor is named
  4571. <literal>AspectJSecurityInterceptor</literal>. Unlike the AOP Alliance
  4572. security interceptor, which relies on the Spring application context
  4573. to weave in the security interceptor via proxying, the
  4574. <literal>AspectJSecurityInterceptor</literal> is weaved in via the
  4575. AspectJ compiler. It would not be uncommon to use both types of
  4576. security interceptors in the same application, with
  4577. <literal>AspectJSecurityInterceptor</literal> being used for domain
  4578. object instance security and the AOP Alliance
  4579. <literal>MethodSecurityInterceptor</literal> being used for services
  4580. layer security.</para>
  4581. <para>Let's first consider how the
  4582. <literal>AspectJSecurityInterceptor</literal> is configured in the
  4583. Spring application context:</para>
  4584. <programlisting>&lt;bean id="bankManagerSecurity"
  4585. class="org.springframework.security.intercept.method.aspectj.AspectJSecurityInterceptor"&gt;
  4586. &lt;property name="validateConfigAttributes"&gt;&lt;value&gt;true&lt;/value&gt;&lt;/property&gt;
  4587. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  4588. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  4589. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  4590. &lt;property name="afterInvocationManager"&gt;&lt;ref bean="afterInvocationManager"/&gt;&lt;/property&gt;
  4591. &lt;property name="objectDefinitionSource"&gt;
  4592. &lt;value&gt;
  4593. org.springframework.security.context.BankManager.delete*=ROLE_SUPERVISOR,RUN_AS_SERVER
  4594. org.springframework.security.context.BankManager.getBalance=ROLE_TELLER,ROLE_SUPERVISOR,BANKSECURITY_CUSTOMER,RUN_AS_SERVER
  4595. &lt;/value&gt;
  4596. &lt;/property&gt;
  4597. &lt;/bean&gt; </programlisting>
  4598. <para>As you can see, aside from the class name, the
  4599. <literal>AspectJSecurityInterceptor</literal> is exactly the same as
  4600. the AOP Alliance security interceptor. Indeed the two interceptors can
  4601. share the same <literal>objectDefinitionSource</literal>, as the
  4602. <literal>ObjectDefinitionSource</literal> works with
  4603. <literal>java.lang.reflect.Method</literal>s rather than an AOP
  4604. library-specific class. Of course, your access decisions have access
  4605. to the relevant AOP library-specific invocation (ie
  4606. <literal>MethodInvocation</literal> or <literal>JoinPoint</literal>)
  4607. and as such can consider a range of addition criteria when making
  4608. access decisions (such as method arguments).</para>
  4609. <para>Next you'll need to define an AspectJ <literal>aspect</literal>.
  4610. For example:</para>
  4611. <programlisting>package org.springframework.security.samples.aspectj;
  4612. import org.springframework.security.intercept.method.aspectj.AspectJSecurityInterceptor;
  4613. import org.springframework.security.intercept.method.aspectj.AspectJCallback;
  4614. import org.springframework.beans.factory.InitializingBean;
  4615. public aspect DomainObjectInstanceSecurityAspect implements InitializingBean {
  4616. private AspectJSecurityInterceptor securityInterceptor;
  4617. pointcut domainObjectInstanceExecution(): target(PersistableEntity)
  4618. &amp;&amp; execution(public * *(..)) &amp;&amp; !within(DomainObjectInstanceSecurityAspect);
  4619. Object around(): domainObjectInstanceExecution() {
  4620. if (this.securityInterceptor != null) {
  4621. AspectJCallback callback = new AspectJCallback() {
  4622. public Object proceedWithObject() {
  4623. return proceed();
  4624. }
  4625. };
  4626. return this.securityInterceptor.invoke(thisJoinPoint, callback);
  4627. } else {
  4628. return proceed();
  4629. }
  4630. }
  4631. public AspectJSecurityInterceptor getSecurityInterceptor() {
  4632. return securityInterceptor;
  4633. }
  4634. public void setSecurityInterceptor(AspectJSecurityInterceptor securityInterceptor) {
  4635. this.securityInterceptor = securityInterceptor;
  4636. }
  4637. public void afterPropertiesSet() throws Exception {
  4638. if (this.securityInterceptor == null)
  4639. throw new IllegalArgumentException("securityInterceptor required");
  4640. }
  4641. }</programlisting>
  4642. <para>In the above example, the security interceptor will be applied
  4643. to every instance of <literal>PersistableEntity</literal>, which is an
  4644. abstract class not shown (you can use any other class or
  4645. <literal>pointcut</literal> expression you like). For those curious,
  4646. <literal>AspectJCallback</literal> is needed because the
  4647. <literal>proceed();</literal> statement has special meaning only
  4648. within an <literal>around()</literal> body. The
  4649. <literal>AspectJSecurityInterceptor</literal> calls this anonymous
  4650. <literal>AspectJCallback</literal> class when it wants the target
  4651. object to continue.</para>
  4652. <para>You will need to configure Spring to load the aspect and wire it
  4653. with the <literal>AspectJSecurityInterceptor</literal>. A bean
  4654. declaration which achieves this is shown below:</para>
  4655. <programlisting>
  4656. &lt;bean id="domainObjectInstanceSecurityAspect"
  4657. class="org.springframework.security.samples.aspectj.DomainObjectInstanceSecurityAspect"
  4658. factory-method="aspectOf"&gt;
  4659. &lt;property name="securityInterceptor"&gt;&lt;ref bean="aspectJSecurityInterceptor"/&gt;&lt;/property&gt;
  4660. &lt;/bean&gt;
  4661. </programlisting>
  4662. <para>That's it! Now you can create your beans from anywhere within
  4663. your application, using whatever means you think fit (eg <literal>new
  4664. Person();</literal>) and they will have the security interceptor
  4665. applied.</para>
  4666. </sect1>
  4667. <sect1 id="filter-invocation-authorization">
  4668. <title>FilterInvocation Security Interceptor</title>
  4669. <para>To secure <literal>FilterInvocation</literal>s, developers need
  4670. to add a filter to their <literal>web.xml</literal> that delegates to
  4671. the <literal>FilterSecurityInterceptor</literal>. A typical
  4672. configuration example is provided below:</para>
  4673. <programlisting>&lt;filter&gt;
  4674. &lt;filter-name&gt;Spring Security HTTP Request Security Filter&lt;/filter-name&gt;
  4675. &lt;filter-class&gt;org.springframework.security.util.FilterToBeanProxy&lt;/filter-class&gt;
  4676. &lt;init-param&gt;
  4677. &lt;param-name&gt;targetClass&lt;/param-name&gt;
  4678. &lt;param-value&gt;org.springframework.security.intercept.web.FilterSecurityInterceptor&lt;/param-value&gt;
  4679. &lt;/init-param&gt;
  4680. &lt;/filter&gt;
  4681. &lt;filter-mapping&gt;
  4682. &lt;filter-name&gt;Spring Security HTTP Request Security Filter&lt;/filter-name&gt;
  4683. &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
  4684. &lt;/filter-mapping&gt;</programlisting>
  4685. <para>Notice that the filter is actually a
  4686. <literal>FilterToBeanProxy</literal>. Most of the filters used by
  4687. Spring Security use this class. Refer to the Filters section to learn
  4688. more about this bean.</para>
  4689. <para>In the application context you will need to configure three
  4690. beans:</para>
  4691. <programlisting>&lt;bean id="exceptionTranslationFilter"
  4692. class="org.springframework.security.ui.ExceptionTranslationFilter"&gt;
  4693. &lt;property name="authenticationEntryPoint"&gt;&lt;ref local="authenticationEntryPoint"/&gt;&lt;/property&gt;
  4694. &lt;/bean&gt;
  4695. &lt;bean id="authenticationEntryPoint"
  4696. class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint"&gt;
  4697. &lt;property name="loginFormUrl"&gt;&lt;value&gt;/acegilogin.jsp&lt;/value&gt;&lt;/property&gt;
  4698. &lt;property name="forceHttps"&gt;&lt;value&gt;false&lt;/value&gt;&lt;/property&gt;
  4699. &lt;/bean&gt;
  4700. &lt;bean id="filterSecurityInterceptor"
  4701. class="org.springframework.security.intercept.web.FilterSecurityInterceptor"&gt;
  4702. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  4703. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  4704. &lt;property name="objectDefinitionSource"&gt;
  4705. &lt;value&gt;
  4706. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  4707. \A/secure/super/.*\Z=ROLE_WE_DONT_HAVE
  4708. \A/secure/.*\Z=ROLE_SUPERVISOR,ROLE_TELLER
  4709. &lt;/value&gt;
  4710. &lt;/property&gt;
  4711. &lt;/bean&gt; </programlisting>
  4712. <para>The <classname>ExceptionTranslationFilter</classname> provides
  4713. the bridge between Java exceptions and HTTP responses. It is solely
  4714. concerned with maintaining the user interface. This filter does not do
  4715. any actual security enforcement. If an
  4716. <exceptionname>AuthenticationException</exceptionname> is detected,
  4717. the filter will call the AuthenticationEntryPoint to commence the
  4718. authentication process (e.g. a user login).</para>
  4719. <para>The <literal>AuthenticationEntryPoint</literal> will be called
  4720. if the user requests a secure HTTP resource but they are not
  4721. authenticated. The class handles presenting the appropriate response
  4722. to the user so that authentication can begin. Three concrete
  4723. implementations are provided with Spring Security:
  4724. <literal>AuthenticationProcessingFilterEntryPoint</literal> for
  4725. commencing a form-based authentication,
  4726. <literal>BasicProcessingFilterEntryPoint</literal> for commencing a
  4727. HTTP Basic authentication process, and
  4728. <literal>CasProcessingFilterEntryPoint</literal> for commencing a
  4729. JA-SIG Central Authentication Service (CAS) login. The
  4730. <literal>AuthenticationProcessingFilterEntryPoint</literal> and
  4731. <literal>CasProcessingFilterEntryPoint</literal> have optional
  4732. properties related to forcing the use of HTTPS, so please refer to the
  4733. JavaDocs if you require this.</para>
  4734. <para><literal>FilterSecurityInterceptor</literal> is responsible for
  4735. handling the security of HTTP resources. Like any other security
  4736. interceptor, it requires a reference to an
  4737. <literal>AuthenticationManager</literal> and an
  4738. <literal>AccessDecisionManager</literal>, which are both discussed in
  4739. separate sections below. The
  4740. <literal>FilterSecurityInterceptor</literal> is also configured with
  4741. configuration attributes that apply to different HTTP URL requests. A
  4742. full discussion of configuration attributes is provided in the High
  4743. Level Design section of this document.</para>
  4744. <para>The <literal>FilterSecurityInterceptor</literal> can be
  4745. configured with configuration attributes in two ways. The first is via
  4746. a property editor and the application context, which is shown above.
  4747. The second is via writing your own
  4748. <literal>ObjectDefinitionSource</literal>, although this is beyond the
  4749. scope of this document. Irrespective of the approach used, the
  4750. <literal>ObjectDefinitionSource</literal> is responsible for returning
  4751. a <literal>ConfigAttributeDefinition</literal> object that contains
  4752. all of the configuration attributes associated with a single secure
  4753. HTTP URL.</para>
  4754. <para>It should be noted that the
  4755. <literal>FilterSecurityInterceptor.setObjectDefinitionSource()</literal>
  4756. method actually expects an instance of
  4757. <literal>FilterInvocationDefinitionSource</literal>. This is a marker
  4758. interface which subclasses <literal>ObjectDefinitionSource</literal>.
  4759. It simply denotes the <literal>ObjectDefinitionSource</literal>
  4760. understands <literal>FilterInvocation</literal>s. In the interests of
  4761. simplicity we'll continue to refer to the
  4762. <literal>FilterInvocationDefinitionSource</literal> as an
  4763. <literal>ObjectDefinitionSource</literal>, as the distinction is of
  4764. little relevance to most users of the
  4765. <literal>FilterSecurityInterceptor</literal>.</para>
  4766. <para>If using the application context property editor approach (as
  4767. shown above), commas are used to delimit the different configuration
  4768. attributes that apply to each HTTP URL. Each configuration attribute
  4769. is assigned into its own <literal>SecurityConfig</literal> object. The
  4770. <literal>SecurityConfig</literal> object is discussed in the High
  4771. Level Design section. The <literal>ObjectDefinitionSource</literal>
  4772. created by the property editor,
  4773. <literal>FilterInvocationDefinitionSource</literal>, matches
  4774. configuration attributes against <literal>FilterInvocations</literal>
  4775. based on expression evaluation of the request URL. Two standard
  4776. expression syntaxes are supported. The default is to treat all
  4777. expressions as regular expressions. Alternatively, the presence of a
  4778. <literal>PATTERN_TYPE_APACHE_ANT</literal> directive will cause all
  4779. expressions to be treated as Apache Ant paths. It is not possible to
  4780. mix expression syntaxes within the same definition. For example, the
  4781. earlier configuration could be generated using Apache Ant paths as
  4782. follows:</para>
  4783. <programlisting>&lt;bean id="filterInvocationInterceptor"
  4784. class="org.springframework.security.intercept.web.FilterSecurityInterceptor"&gt;
  4785. &lt;property name="authenticationManager"&gt;&lt;ref bean="authenticationManager"/&gt;&lt;/property&gt;
  4786. &lt;property name="accessDecisionManager"&gt;&lt;ref bean="accessDecisionManager"/&gt;&lt;/property&gt;
  4787. &lt;property name="runAsManager"&gt;&lt;ref bean="runAsManager"/&gt;&lt;/property&gt;
  4788. &lt;property name="objectDefinitionSource"&gt;
  4789. &lt;value&gt;
  4790. CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
  4791. PATTERN_TYPE_APACHE_ANT
  4792. /secure/super/**=ROLE_WE_DONT_HAVE
  4793. /secure/**=ROLE_SUPERVISOR,ROLE_TELLER
  4794. &lt;/value&gt;
  4795. &lt;/property&gt;
  4796. &lt;/bean&gt; </programlisting>
  4797. <para>Irrespective of the type of expression syntax used, expressions
  4798. are always evaluated in the order they are defined. Thus it is
  4799. important that more specific expressions are defined higher in the
  4800. list than less specific expressions. This is reflected in our example
  4801. above, where the more specific <literal>/secure/super/</literal>
  4802. pattern appears higher than the less specific
  4803. <literal>/secure/</literal> pattern. If they were reversed, the
  4804. <literal>/secure/</literal> pattern would always match and the
  4805. <literal>/secure/super/</literal> pattern would never be
  4806. evaluated.</para>
  4807. <para>The special keyword
  4808. <literal>CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</literal> causes
  4809. the <literal>FilterInvocationDefinitionSource</literal> to
  4810. automatically convert a request URL to lowercase before comparison
  4811. against the expressions. Whilst by default the case of the request URL
  4812. is not converted, it is generally recommended to use
  4813. <literal>CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON</literal> and
  4814. write each expression assuming lowercase.</para>
  4815. <para>As with other security interceptors, the
  4816. <literal>validateConfigAttributes</literal> property is observed. When
  4817. set to <literal>true</literal> (the default), at startup time the
  4818. <literal>FilterSecurityInterceptor</literal> will evaluate if the
  4819. provided configuration attributes are valid. It does this by checking
  4820. each configuration attribute can be processed by either the
  4821. <literal>AccessDecisionManager</literal> or the
  4822. <literal>RunAsManager</literal>. If neither of these can process a
  4823. given configuration attribute, an exception is thrown.</para>
  4824. </sect1>
  4825. </chapter>
  4826. <chapter id="domain-acls">
  4827. <title>Domain Object Security</title>
  4828. <section id="domain-acls-overview">
  4829. <title>Overview</title>
  4830. <para>PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new
  4831. ACL module. The new ACL module is a significant rewrite of the
  4832. existing ACL module. The new module can be found under the
  4833. <literal>org.springframework.security.acls</literal> package, with the
  4834. old ACL module under
  4835. <literal>org.springframework.security.acl</literal>. We encourage
  4836. users to consider testing with the new ACL module and build
  4837. applications with it. The old ACL module should be considered
  4838. deprecated and may be removed from a future release.</para>
  4839. <para>Complex applications often will find the need to define access
  4840. permissions not simply at a web request or method invocation level.
  4841. Instead, security decisions need to comprise both who
  4842. (<literal>Authentication</literal>), where
  4843. (<literal>MethodInvocation</literal>) and what
  4844. (<literal>SomeDomainObject</literal>). In other words, authorization
  4845. decisions also need to consider the actual domain object instance
  4846. subject of a method invocation.</para>
  4847. <para>Imagine you're designing an application for a pet clinic. There
  4848. will be two main groups of users of your Spring-based application:
  4849. staff of the pet clinic, as well as the pet clinic's customers. The
  4850. staff will have access to all of the data, whilst your customers will
  4851. only be able to see their own customer records. To make it a little
  4852. more interesting, your customers can allow other users to see their
  4853. customer records, such as their "puppy preschool "mentor or president
  4854. of their local "Pony Club". Using Spring Security as the foundation,
  4855. you have several approaches that can be used:<orderedlist>
  4856. <listitem>
  4857. <para>Write your business methods to enforce the security. You
  4858. could consult a collection within the
  4859. <literal>Customer</literal> domain object instance to determine
  4860. which users have access. By using the
  4861. <literal>SecurityContextHolder.getContext().getAuthentication()</literal>,
  4862. you'll be able to access the <literal>Authentication</literal>
  4863. object.</para>
  4864. </listitem>
  4865. <listitem>
  4866. <para>Write an <literal>AccessDecisionVoter</literal> to enforce
  4867. the security from the <literal>GrantedAuthority[]</literal>s
  4868. stored in the <literal>Authentication</literal> object. This
  4869. would mean your <literal>AuthenticationManager</literal> would
  4870. need to populate the <literal>Authentication</literal> with
  4871. custom <literal>GrantedAuthority</literal>[]s representing each
  4872. of the <literal>Customer</literal> domain object instances the
  4873. principal has access to.</para>
  4874. </listitem>
  4875. <listitem>
  4876. <para>Write an <literal>AccessDecisionVoter</literal> to enforce
  4877. the security and open the target <literal>Customer</literal>
  4878. domain object directly. This would mean your voter needs access
  4879. to a DAO that allows it to retrieve the
  4880. <literal>Customer</literal> object. It would then access the
  4881. <literal>Customer</literal> object's collection of approved
  4882. users and make the appropriate decision.</para>
  4883. </listitem>
  4884. </orderedlist></para>
  4885. <para>Each one of these approaches is perfectly legitimate. However,
  4886. the first couples your authorization checking to your business code.
  4887. The main problems with this include the enhanced difficulty of unit
  4888. testing and the fact it would be more difficult to reuse the
  4889. <literal>Customer</literal> authorization logic elsewhere. Obtaining
  4890. the <literal>GrantedAuthority[]</literal>s from the
  4891. <literal>Authentication</literal> object is also fine, but will not
  4892. scale to large numbers of <literal>Customer</literal>s. If a user
  4893. might be able to access 5,000 <literal>Customer</literal>s (unlikely
  4894. in this case, but imagine if it were a popular vet for a large Pony
  4895. Club!) the amount of memory consumed and time required to construct
  4896. the <literal>Authentication</literal> object would be undesirable. The
  4897. final method, opening the <literal>Customer</literal> directly from
  4898. external code, is probably the best of the three. It achieves
  4899. separation of concerns, and doesn't misuse memory or CPU cycles, but
  4900. it is still inefficient in that both the
  4901. <literal>AccessDecisionVoter</literal> and the eventual business
  4902. method itself will perform a call to the DAO responsible for
  4903. retrieving the <literal>Customer</literal> object. Two accesses per
  4904. method invocation is clearly undesirable. In addition, with every
  4905. approach listed you'll need to write your own access control list
  4906. (ACL) persistence and business logic from scratch.</para>
  4907. <para>Fortunately, there is another alternative, which we'll talk
  4908. about below.</para>
  4909. </section>
  4910. <section id="domain-acls-key-concepts">
  4911. <title>Key Concepts</title>
  4912. <para>The org.springframework.security.acls package should be
  4913. consulted for its major interfaces. The key interfaces are:</para>
  4914. <itemizedlist spacing="compact">
  4915. <listitem>
  4916. <para><literal>Acl</literal>: Every domain object has one and only
  4917. one <literal>Acl</literal> object, which internally holds the
  4918. <literal>AccessControlEntry</literal>s as well as knows the owner
  4919. of the <literal>Acl</literal>. An Acl does not refer directly to
  4920. the domain object, but instead to an
  4921. <literal>ObjectIdentity</literal>.</para>
  4922. </listitem>
  4923. <listitem>
  4924. <para><literal><literal>AccessControlEntry</literal></literal>: An
  4925. Acl holds multiple <literal>AccessControlEntry</literal>s, which
  4926. are often abbreviated as ACEs in the framework. Each ACE refers to
  4927. a specific tuple of <literal>Permission</literal>,
  4928. <literal>Sid</literal> and <literal>Acl</literal>. An ACE can also
  4929. be granting or non-granting and contain audit settings.</para>
  4930. </listitem>
  4931. <listitem>
  4932. <para><literal>Permission</literal>: A permission represents an
  4933. immutable particular bit mask, and offers convenience functions
  4934. for bit masking and outputting information.</para>
  4935. </listitem>
  4936. <listitem>
  4937. <para><literal>Sid</literal>: The ACL module needs to refer to
  4938. principals and <literal>GrantedAuthority[]</literal>s. A level of
  4939. indirection is provided by the <literal>Sid</literal> interface.
  4940. Common classes include <literal>PrincipalSid</literal> (to
  4941. represent the principal inside an
  4942. <literal>Authentication</literal> object) and
  4943. <literal>GrantedAuthoritySid</literal>.</para>
  4944. </listitem>
  4945. <listitem>
  4946. <para><literal>ObjectIdentity</literal>: Each domain object is
  4947. represented internally within the ACL module by an
  4948. <literal>ObjectIdentity</literal>.</para>
  4949. </listitem>
  4950. <listitem>
  4951. <para><literal>AclService</literal>: Retrieves the
  4952. <literal>Acl</literal> applicable for a given
  4953. <literal>ObjectIdentity</literal>.</para>
  4954. </listitem>
  4955. <listitem>
  4956. <para><literal>MutableAclService</literal>: Allows a modified
  4957. <literal>Acl</literal> to be presented for persistence. It is not
  4958. essential to use this interface if you do not wish.</para>
  4959. </listitem>
  4960. </itemizedlist>
  4961. <para>The ACL module was based on extensive feedback from the user
  4962. community following real-world use of the original ACL module. This
  4963. feedback resulted in a rearchitecture of the ACL module to offer
  4964. significantly enhanced performance (particularly in the area of
  4965. database retrieval), significantly better encapsulation, higher
  4966. cohesion, and enhanced customisation points.</para>
  4967. <para>The Contacts Sample that ships with Acegi Security 1.0.3 offers
  4968. a demonstration of the new ACL module. Converting Contacts from using
  4969. the old module to the new module was relatively simple, and users of
  4970. the old ACL module will likely find their applications can be modified
  4971. with relatively little work.</para>
  4972. <para>We will document the new ACL module more fully with a subsequent
  4973. release. Please note that the new ACL module should be considered a
  4974. preview only (ie do not use in production without proper prior
  4975. testing), and there is a small chance there may be changes between
  4976. 1.0.3 and 1.1.0 when it will become final. Nevertheless,
  4977. compatibility-affecting changes are considered quite unlikely,
  4978. especially given the module is already based on several years of
  4979. feedback from users of the original ACL module.</para>
  4980. </section>
  4981. </chapter>
  4982. <chapter id="domain-acls-old">
  4983. <title>Domain Object Security (old ACL module)</title>
  4984. <section id="domain-acls-overview-old">
  4985. <title>Overview</title>
  4986. <para>PLEASE NOTE: Acegi Security 1.0.3 contains a preview of a new
  4987. ACL module. The new ACL module is a significant rewrite of the
  4988. existing ACL module. The new module can be found under the
  4989. <literal>org.springframework.security.acls</literal> package, with the
  4990. old ACL module under
  4991. <literal>org.springframework.security.acl</literal>. We encourage
  4992. users to consider testing with the new ACL module and build
  4993. applications with it. The old ACL module should be considered
  4994. deprecated and may be removed from a future release.</para>
  4995. <para>Complex applications often will find the need to define access
  4996. permissions not simply at a web request or method invocation level.
  4997. Instead, security decisions need to comprise both who
  4998. (<literal>Authentication</literal>), where
  4999. (<literal>MethodInvocation</literal>) and what
  5000. (<literal>SomeDomainObject</literal>). In other words, authorization
  5001. decisions also need to consider the actual domain object instance
  5002. subject of a method invocation.</para>
  5003. <para>Imagine you're designing an application for a pet clinic. There
  5004. will be two main groups of users of your Spring-based application:
  5005. staff of the pet clinic, as well as the pet clinic's customers. The
  5006. staff will have access to all of the data, whilst your customers will
  5007. only be able to see their own customer records. To make it a little
  5008. more interesting, your customers can allow other users to see their
  5009. customer records, such as their "puppy preschool "mentor or president
  5010. of their local "Pony Club". Using Spring Security as the foundation,
  5011. you have several approaches that can be used:<orderedlist>
  5012. <listitem>
  5013. <para>Write your business methods to enforce the security. You
  5014. could consult a collection within the
  5015. <literal>Customer</literal> domain object instance to determine
  5016. which users have access. By using the
  5017. <literal>SecurityContextHolder.getContext().getAuthentication()</literal>,
  5018. you'll be able to access the <literal>Authentication</literal>
  5019. object.</para>
  5020. </listitem>
  5021. <listitem>
  5022. <para>Write an <literal>AccessDecisionVoter</literal> to enforce
  5023. the security from the <literal>GrantedAuthority[]</literal>s
  5024. stored in the <literal>Authentication</literal> object. This
  5025. would mean your <literal>AuthenticationManager</literal> would
  5026. need to populate the <literal>Authentication</literal> with
  5027. custom <literal>GrantedAuthority</literal>[]s representing each
  5028. of the <literal>Customer</literal> domain object instances the
  5029. principal has access to.</para>
  5030. </listitem>
  5031. <listitem>
  5032. <para>Write an <literal>AccessDecisionVoter</literal> to enforce
  5033. the security and open the target <literal>Customer</literal>
  5034. domain object directly. This would mean your voter needs access
  5035. to a DAO that allows it to retrieve the
  5036. <literal>Customer</literal> object. It would then access the
  5037. <literal>Customer</literal> object's collection of approved
  5038. users and make the appropriate decision.</para>
  5039. </listitem>
  5040. </orderedlist></para>
  5041. <para>Each one of these approaches is perfectly legitimate. However,
  5042. the first couples your authorization checking to your business code.
  5043. The main problems with this include the enhanced difficulty of unit
  5044. testing and the fact it would be more difficult to reuse the
  5045. <literal>Customer</literal> authorization logic elsewhere. Obtaining
  5046. the <literal>GrantedAuthority[]</literal>s from the
  5047. <literal>Authentication</literal> object is also fine, but will not
  5048. scale to large numbers of <literal>Customer</literal>s. If a user
  5049. might be able to access 5,000 <literal>Customer</literal>s (unlikely
  5050. in this case, but imagine if it were a popular vet for a large Pony
  5051. Club!) the amount of memory consumed and time required to construct
  5052. the <literal>Authentication</literal> object would be undesirable. The
  5053. final method, opening the <literal>Customer</literal> directly from
  5054. external code, is probably the best of the three. It achieves
  5055. separation of concerns, and doesn't misuse memory or CPU cycles, but
  5056. it is still inefficient in that both the
  5057. <literal>AccessDecisionVoter</literal> and the eventual business
  5058. method itself will perform a call to the DAO responsible for
  5059. retrieving the <literal>Customer</literal> object. Two accesses per
  5060. method invocation is clearly undesirable. In addition, with every
  5061. approach listed you'll need to write your own access control list
  5062. (ACL) persistence and business logic from scratch.</para>
  5063. <para>Fortunately, there is another alternative, which we'll talk
  5064. about below.</para>
  5065. </section>
  5066. <section id="domain-acls-basic-old">
  5067. <title>Basic ACL Package</title>
  5068. <para>Please note that our Basic ACL services are currently being
  5069. refactored. We expect release 1.1.0 will contain this new code.
  5070. Planned code is already in the Spring Security Subversion sandbox, so
  5071. please check there if you have a new application requiring ACLs or are
  5072. in the planning stages. The Basic ACL services will be deprecated from
  5073. release 1.1.0.</para>
  5074. <para>The <literal>org.springframework.security.acl</literal> package
  5075. is very simple, comprising only a handful of interfaces and a single
  5076. class, as shown in Figure 6. It provides the basic foundation for
  5077. access control list (ACL) lookups.</para>
  5078. <para><mediaobject>
  5079. <imageobject role="html">
  5080. <imagedata align="center" fileref="images/ACLSecurity.gif"
  5081. format="GIF" />
  5082. </imageobject>
  5083. <caption>
  5084. <para>Figure 6: Access Control List Manager</para>
  5085. </caption>
  5086. </mediaobject></para>
  5087. <para>The central interface is <literal>AclManager</literal>, which is
  5088. defined by two methods:</para>
  5089. <para><programlisting>public AclEntry[] getAcls(java.lang.Object domainInstance);
  5090. public AclEntry[] getAcls(java.lang.Object domainInstance, Authentication authentication);</programlisting></para>
  5091. <para><literal>AclManager</literal> is intended to be used as a
  5092. collaborator against your business objects, or, more desirably,
  5093. <literal>AccessDecisionVoter</literal>s. This means you use Spring's
  5094. normal <literal>ApplicationContext</literal> features to wire up your
  5095. <literal>AccessDecisionVoter</literal> (or business method) with an
  5096. <literal>AclManager</literal>. Consideration was given to placing the
  5097. ACL information in the <literal>ContextHolder</literal>, but it was
  5098. felt this would be inefficient both in terms of memory usage as well
  5099. as the time spent loading potentially unused ACL information. The
  5100. trade-off of needing to wire up a collaborator for those objects
  5101. requiring ACL information is rather minor, particularly in a
  5102. Spring-managed application.</para>
  5103. <para>The first method of the <literal>AclManager</literal> will
  5104. return all ACLs applying to the domain object instance passed to it.
  5105. The second method does the same, but only returns those ACLs which
  5106. apply to the passed <literal>Authentication</literal> object.</para>
  5107. <para>The <literal>AclEntry</literal> interface returned by
  5108. <literal>AclManager</literal> is merely a marker interface. You will
  5109. need to provide an implementation that reflects that ACL permissions
  5110. for your application.</para>
  5111. <para>Rounding out the
  5112. <literal>org.springframework.security.acl</literal> package is an
  5113. <literal>AclProviderManager</literal> class, with a corresponding
  5114. <literal>AclProvider</literal> interface.
  5115. <literal>AclProviderManager</literal> is a concrete implementation of
  5116. <literal>AclManager</literal>, which iterates through registered
  5117. <literal>AclProvider</literal>s. The first
  5118. <literal>AclProvider</literal> that indicates it can authoritatively
  5119. provide ACL information for the presented domain object instance will
  5120. be used. This is very similar to the
  5121. <literal>AuthenticationProvider</literal> interface used for
  5122. authentication.</para>
  5123. <para>With this background, let's now look at a usable ACL
  5124. implementation.</para>
  5125. <para>Spring Security includes a production-quality ACL provider
  5126. implementation, which is shown in Figure 7.</para>
  5127. <para><mediaobject>
  5128. <imageobject role="html">
  5129. <imagedata align="center" fileref="images/BasicAclProvider.gif"
  5130. format="GIF" />
  5131. </imageobject>
  5132. <caption>
  5133. <para>Figure 7: Basic ACL Manager</para>
  5134. </caption>
  5135. </mediaobject></para>
  5136. <para>The implementation is based on integer masking, which is
  5137. commonly used for ACL permissions given its flexibility and speed.
  5138. Anyone who has used Unix's <literal>chmod</literal> command will know
  5139. all about this type of permission masking (eg <literal>chmod
  5140. 777</literal>). You'll find the classes and interfaces for the integer
  5141. masking ACL package under
  5142. <literal>org.springframework.security.acl.basic</literal>.</para>
  5143. <para>Extending the <literal>AclEntry</literal> interface is a
  5144. <literal>BasicAclEntry</literal> interface, with the main methods
  5145. shown below:</para>
  5146. <para><programlisting>public AclObjectIdentity getAclObjectIdentity();
  5147. public AclObjectIdentity getAclObjectParentIdentity();
  5148. public int getMask();
  5149. public java.lang.Object getRecipient();</programlisting></para>
  5150. <para>As shown, each <literal>BasicAclEntry</literal> has four main
  5151. properties. The <literal>mask</literal> is the integer that represents
  5152. the permissions granted to the <literal>recipient</literal>. The
  5153. <literal>aclObjectIdentity</literal> is able to identify the domain
  5154. object instance for which the ACL applies, and the
  5155. <literal>aclObjectParentIdentity</literal> optionally specifies the
  5156. parent of the domain object instance. Multiple
  5157. <literal>BasicAclEntry</literal>s usually exist against a single
  5158. domain object instance, and as suggested by the parent identity
  5159. property, permissions granted higher in the object hierarchy will
  5160. trickle down and be inherited (unless blocked by integer zero).</para>
  5161. <para><literal>BasicAclEntry</literal> implementations typically
  5162. provide convenience methods, such as
  5163. <literal>isReadAllowed()</literal>, to avoid application classes
  5164. needing to perform bit masking themselves. The
  5165. <literal>SimpleAclEntry</literal> and
  5166. <literal>AbstractBasicAclEntry</literal> demonstrate and provide much
  5167. of this bit masking logic.</para>
  5168. <para>The <literal>AclObjectIdentity</literal> itself is merely a
  5169. marker interface, so you need to provide implementations for your
  5170. domain objects. However, the package does include a
  5171. <literal>NamedEntityObjectIdentity</literal> implementation which will
  5172. suit many needs. The <literal>NamedEntityObjectIdentity</literal>
  5173. identifies a given domain object instance by the classname of the
  5174. instance and the identity of the instance. A
  5175. <literal>NamedEntityObjectIdentity</literal> can be constructed
  5176. manually (by calling the constructor and providing the classname and
  5177. identity <literal>String</literal>s), or by passing in any domain
  5178. object that contains a <literal>getId()</literal> method.</para>
  5179. <para>The actual <literal>AclProvider</literal> implementation is
  5180. named <literal>BasicAclProvider</literal>. It has adopted a similar
  5181. design to that used by the authentication-related
  5182. <literal>DaoAuthenticationProvder</literal>. Specifically, you define
  5183. a <literal>BasicAclDao</literal> against the provider, so different
  5184. ACL repository types can be accessed in a pluggable manner. The
  5185. <literal>BasicAclProvider</literal> also supports pluggable cache
  5186. providers (with Spring Security including an implementation that
  5187. fronts EH-CACHE).</para>
  5188. <para>The <literal>BasicAclDao</literal> interface is very simple to
  5189. implement:</para>
  5190. <para><programlisting>public BasicAclEntry[] getAcls(AclObjectIdentity aclObjectIdentity);</programlisting></para>
  5191. <para>A <literal>BasicAclDao</literal> implementation needs to
  5192. understand the presented <literal>AclObjectIdentity</literal> and how
  5193. it maps to a storage repository, find the relevant records, and create
  5194. appropriate <literal>BasicAclEntry</literal> objects and return
  5195. them.</para>
  5196. <para>Spring Security includes a single <literal>BasicAclDao</literal>
  5197. implementation called <literal>JdbcDaoImpl</literal>. As implied by
  5198. the name, <literal>JdbcDaoImpl</literal> accesses ACL information from
  5199. a JDBC database. There is also an extended version of this DAO,
  5200. <literal>JdbcExtendedDaoImpl</literal>, which provides CRUD operations
  5201. on the JDBC database, although we won't discuss these features here.
  5202. The default database schema and some sample data will aid in
  5203. understanding its function:</para>
  5204. <para><programlisting>CREATE TABLE acl_object_identity (
  5205. id IDENTITY NOT NULL,
  5206. object_identity VARCHAR_IGNORECASE(250) NOT NULL,
  5207. parent_object INTEGER,
  5208. acl_class VARCHAR_IGNORECASE(250) NOT NULL,
  5209. CONSTRAINT unique_object_identity UNIQUE(object_identity),
  5210. FOREIGN KEY (parent_object) REFERENCES acl_object_identity(id)
  5211. );
  5212. CREATE TABLE acl_permission (
  5213. id IDENTITY NOT NULL,
  5214. acl_object_identity INTEGER NOT NULL,
  5215. recipient VARCHAR_IGNORECASE(100) NOT NULL,
  5216. mask INTEGER NOT NULL,
  5217. CONSTRAINT unique_recipient UNIQUE(acl_object_identity, recipient),
  5218. FOREIGN KEY (acl_object_identity) REFERENCES acl_object_identity(id)
  5219. );
  5220. INSERT INTO acl_object_identity VALUES (1, 'corp.DomainObject:1', null,
  5221. 'org.springframework.security.acl.basic.SimpleAclEntry');
  5222. INSERT INTO acl_object_identity VALUES (2, 'corp.DomainObject:2', 1,
  5223. 'org.springframework.security.acl.basic.SimpleAclEntry');
  5224. INSERT INTO acl_object_identity VALUES (3, 'corp.DomainObject:3', 1,
  5225. 'org.springframework.security.acl.basic.SimpleAclEntry');
  5226. INSERT INTO acl_object_identity VALUES (4, 'corp.DomainObject:4', 1,
  5227. 'org.springframework.security.acl.basic.SimpleAclEntry');
  5228. INSERT INTO acl_object_identity VALUES (5, 'corp.DomainObject:5', 3,
  5229. 'org.springframework.security.acl.basic.SimpleAclEntry');
  5230. INSERT INTO acl_object_identity VALUES (6, 'corp.DomainObject:6', 3,
  5231. 'org.springframework.security.acl.basic.SimpleAclEntry');
  5232. INSERT INTO acl_permission VALUES (null, 1, 'ROLE_SUPERVISOR', 1);
  5233. INSERT INTO acl_permission VALUES (null, 2, 'ROLE_SUPERVISOR', 0);
  5234. INSERT INTO acl_permission VALUES (null, 2, 'rod', 2);
  5235. INSERT INTO acl_permission VALUES (null, 3, 'scott', 14);
  5236. INSERT INTO acl_permission VALUES (null, 6, 'scott', 1);</programlisting></para>
  5237. <para>As can be seen, database-specific constraints are used
  5238. extensively to ensure the integrity of the ACL information. If you
  5239. need to use a different database (Hypersonic SQL statements are shown
  5240. above), you should try to implement equivalent constraints. The
  5241. equivalent Oracle configuration is:</para>
  5242. <para><programlisting>CREATE TABLE ACL_OBJECT_IDENTITY (
  5243. ID number(19,0) not null,
  5244. OBJECT_IDENTITY varchar2(255) NOT NULL,
  5245. PARENT_OBJECT number(19,0),
  5246. ACL_CLASS varchar2(255) NOT NULL,
  5247. primary key (ID)
  5248. );
  5249. ALTER TABLE ACL_OBJECT_IDENTITY ADD CONTRAINT FK_PARENT_OBJECT foreign key (ID) references ACL_OBJECT_IDENTITY
  5250. CREATE SEQUENCE ACL_OBJECT_IDENTITY_SEQ;
  5251. CREATE OR REPLACE TRIGGER ACL_OBJECT_IDENTITY_ID
  5252. BEFORE INSERT ON ACL_OBJECT_IDENTITY
  5253. FOR EACH ROW
  5254. BEGIN
  5255. SELECT ACL_OBJECT_IDENTITY_SEQ.NEXTVAL INTO :new.id FROM dual;
  5256. END;
  5257. CREATE TABLE ACL_PERMISSION (
  5258. ID number(19,0) not null,
  5259. ACL_OBJECT_IDENTITY number(19,0) NOT NULL,
  5260. RECIPIENT varchar2(255) NOT NULL,
  5261. MASK number(19,0) NOT NULL,
  5262. primary key (ID)
  5263. );
  5264. ALTER TABLE ACL_PERMISSION ADD CONTRAINT UNIQUE_ID_RECIPIENT unique (acl_object_identity, recipient);
  5265. CREATE SEQUENCE ACL_PERMISSION_SEQ;
  5266. CREATE OR REPLACE TRIGGER ACL_PERMISSION_ID
  5267. BEFORE INSERT ON ACL_PERMISSION
  5268. FOR EACH ROW
  5269. BEGIN
  5270. SELECT ACL_PERMISSION_SEQ.NEXTVAL INTO :new.id FROM dual;
  5271. END;
  5272. &lt;bean id="basicAclExtendedDao" class="org.springframework.security.acl.basic.jdbc.JdbcExtendedDaoImpl"&gt;
  5273. &lt;property name="dataSource"&gt;
  5274. &lt;ref bean="dataSource"/&gt;
  5275. &lt;/property&gt;
  5276. &lt;property name="objectPropertiesQuery" value="${acegi.objectPropertiesQuery}"/&gt;
  5277. &lt;/bean&gt;
  5278. &lt;prop key="acegi.objectPropertiesQuery"&gt;SELECT CHILD.ID, CHILD.OBJECT_IDENTITY, CHILD.ACL_CLASS, PARENT.OBJECT_IDENTITY as PARENT_OBJECT_IDENTITY FROM acl_object_identity as CHILD LEFT OUTER JOIN acl_object_identity as PARENT ON CHILD.parent_object=PARENT.id WHERE CHILD.object_identity = ?&lt;/prop&gt; </programlisting></para>
  5279. <para>The <literal>JdbcDaoImpl</literal> will only respond to requests
  5280. for <literal>NamedEntityObjectIdentity</literal>s. It converts such
  5281. identities into a single <literal>String</literal>, comprising
  5282. the<literal> NamedEntityObjectIdentity.getClassname()</literal> +
  5283. <literal>":"</literal> +
  5284. <literal>NamedEntityObjectIdentity.getId()</literal>. This yields the
  5285. type of <literal>object_identity</literal> values shown above. As
  5286. indicated by the sample data, each database row corresponds to a
  5287. single <literal>BasicAclEntry</literal>. As stated earlier and
  5288. demonstrated by <literal>corp.DomainObject:2</literal> in the above
  5289. sample data, each domain object instance will often have multiple
  5290. <literal>BasicAclEntry</literal>[]s.</para>
  5291. <para>As <literal>JdbcDaoImpl</literal> is required to return concrete
  5292. <literal>BasicAclEntry</literal> classes, it needs to know which
  5293. <literal>BasicAclEntry</literal> implementation it is to create and
  5294. populate. This is the role of the <literal>acl_class</literal> column.
  5295. <literal>JdbcDaoImpl</literal> will create the indicated class and set
  5296. its <literal>mask</literal>, <literal>recipient</literal>,
  5297. <literal>aclObjectIdentity</literal> and
  5298. <literal>aclObjectParentIdentity</literal> properties.</para>
  5299. <para>As you can probably tell from the sample data, the
  5300. <literal>parent_object_identity</literal> value can either be null or
  5301. in the same format as the <literal>object_identity</literal>. If
  5302. non-null, <literal>JdbcDaoImpl</literal> will create a
  5303. <literal>NamedEntityObjectIdentity</literal> to place inside the
  5304. returned <literal>BasicAclEntry</literal> class.</para>
  5305. <para>Returning to the <literal>BasicAclProvider</literal>, before it
  5306. can poll the <literal>BasicAclDao</literal> implementation it needs to
  5307. convert the domain object instance it was passed into an
  5308. <literal>AclObjectIdentity</literal>.
  5309. <literal>BasicAclProvider</literal> has a <literal>protected
  5310. AclObjectIdentity obtainIdentity(Object domainInstance)</literal>
  5311. method that is responsible for this. As a protected method, it enables
  5312. subclasses to easily override. The normal implementation checks
  5313. whether the passed domain object instance implements the
  5314. <literal>AclObjectIdentityAware</literal> interface, which is merely a
  5315. getter for an <literal>AclObjectIdentity</literal>. If the domain
  5316. object does implement this interface, that is the identity returned.
  5317. If the domain object does not implement this interface, the method
  5318. will attempt to create an <literal>AclObjectIdentity</literal> by
  5319. passing the domain object instance to the constructor of a class
  5320. defined by the
  5321. <literal>BasicAclProvider.getDefaultAclObjectIdentity()</literal>
  5322. method. By default the defined class is
  5323. <literal>NamedEntityObjectIdentity</literal>, which was described in
  5324. more detail above. Therefore, you will need to either (i) provide a
  5325. <literal>getId()</literal> method on your domain objects, (ii)
  5326. implement <literal>AclObjectIdentityAware</literal> on your domain
  5327. objects, (iii) provide an alternative
  5328. <literal>AclObjectIdentity</literal> implementation that will accept
  5329. your domain object in its constructor, or (iv) override the
  5330. <literal>obtainIdentity(Object)</literal> method.</para>
  5331. <para>Once the <literal>AclObjectIdentity</literal> of the domain
  5332. object instance is determined, the <literal>BasicAclProvider</literal>
  5333. will poll the DAO to obtain its <literal>BasicAclEntry</literal>[]s.
  5334. If any of the entries returned by the DAO indicate there is a parent,
  5335. that parent will be polled, and the process will repeat until there is
  5336. no further parent. The permissions assigned to a
  5337. <literal>recipient</literal> closest to the domain object instance
  5338. will always take priority and override any inherited permissions. From
  5339. the sample data above, the following inherited permissions would
  5340. apply:</para>
  5341. <para><programlisting>--- Mask integer 0 = no permissions
  5342. --- Mask integer 1 = administer
  5343. --- Mask integer 2 = read
  5344. --- Mask integer 6 = read and write permissions
  5345. --- Mask integer 14 = read and write and create permissions
  5346. ---------------------------------------------------------------------
  5347. --- *** INHERITED RIGHTS FOR DIFFERENT INSTANCES AND RECIPIENTS ***
  5348. --- INSTANCE RECIPIENT PERMISSION(S) (COMMENT #INSTANCE)
  5349. ---------------------------------------------------------------------
  5350. --- 1 ROLE_SUPERVISOR Administer
  5351. --- 2 ROLE_SUPERVISOR None (overrides parent #1)
  5352. --- rod Read
  5353. --- 3 ROLE_SUPERVISOR Administer (from parent #1)
  5354. --- scott Read, Write, Create
  5355. --- 4 ROLE_SUPERVISOR Administer (from parent #1)
  5356. --- 5 ROLE_SUPERVISOR Administer (from parent #3)
  5357. --- scott Read, Write, Create (from parent #3)
  5358. --- 6 ROLE_SUPERVISOR Administer (from parent #3)
  5359. --- scott Administer (overrides parent #3)</programlisting></para>
  5360. <para>So the above explains how a domain object instance has its
  5361. <literal>AclObjectIdentity</literal> discovered, and the
  5362. <literal>BasicAclDao</literal> will be polled successively until an
  5363. array of inherited permissions is constructed for the domain object
  5364. instance. The final step is to determine the
  5365. <literal>BasicAclEntry</literal>[]s that are actually applicable to a
  5366. given <literal>Authentication</literal> object.</para>
  5367. <para>As you would recall, the <literal>AclManager</literal> (and all
  5368. delegates, up to and including <literal>BasicAclProvider</literal>)
  5369. provides a method which returns only those
  5370. <literal>BasicAclEntry</literal>[]s applying to a passed
  5371. <literal>Authentication</literal> object.
  5372. <literal>BasicAclProvider</literal> delivers this functionality by
  5373. delegating the filtering operation to an
  5374. <literal>EffectiveAclsResolver</literal> implementation. The default
  5375. implementation,
  5376. <literal>GrantedAuthorityEffectiveAclsResolver</literal>, will iterate
  5377. through the <literal>BasicAclEntry</literal>[]s and include only those
  5378. where the <literal>recipient</literal> is equal to either the
  5379. <literal>Authentication</literal>'s <literal>principal</literal> or
  5380. any of the <literal>Authentication</literal>'s
  5381. <literal>GrantedAuthority</literal>[]s. Please refer to the JavaDocs
  5382. for more information.</para>
  5383. <mediaobject>
  5384. <imageobject role="html">
  5385. <imagedata align="center" fileref="images/Permissions.gif"
  5386. format="GIF" />
  5387. </imageobject>
  5388. <caption>
  5389. <para>Figure 8: ACL Instantiation Approach</para>
  5390. </caption>
  5391. </mediaobject>
  5392. <para>The above figure explains the key relationships between objects
  5393. in the Basic ACL package.</para>
  5394. </section>
  5395. </chapter>
  5396. </part>
  5397. <part id="resources">
  5398. <title>Other Resources</title>
  5399. <partintro>
  5400. <para>In addition to this reference guide, a number of other resources
  5401. exist to help you learn how to use Spring Security. These resources are
  5402. discussed in this section.</para>
  5403. </partintro>
  5404. <chapter id="sample-apps">
  5405. <title id="samples">Sample Applications</title>
  5406. <sect1 id="contacts-sample">
  5407. <title id="contacts">Contacts</title>
  5408. <para>Included with Spring Security is a very simple application that
  5409. can demonstrate the basic security facilities provided by the system
  5410. (and confirm your Container Adapter is properly configured if you're
  5411. using one).</para>
  5412. <para>If you build from Subversion, the Contacts sample application
  5413. includes three deployable versions:
  5414. <literal>spring-security-sample-contacts-filter.war</literal> is
  5415. configured with the HTTP Session Authentication approach.
  5416. <literal>spring-security-sample-contacts-ca.war</literal> is
  5417. configured to use a Container Adapter. Finally,
  5418. <literal>spring-security-sample-contacts-cas.war</literal> is designed
  5419. to work with a JA-SIG CAS server. If you're just wanting to see how
  5420. the sample application works, please use
  5421. <literal><literal>spring-security-sample-contacts-filter.war</literal></literal>
  5422. as it does not require special configuration of your container. This
  5423. is also the artifact included in official release ZIPs.</para>
  5424. <para>To deploy, simply copy the relevant WAR file from Spring
  5425. Security distribution into your container’s <literal>webapps</literal>
  5426. directory.</para>
  5427. <para>After starting your container, check the application can load.
  5428. Visit
  5429. <literal>http://localhost:8080/spring-security-sample-contacts-filter</literal>
  5430. (or whichever URL is appropriate for your web container and the WAR
  5431. you deployed). A random contact should be displayed. Click "Refresh"
  5432. several times and you will see different contacts. The business method
  5433. that provides this random contact is not secured.</para>
  5434. <para>Next, click "Debug". You will be prompted to authenticate, and a
  5435. series of usernames and passwords are suggested on that page. Simply
  5436. authenticate with any of these and view the resulting page. It should
  5437. contain a success message similar to the following:</para>
  5438. <blockquote>
  5439. <para>Context on SecurityContextHolder is of type:
  5440. org.springframework.security.context.SecurityContextImpl</para>
  5441. <para>The Context implements SecurityContext.</para>
  5442. <para>Authentication object is of type:
  5443. org.springframework.security.adapters.PrincipalSpringSecurityUserToken</para>
  5444. <para>Authentication object as a String:
  5445. org.springframework.security.adapters.PrincipalSpringSecurityUserToken@e9a7c2:
  5446. Username: rod; Password: [PROTECTED]; Authenticated: true; Granted
  5447. Authorities: ROLE_TELLER, ROLE_SUPERVISOR</para>
  5448. <para>Authentication object holds the following granted
  5449. authorities:</para>
  5450. <para>ROLE_TELLER (getAuthority(): ROLE_TELLER)</para>
  5451. <para>ROLE_SUPERVISOR (getAuthority(): ROLE_SUPERVISOR)</para>
  5452. <para>SUCCESS! Your [container adapter|web filter] appears to be
  5453. properly configured!</para>
  5454. </blockquote>
  5455. <para>If you receive a different message, and deployed
  5456. <literal>spring-security-sample-contacts-ca.war</literal>, check you
  5457. have properly configured your Container Adapter as described elsewhere
  5458. in this reference guide.</para>
  5459. <para>Once you successfully receive the above message, return to the
  5460. sample application's home page and click "Manage". You can then try
  5461. out the application. Notice that only the contacts available to the
  5462. currently logged on user are displayed, and only users with
  5463. <literal>ROLE_SUPERVISOR</literal> are granted access to delete their
  5464. contacts. Behind the scenes, the
  5465. <literal>MethodSecurityInterceptor</literal> is securing the business
  5466. objects. If you're using or
  5467. <literal>spring-security-sample-contacts-cas.war</literal>, the
  5468. <literal><literal>spring-security-sample-contacts-filter.war</literal></literal>
  5469. <literal>FilterSecurityInterceptor</literal> is also securing the HTTP
  5470. requests. If using either of these WARs, be sure to try visiting
  5471. <literal>http://localhost:8080/contacts/secure/super</literal>, which
  5472. will demonstrate access being denied by the
  5473. <literal>FilterSecurityInterceptor</literal>. Note the sample
  5474. application enables you to modify the access control lists associated
  5475. with different contacts. Be sure to give this a try and understand how
  5476. it works by reviewing the sample application's application context XML
  5477. files.</para>
  5478. <para>The Contacts sample application also include a
  5479. <literal>client</literal> directory. Inside you will find a small
  5480. application that queries the backend business objects using several
  5481. web services protocols. This demonstrates how to use Spring Security
  5482. for authentication with Spring remoting protocols. To try this client,
  5483. ensure your servlet container is still running the Contacts sample
  5484. application, and then execute <literal>client rod koala</literal>. The
  5485. command-line parameters respectively represent the username to use,
  5486. and the password to use. Note that you may need to edit
  5487. <literal>client.properties</literal> to use a different target
  5488. URL.</para>
  5489. <para>Please note the sample application's <literal>client</literal>
  5490. does not currently support CAS. You can still give it a try, though,
  5491. if you're ambitious: try <literal>client _cas_stateless_
  5492. YOUR-SERVICE-TICKET-ID</literal>.</para>
  5493. </sect1>
  5494. <sect1 id="tutorial-sample">
  5495. <title>Tutorial Sample</title>
  5496. <para>Whilst the <link linkend="contacts-sample">Contacts
  5497. Sample</link> is quite advanced in that it illustrates the more
  5498. powerful features of domain object access control lists and so on,
  5499. sometimes you just want to start with a nice basic example. The
  5500. tutorial sample is intended to provide this for you.</para>
  5501. <para>The compiled tutorial is included in the distribution ZIP file,
  5502. ready to be deployed into your web container. Authentication is
  5503. handled by the <link
  5504. linkend="dao-provider">DaoAuthenticationProvider</link>, using the
  5505. <link linkend="in-memory-service">in-memory</link>
  5506. <literal>UserDetailsService</literal> that sources information from
  5507. the <literal>users.properties</literal> file located in the WAR's
  5508. <literal>/WEB-INF</literal> directory. The <link
  5509. linkend="form">form-based</link> authentication mechanism is used,
  5510. with the commonly-used <link linkend="remember-me">remember-me</link>
  5511. authentication provider used to automatically remember the login using
  5512. cookies.</para>
  5513. <para>In terms of authorization, to keep things simple we've
  5514. configured the tutorial to only perform some basic <link
  5515. linkend="filter-invocation-authorization">web filter
  5516. authorization</link>. We've wired two common <link
  5517. linkend="pre-invocation">pre-invocation access decision voters</link>,
  5518. being the <literal>RoleVoter</literal> and
  5519. <literal>AuthenticatedVoter</literal>, such that
  5520. <literal>ROLE_*</literal> configuration attributes and
  5521. <literal>IS_AUTHENTICATED_*</literal> configuration attributes may be
  5522. used. Of course, it's extremely easy to add in other providers, with
  5523. most users probably starting with some services-layer security using
  5524. <link linkend="aop-alliance">MethodSecurityInterceptor</link>.</para>
  5525. <para>We recommend you start with the tutorial sample, as the XML is
  5526. minimal and easy to follow. All of the needed <link
  5527. linkend="filters">filters</link> are configured properly, and using
  5528. best practise. Most importantly, you can easily this one XML file (and
  5529. its corresponding <literal>web.xml</literal> entries) to your existing
  5530. application. Only when this basic integration is achieved do we
  5531. suggest you attempt adding in method authorization or domain object
  5532. security.</para>
  5533. </sect1>
  5534. </chapter>
  5535. <chapter id="community">
  5536. <title>Community Support</title>
  5537. <sect1 id="jira">
  5538. <title>Use JIRA for Issue Tracking</title>
  5539. <para>Spring Security uses JIRA to manage bug reports and enhancement
  5540. requests. If you find a bug, please log a report using JIRA. Do not
  5541. log it on the support forum, mailing list or by emailing the project's
  5542. developers. Such approaches are ad-hoc and we prefer to manage bugs
  5543. using a more formal process.</para>
  5544. <para>If possible, in your JIRA report please provide a JUnit test
  5545. that demonstrates any incorrect behaviour. Or, better yet, provide a
  5546. patch that corrects the issue. Similarly, enhancements are welcome to
  5547. be logged in JIRA, although we only accept commit enhancement requests
  5548. if you include corresponding unit tests. This is necessary to ensure
  5549. project test coverage is adequately maintained.</para>
  5550. <para>You can access JIRA at <ulink
  5551. url="http://opensource.atlassian.com/projects/spring/secure/BrowseProject.jspa?id=10040"></ulink>.</para>
  5552. </sect1>
  5553. <sect1 id="becoming-involved">
  5554. <title>Becoming Involved</title>
  5555. <para>We welcome you to become involved in Spring Security project.
  5556. There are many ways of contributing, including reading the mailing
  5557. list and responding to questions from other people, writing new code,
  5558. improving existing code, assisting with documentation, developing
  5559. samples or tutorials, or simply making suggestions.</para>
  5560. <para>Please read our project policies web page that is available on
  5561. Spring Security home page. This explains the path to become a
  5562. committer, and the administration approaches we use within the
  5563. project.</para>
  5564. </sect1>
  5565. <sect1 id="further-info">
  5566. <title>Further Information</title>
  5567. <para>Questions and comments on Spring Security are welcome. Please
  5568. use the Spring Community Forum web site at <ulink
  5569. url="http://forum.springframework.org"></ulink> for all support
  5570. issues. Remember to use JIRA for bug reports, as explained above.
  5571. Everyone is also welcome to join the Acegisecurity-developer mailing
  5572. list and participate in design discussions. It's also a good way of
  5573. finding out what's happening with regard to release timing, and the
  5574. traffic volume is quite light. Finally, our project home page (where
  5575. you can obtain the latest release of the project and convenient links
  5576. to Subversion, JIRA, mailing lists, forums etc) is at <ulink
  5577. url="http://acegisecurity.org"></ulink>.</para>
  5578. </sect1>
  5579. </chapter>
  5580. </part>
  5581. </book>