Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 1
J2EE Security ModelDan JohnssonOmegapoint AB / Frobozz AB; [email protected] / [email protected]
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 2
Silly Example - BarBehind Counter
GentsLadies
Who’s there?Women
Men
Personnel
Security Guards
Bar
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 3
Bar ActivitiesMove around
Bar areaBehind counterLadiesGentsHome
Buy DrinksTake money from cash register
Who may do what?
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 4
The StoryUse of Enterprise System
app/web EJB
m RRRm RRRm RRR
ejb-jar.xml
User DB
id RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 5
J2EEPlatform for enterprise systemsWhy do we need security model
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 6
Enterprise SystemsInformation system
Information = data about somethingManage data• Oppose: games, FEM-calculations
Producers and consumersConsistency of dataEnterprise Logic = rules on dataSystem is Model of Reality
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 7
Large Scale Distributed Enterprise Systems
Large ScaleLots of usersLots of kinds of usersLots of functionalityLots of kinds of use per user
DistributedNo control of clients
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 8
Security ChallengesDifferent access to functionality
Event within same componente.g. register sale - sale statisticsNeed authorisation system
Functional components exposedRisk for malicious clientsNeed authentication
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 9
What Is in a Platform?
newfree
C++Services provided by runtime environmente.g.: memory management
C++: keep track of your object lest memory will leak• Learn strategies (object ownership etc)• Repetitive coding
Java: Garbage Collect
Like it or leave it Garbagecollection
Java
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 10
J2EE Platform Services (a few)Web tier: session tracking
• HttpRequest.getSession()
EJB tier: persistence service• EJB CMP
Across all tiersStandard Transaction ModelStandard Security Model
All services: use or leave
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 11
Sound Use of Services1 - Use (Standard Model)
Configure• majority of cases
2 - AugmentBuild code on top• some cases
3 - DiscardBuild your own system• very unususal
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 12
The Cube - TiersSplit system functionality
ClientPresentationEnterprise/Business LogicIntegrationResource
CLIENT
PRESEN
LOGIC
INTEGR
RES
11000110001100110010101
OOA
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 13
The Cube - LayersLayers of abstraction
Application
Virtual Platform
Operational Environment
Operating System
FunctionalityBuy - platformWrite - application
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 14
The Cube - CapabilitiesEmergent properties
PerformanceAvailabilitySecurityExtensibility
Not located in single componentDiscussing architecture - must consider entire system
capabilities
layers
tiers
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 15
BarDweller - EJB SessionSession EJBs encapsulate enterprise flow
public interface BarDweller extends EJBObject {
public void buyDrink() throws RemoteException;
public void takeMoney() throws RemoteException;
public void goBar() throws RemoteException;
public void goBehindCounter() throws RemoteException;
public void goLadies() throws RemoteException;
public void goGents() throws RemoteException;
public void goHome() throws RemoteException;}
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 16
Security Threats (Examples)CrackersDenial of ServiceBurglaryBlackmailingInside jobs
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 17
Two Sides of SecurityNegative Security
What people must not be able to doRisk: crackers
Positive SecurityWhat people must be able to doRisk: denial of service
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 18
Security PolicyLine between positive and negativeWho is allowed to do what?Metric for measuring security
Can make automated tests
Remember: System is Model of Reality
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 19
Bar Security RulesOnly personnel/guards behind the counterOnly women in the ladies (except guards)
Personnel in ladies must be women
Only men in the gents (except guards)Personnel in gents must be men
Only personnel may handle moneyNo drinking by personnel and guards
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 20
BarDweller - Securitypublic void buyDrink()
all men and women, but neither guards nor personnel
public void takeMoney()personnel
public void goBar()everybody
public void goBehindCounter()personnel and guards
public void goLadies()women and guards
public void goGents()men and guards
public void goHome()everybody
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 21
Standard Security Model -Ambition
Ambition: nice general levelConsiderations
Transparent for componentsDeclarative configurationExtensible - possible to augment• Programmatic support
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 22
Standard Security Model -Design Fundamentals
Method based access controlJ2EE recommends Service Oriented Architectures • functionality grouped by themes
SOA demands method granularity• Functionality for mixed clients in one component• Component based access control - would not work
Role basedSuffice for lots of applicationsStill simple
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 23
Pipe Metaphor
authentication authorisation resource access
m RRRm RRRm RRR
ejb-jar.xml
app/web EJB
User DB
id RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 24
AuthenticationEstablish identityAs close as possible to clientClient container
Application containerWeb container
Transparent to code/web-appClient container holds identity
Pass in call to EJB-methods
app/web
ID?
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 25
User DatabaseKeeps the user information
principal / credentials
Operating environment, not covered by specRigged by deployer / sysadmin
Used by client container to verify identityTechnology
Relational DatabaseLDAP Directory (preferred)
User DB
id RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 26
Application clients (J2EE [1.3] 9.2)
Interact with user through JAASjavax.security.auth.callback.CallbackHandler
Configurable in deployment descriptorFlexible: Some possible authenticators
Pop-up windowOperating SystemBiometric deviceSmart Card
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 27
To Make It Work - GUI ClientMETA-INF/application-client.xml<application-client>
<callback-handler>bar.auth.RetinaScanCallbackHandler
</callback-handler> </application-client>
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 28
Web ClientsWeb Container asks for proof of identity
BASIC, (DIGEST), FORM, CLIENT-CERT
Identity stored in container (e.g. session)Identity passed to EJB on callFixed identity: run-as (deploy setting)
Web container uses same ID
Servlet [2.3] 12.5 (Security/Authentication)
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 29
To Make It Work - Web Loginweb-inf/web.xml<web-app>
<security-constraint>…</security-constraint> <login-config>
<auth-method>BASIC</auth-method> </login-config>
</web-app>
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 30
BASIC AuthenticationHTTP Authentication (RFC 2617)Username / Password Headers
HTTP GET
401 Unauthorizedusername/password?Pop-Up
HTTP GET + Headers
User DBid RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 31
Evaluation of BASICAdvantages
SimpleDrawbacks
Credentials in plain text• HTTPS - all pages
strain on web server
Art Director• That pop-up looks ugly!
Browser enforce security• Or so it seems to user
Browser keeps credentials• Bad for public terminals• No “clear credentials”
button
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 32
FORM-based AuthenticationChallenge - ResponseChallenge = login form
j_username, j_password, j_security_check HTTP GET
redirect to formusername/password?
User DBid RRRid RRRid RRR
id credid credid cred
<form …>
HTTP POST
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 33
Evaluation of FORMAdvantages
Control over Look-and-Feel of login formCan secure just login
• Redirect to HTTPS-URL
DrawbacksHard to add extra info to login form
• e.g. “login failed”
Credentials saved by some browsers
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 34
CLIENT-CERT AuthenticationClient present certificate w public keyServer open SSL-tunnelData encryption not really authentication
challenge-response auth during handshake
Certificate
Challenge / Response
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 35
Evaluation of CLIENT-CERTAdvantages
Very secureDrawbacks
Demands PKI• Cumbersome admin
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 36
The Story This Far
m RRRm RRRm RRR
ejb-jar.xml
EJB
User DB
id RRRid RRRid RRR
id credid credid cred
app/webID
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 37
Call to EJBIdentity passed in call
Packed in network package• EJB [2.0] 19.8.2 Securing EJB invocations
app/web EJBID
ID
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 38
AuthorisationBy EJB containerTransparentFetch ID from callFetch roles from user databaseFetch permitted roles from EJB DDRole resolution
app/web EJBID
m RRRm RRRm RRR
ejb-jar.xml
User DB
id RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 39
Role ResolutionAutomatic by the platformProgrammatic
EJBContext.isCallerInRoleEJBContext.getCallerPrincipal
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 40
To Make It Work - RolesApplication
Define application rolesAssign access permissions
ejb-jar.xml<assembly-descriptor>
<security-role>…</security-role><security-role>…</security-role><method-permission>
<role-name>…</role-name><method>…</method><method>…</method>
</method-permission></assembly-descriptor>
Operating EnvironmentMap principals to application roles
Managed through app-server tool
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 41
BarDweller - Securitypublic void buyDrink()
all men and women, but neither guards nor personnel
public void takeMoney()personnel
public void goBar()everybody
public void goBehindCounter()personnel and guards
public void goLadies()women and guards
public void goGents()men and guards
public void goHome()everybody
OK
Hmm, trickyLet’s ignore
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 42
To Make It Work - ejb-jar.xmlSecurity Roles<security-role>
<description>male or …
</description><role-name>man</role-name>
</security-role><security-role>
<role-name>guard</role-name></security-role><security-role>
<role-name>woman</role-name></security-role><security-role>
<role-name>personnel</role-name></security-role>
Method permissions<method-permission>
<role-name>woman
</role-name><method><ejb-name>BarDwellerEJBean
</ejb-name><method-intf>Remote</method-intf><method-name>
buyDrink</method-name><method-params />
</method><method>
… goLadies</method>
</method-permission>
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 43
The Story This Far
app/web EJB
m RRRm RRRm RRR
ejb-jar.xml
User DB
id RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 44
Resource ControlContainment
Limits access to resource
ExposureGives controlled access to resource
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 45
Example: Log DatabaseProblem
Database w/ complex table relationsDo not want access code throughout system
SolutionDatabase hidden behind EJBEJB configured with credentialsDatabase inaccessible “from side”
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 46
Resource Authentication Requirements (J2EE 1.3 spec)
RequiredConfigured IdentityProgrammatic Authentication
RecommendedCaller ImpersonationPrincipal MappingCredential Mapping
ID?
EJB
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 47
Configured IdentityStandard modelUsername / password
Held by EJBSet by deployerStatic
Code:datasource.getConnection()
ID!
EJB
ID
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 48
Programmatic AuthenticationIf standard model not good enoughCode it in component (app layer)Code:
datasource.getConnection(user, passwd)
Completely general ID!
EJB
ID
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 49
Recommended FeaturesCaller ImpersonationPrincipal/credentials mappingWhy are they recommended?
Handy in some usual cases
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 50
ExampleLegacy system
DatabaseGUI clientsUsers in database
Webbify it!What ID should Web system use?Need to user client’s ID
ID
ID
ID
ID
ID ID?
ID
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 51
Caller ImpersonationUser caller ID to contact resource
danj!
AS
danj
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 52
Principal MappingPrincipal is not always samePrincipal ‘danj’ to databasePrincipal ‘[email protected]’ to Web system
danj!
AS
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 53
Credential MappingNot only different principalsDifferent passwordsDifferent ways of authentication
Certificate to web tierUsername/password to database
Credential mapping translates
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 54
The Story This Far
app/web EJB
m RRRm RRRm RRR
ejb-jar.xml
User DB
id RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 55
Limitations of ModelComplicated role systems
negative permissions
Data-oriented securityBalance of bank account• Not for all “Web-user”s - just for me
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 56
BarDweller - Securitypublic void buyDrink()
all men and women, but neither guards nor personnel
public void takeMoney()personnel
public void goBar()everybody
public void goBehindCounter()personnel and guards
public void goLadies()women and guards
public void goGents()men and guards
public void goHome()everybody
OK
Hmm, tricky
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 57
Augmenting the ModelDo not throw out model
baby / bath water
Code on top of modelpublic void buyDrink() {
if(sessionctx.isCallerInRole("personnel")|| sessionctx.isCallerInRole("guard"))
throw new SecurityException("Not permitted to drink");…
}Note: Seemingly hardcoded ”personnel” and ”guard” are mapped to application roles.
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 58
Data-oriented SecurityExample: Internet bank w/ accountRole based security not enoughAugment model: code on toppublic void getBalance() {
if(! areSame(getName(), ctx.getCallerPrincipal()))throw new SecurityException(”Not your account");
…}
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 59
Recap of Full Scale ModelAuthentication by client containersID transport on call - transparentlyAuthorization by EJB containerProtected resourcestodo: What triggers authentication?todo: User Administration
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 60
Web SystemDegenerated caseNo EJB tier
Who will authorise?
Web container have to - no other around
Protected views
Will trigger authentication!
web
User DB
id RRRid RRRid RRR
id credid credid cred
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 61
To Make It WorkExample web.xml (SRV[2.3] 13.4.2)<security-constraint>
<web-resource-collection><web-resource-name>SalesInfo</web-resource-name><url-pattern>/salesinfo/*</url-pattern><http-method>GET</http-method>
</web-resource-collection><auth-constraint>
<role-name>manager</role-name></auth-constraint><user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee></user-data-constraint>
</security-constraint>
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 62
User AdministrationLarge system ⇒ dynamic user baseBlack Sheep - no standard”This scenario was widely discussed /…/ [JSR-53 EG] but we were unable to achieve consensus on the appropriate solution. We had to abandon this work for J2EE 1.3 ….”
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 63
Drawbacks in User AdminNo User Admin APICannot add usersCannot change passwordCannot change rolesWorkarounds Exist!
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 64
User DatabasesNot standardisedUsual
Flat fileRelational databaseLDAP system
Most app-serversProprietary interfaceAdapters
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 65
User DB Example - TomcatInterfaceAdapters
MemoryRealmJDBCRealmJNDIRealm
Config i server.xml
Tomcat
tomcat-users.xml JDBC LDAP
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 66
Workaround for User AdminUse your LDAP system
good industry support
Update through JNDINo portability guarantee
AS
LDAP
JNDI
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 67
Crystal BallUser admin APIConnectors to auth systems
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 68
Future JSRsJava Authentication Service Provider Interface for Containers (196)Java Authorization Contract for Containers (115)
Colorado Software Summit: October 26 – 31, 2003 © Copyright 2003, Omegapoint AB / Frobozz AB
Dan Johnsson — J2EE Security Model Page 69
ConclusionsStandard model in platformUsable in most casesDeclarative - transparent to codeCan be augmented programmaticallyUser admin is black sheep
Top Related