Source Code Cross Referenced for WebContainerAuthorizer.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » auth » authorize » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Wiki Engine » JSPWiki » com.ecyrd.jspwiki.auth.authorize 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JSPWiki - a JSP-based WikiWiki clone. Copyright (C) 2001-2003 Janne Jalkanen
003:         * (Janne.Jalkanen@iki.fi) This program is free software; you can redistribute
004:         * it and/or modify it under the terms of the GNU Lesser General Public License
005:         * as published by the Free Software Foundation; either version 2.1 of the
006:         * License, or (at your option) any later version. This program is distributed
007:         * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
008:         * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
009:         * See the GNU Lesser General Public License for more details. You should have
010:         * received a copy of the GNU Lesser General Public License along with this
011:         * program; if not, write to the Free Software Foundation, Inc., 59 Temple
012:         * Place, Suite 330, Boston, MA 02111-1307 USA
013:         */
014:        package com.ecyrd.jspwiki.auth.authorize;
015:
016:        import java.io.IOException;
017:        import java.net.URL;
018:        import java.security.Principal;
019:        import java.util.HashSet;
020:        import java.util.Iterator;
021:        import java.util.List;
022:        import java.util.Properties;
023:        import java.util.Set;
024:
025:        import javax.servlet.http.HttpServletRequest;
026:
027:        import org.apache.log4j.Logger;
028:        import org.jdom.Document;
029:        import org.jdom.Element;
030:        import org.jdom.Namespace;
031:        import org.jdom.JDOMException;
032:        import org.jdom.input.SAXBuilder;
033:        import org.jdom.xpath.XPath;
034:        import org.xml.sax.EntityResolver;
035:        import org.xml.sax.InputSource;
036:        import org.xml.sax.SAXException;
037:
038:        import com.ecyrd.jspwiki.InternalWikiException;
039:        import com.ecyrd.jspwiki.WikiEngine;
040:        import com.ecyrd.jspwiki.WikiSession;
041:
042:        /**
043:         * Authorizes users by delegating role membership checks to the servlet
044:         * container. In addition to implementing methods for the
045:         * <code>Authorizer</code> interface, this class also provides a convenience
046:         * method {@link #isContainerAuthorized()} that queries the web application
047:         * descriptor to determine if the container manages authorization.
048:         * @author Andrew Jaquith
049:         * @since 2.3
050:         */
051:        public class WebContainerAuthorizer implements  WebAuthorizer {
052:            private static final String J2EE_SCHEMA_24_NAMESPACE = "http://java.sun.com/xml/ns/j2ee";
053:
054:            protected static final Logger log = Logger
055:                    .getLogger(WebContainerAuthorizer.class);
056:
057:            protected WikiEngine m_engine;
058:
059:            /**
060:             * A lazily-initialized array of Roles that the container knows about. These
061:             * are parsed from JSPWiki's <code>web.xml</code> web application
062:             * deployment descriptor. If this file cannot be read for any reason, the
063:             * role list will be empty. This is a hack designed to get around the fact
064:             * that we have no direct way of querying the web container about which
065:             * roles it manages.
066:             */
067:            protected Role[] m_containerRoles = new Role[0];
068:
069:            /**
070:             * Lazily-initialized boolean flag indicating whether the web container
071:             * protects JSPWiki resources.
072:             */
073:            protected boolean m_containerAuthorized = false;
074:
075:            private Document m_webxml = null;
076:
077:            /**
078:             * Constructs a new instance of the WebContainerAuthorizer class.
079:             */
080:            public WebContainerAuthorizer() {
081:                super ();
082:            }
083:
084:            /**
085:             * Initializes the authorizer for.
086:             * @param engine the current wiki engine
087:             * @param props the wiki engine initialization properties
088:             */
089:            public void initialize(WikiEngine engine, Properties props) {
090:                m_engine = engine;
091:                m_containerAuthorized = false;
092:
093:                // FIXME: Error handling here is not very verbose
094:                try {
095:                    m_webxml = getWebXml();
096:                    if (m_webxml != null) {
097:                        // Add the J2EE 2.4 schema namespace
098:                        m_webxml
099:                                .getRootElement()
100:                                .setNamespace(
101:                                        Namespace
102:                                                .getNamespace(J2EE_SCHEMA_24_NAMESPACE));
103:
104:                        m_containerAuthorized = isConstrained("/Delete.jsp",
105:                                Role.ALL)
106:                                && isConstrained("/Login.jsp", Role.ALL);
107:                    }
108:                    if (m_containerAuthorized) {
109:                        m_containerRoles = getRoles(m_webxml);
110:                        log
111:                                .info("JSPWiki is using container-managed authentication.");
112:                    } else {
113:                        log.info("JSPWiki is using custom authentication.");
114:                    }
115:                } catch (IOException e) {
116:                    log.error("Initialization failed: ", e);
117:                    throw new InternalWikiException(e.getClass().getName()
118:                            + ": " + e.getMessage());
119:                } catch (JDOMException e) {
120:                    log.error("Malformed XML in web.xml", e);
121:                    throw new InternalWikiException(e.getClass().getName()
122:                            + ": " + e.getMessage());
123:                }
124:
125:                if (m_containerRoles.length > 0) {
126:                    String roles = "";
127:                    for (int i = 0; i < m_containerRoles.length; i++) {
128:                        roles = roles + m_containerRoles[i] + " ";
129:                    }
130:                    log
131:                            .info(" JSPWiki determined the web container manages these roles: "
132:                                    + roles);
133:                }
134:                log
135:                        .info("Authorizer WebContainerAuthorizer initialized successfully.");
136:            }
137:
138:            /**
139:             * Determines whether a user associated with an HTTP request possesses
140:             * a particular role. This method simply delegates to 
141:             * {@link javax.servlet.http.HttpServletRequest#isUserInRole(String)}
142:             * by converting the Principal's name to a String.
143:             * @param request the HTTP request
144:             * @param role the role to check
145:             * @return <code>true</code> if the user is considered to be in the role,
146:             *         <code>false</code> otherwise
147:             */
148:            public boolean isUserInRole(HttpServletRequest request,
149:                    Principal role) {
150:                return request.isUserInRole(role.getName());
151:            }
152:
153:            /**
154:             * Determines whether the Subject associated with a WikiSession is in a
155:             * particular role. This method takes two parameters: the WikiSession
156:             * containing the subject and the desired role ( which may be a Role or a
157:             * Group). If either parameter is <code>null</code>, this method must
158:             * return <code>false</code>.
159:             * This method simply examines the WikiSession subject to see if it
160:             * possesses the desired Principal. We assume that the method
161:             * {@link com.ecyrd.jspwiki.auth.AuthenticationManager#login(HttpServletRequest)}
162:             * previously executed at user login time, and that it has injected
163:             * the role Principals that were in force at login time.
164:             * This is definitely a hack,
165:             * but it eliminates the need for WikiSession to keep dangling
166:             * references to the last WikiContext hanging around, just
167:             * so we can look up the HttpServletRequest.
168:             *
169:             * @param session the current WikiSession
170:             * @param role the role to check
171:             * @return <code>true</code> if the user is considered to be in the role,
172:             *         <code>false</code> otherwise
173:             * @see com.ecyrd.jspwiki.auth.Authorizer#isUserInRole(com.ecyrd.jspwiki.WikiSession, java.security.Principal)
174:             */
175:            public boolean isUserInRole(WikiSession session, Principal role) {
176:                if (session == null || role == null) {
177:                    return false;
178:                }
179:                return session.hasPrincipal(role);
180:            }
181:
182:            /**
183:             * Looks up and returns a Role Principal matching a given String. If the
184:             * Role does not match one of the container Roles identified during
185:             * initialization, this method returns <code>null</code>.
186:             * @param role the name of the Role to retrieve
187:             * @return a Role Principal, or <code>null</code>
188:             * @see com.ecyrd.jspwiki.auth.Authorizer#initialize(WikiEngine, Properties)
189:             */
190:            public Principal findRole(String role) {
191:                for (int i = 0; i < m_containerRoles.length; i++) {
192:                    if (m_containerRoles[i].getName().equals(role)) {
193:                        return m_containerRoles[i];
194:                    }
195:                }
196:                return null;
197:            }
198:
199:            /**
200:             * <p>
201:             * Protected method that identifies whether a particular webapp URL is
202:             * constrained to a particular Role. The resource is considered constrained
203:             * if:
204:             * </p>
205:             * <ul>
206:             * <li>the web application deployment descriptor contains a
207:             * <code>security-constraint</code> with a child
208:             * <code>web-resource-collection/url-pattern</code> element matching the
209:             * URL, <em>and</em>:</li>
210:             * <li>this constraint also contains an
211:             * <code>auth-constraint/role-name</code> element equal to the supplied
212:             * Role's <code>getName()</code> method. If the supplied Role is Role.ALL,
213:             * it matches all roles</li>
214:             * </ul>
215:             * @param url the web resource
216:             * @param role the role
217:             * @return <code>true</code> if the resource is constrained to the role,
218:             *         <code>false</code> otherwise
219:             * @throws JDOMException if elements cannot be parsed correctly
220:             */
221:            public boolean isConstrained(String url, Role role)
222:                    throws JDOMException {
223:                Element root = m_webxml.getRootElement();
224:                XPath xpath;
225:                String selector;
226:
227:                // Get all constraints that have our URL pattern
228:                // (Note the crazy j: prefix to denote the 2.4 j2ee schema)
229:                selector = "//j:web-app/j:security-constraint[j:web-resource-collection/j:url-pattern=\""
230:                        + url + "\"]";
231:                xpath = XPath.newInstance(selector);
232:                xpath.addNamespace("j", J2EE_SCHEMA_24_NAMESPACE);
233:                List constraints = xpath.selectNodes(root);
234:
235:                // Get all constraints that match our Role pattern
236:                selector = "//j:web-app/j:security-constraint[j:auth-constraint/j:role-name=\""
237:                        + role.getName() + "\"]";
238:                xpath = XPath.newInstance(selector);
239:                xpath.addNamespace("j", J2EE_SCHEMA_24_NAMESPACE);
240:                List roles = xpath.selectNodes(root);
241:
242:                // If we can't find either one, we must not be constrained
243:                if (constraints.size() == 0) {
244:                    return false;
245:                }
246:
247:                // Shortcut: if the role is ALL, we are constrained
248:                if (role.equals(Role.ALL)) {
249:                    return true;
250:                }
251:
252:                // If no roles, we must not be constrained
253:                if (roles.size() == 0) {
254:                    return false;
255:                }
256:
257:                // If a constraint is contained in both lists, we must be constrained
258:                for (Iterator c = constraints.iterator(); c.hasNext();) {
259:                    Element constraint = (Element) c.next();
260:                    for (Iterator r = roles.iterator(); r.hasNext();) {
261:                        Element roleConstraint = (Element) r.next();
262:                        if (constraint.equals(roleConstraint)) {
263:                            return true;
264:                        }
265:                    }
266:                }
267:                return false;
268:            }
269:
270:            /**
271:             * Returns <code>true</code> if the web container is configured to protect
272:             * certain JSPWiki resources by requiring authentication. Specifically, this
273:             * method parses JSPWiki's web application descriptor (<code>web.xml</code>)
274:             * and identifies whether the string representation of
275:             * {@link com.ecyrd.jspwiki.auth.authorize.Role#AUTHENTICATED} is required
276:             * to access <code>/Delete.jsp</code> and <code>LoginRedirect.jsp</code>.
277:             * If the administrator has uncommented the large
278:             * <code>&lt;security-constraint&gt;</code> section of <code>web.xml</code>,
279:             * this will be true. This is admittedly an indirect way to go about it, but
280:             * it should be an accurate test for default installations, and also in 99%
281:             * of customized installs.
282:             * @return <code>true</code> if the container protects resources,
283:             *         <code>false</code> otherwise
284:             */
285:            public boolean isContainerAuthorized() {
286:                return m_containerAuthorized;
287:            }
288:
289:            /**
290:             * Returns an array of role Principals this Authorizer knows about.
291:             * This method will return an array of Role objects corresponding to
292:             * the logical roles enumerated in the <code>web.xml</code>.
293:             * This method actually returns a defensive copy of an internally stored
294:             * array.
295:             * @return an array of Principals representing the roles
296:             */
297:            public Principal[] getRoles() {
298:                return (Principal[]) m_containerRoles.clone();
299:            }
300:
301:            /**
302:             * Protected method that extracts the roles from JSPWiki's web application
303:             * deployment descriptor. Each Role is constructed by using the String
304:             * representation of the Role, for example
305:             * <code>new Role("Administrator")</code>.
306:             * @param webxml the web application deployment descriptor
307:             * @return an array of Role objects
308:             * @throws JDOMException if elements cannot be parsed correctly
309:             */
310:            protected Role[] getRoles(Document webxml) throws JDOMException {
311:                Set roles = new HashSet();
312:                Element root = webxml.getRootElement();
313:
314:                // Get roles referred to by constraints
315:                String selector = "//j:web-app/j:security-constraint/j:auth-constraint/j:role-name";
316:                XPath xpath = XPath.newInstance(selector);
317:                xpath.addNamespace("j", J2EE_SCHEMA_24_NAMESPACE);
318:                List nodes = xpath.selectNodes(root);
319:                for (Iterator it = nodes.iterator(); it.hasNext();) {
320:                    String role = ((Element) it.next()).getTextTrim();
321:                    roles.add(new Role(role));
322:                }
323:
324:                // Get all defined roles
325:                selector = "//j:web-app/j:security-role/j:role-name";
326:                xpath = XPath.newInstance(selector);
327:                xpath.addNamespace("j", J2EE_SCHEMA_24_NAMESPACE);
328:                nodes = xpath.selectNodes(root);
329:                for (Iterator it = nodes.iterator(); it.hasNext();) {
330:                    String role = ((Element) it.next()).getTextTrim();
331:                    roles.add(new Role(role));
332:                }
333:
334:                return (Role[]) roles.toArray(new Role[roles.size()]);
335:            }
336:
337:            /**
338:             * Returns an {@link org.jdom.Document} representing JSPWiki's web
339:             * application deployment descriptor. The document is obtained by calling
340:             * the servlet context's <code>getResource()</code> method and requesting
341:             * <code>/WEB-INF/web.xml</code>. For non-servlet applications, this
342:             * method calls this class'
343:             * {@link ClassLoader#getResource(java.lang.String)} and requesting
344:             * <code>WEB-INF/web.xml</code>.
345:             * @return the descriptor
346:             * @throws IOException if the deployment descriptor cannot be found or opened
347:             * @throws JDOMException if the deployment descriptor cannot be parsed correctly
348:             */
349:            protected Document getWebXml() throws JDOMException, IOException {
350:                URL url;
351:                SAXBuilder builder = new SAXBuilder();
352:                builder.setValidation(false);
353:                builder.setEntityResolver(new LocalEntityResolver());
354:                Document doc = null;
355:                if (m_engine.getServletContext() == null) {
356:                    ClassLoader cl = WebContainerAuthorizer.class
357:                            .getClassLoader();
358:                    url = cl.getResource("WEB-INF/web.xml");
359:                    if (url != null)
360:                        log.info("Examining " + url.toExternalForm());
361:                } else {
362:                    url = m_engine.getServletContext().getResource(
363:                            "/WEB-INF/web.xml");
364:                    if (url != null)
365:                        log.info("Examining " + url.toExternalForm());
366:                }
367:                if (url == null)
368:                    throw new IOException(
369:                            "Unable to find web.xml for processing.");
370:
371:                log.debug("Processing web.xml at " + url.toExternalForm());
372:                doc = builder.build(url);
373:                return doc;
374:            }
375:
376:            /**
377:             * <p>XML entity resolver that redirects resolution requests by JDOM, JAXP and
378:             * other XML parsers to locally-cached copies of the resources. Local
379:             * resources are stored in the <code>WEB-INF/dtd</code> directory.</p>
380:             * <p>For example, Sun Microsystem's DTD for the webapp 2.3 specification is normally
381:             * kept at <code>http://java.sun.com/dtd/web-app_2_3.dtd</code>. The
382:             * local copy is stored at <code>WEB-INF/dtd/web-app_2_3.dtd</code>.</p>
383:             * @author Andrew Jaquith
384:             */
385:            public class LocalEntityResolver implements  EntityResolver {
386:                /**
387:                 * Returns an XML input source for a requested external resource by
388:                 * reading the resource instead from local storage. The local resource path
389:                 * is <code>WEB-INF/dtd</code>, plus the file name of the requested
390:                 * resource, minus the non-filename path information.
391:                 * @param publicId the public ID, such as
392:                 *            <code>-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN</code>
393:                 * @param systemId the system ID, such as
394:                 *            <code>http://java.sun.com/dtd/web-app_2_3.dtd</code>
395:                 * @return the InputSource containing the resolved resource
396:                 * @see org.xml.sax.EntityResolver#resolveEntity(java.lang.String,
397:                 *      java.lang.String)
398:                 * @throws SAXException if the resource cannot be resolved locally
399:                 * @throws IOException if the resource cannot be opened
400:                 */
401:                public InputSource resolveEntity(String publicId,
402:                        String systemId) throws SAXException, IOException {
403:                    String file = systemId
404:                            .substring(systemId.lastIndexOf('/') + 1);
405:                    URL url;
406:                    if (m_engine.getServletContext() == null) {
407:                        ClassLoader cl = WebContainerAuthorizer.class
408:                                .getClassLoader();
409:                        url = cl.getResource("WEB-INF/dtd/" + file);
410:                    } else {
411:                        url = m_engine.getServletContext().getResource(
412:                                "/WEB-INF/dtd/" + file);
413:                    }
414:
415:                    if (url != null) {
416:                        InputSource is = new InputSource(url.openStream());
417:                        log.debug("Resolved systemID=" + systemId
418:                                + " using local file " + url);
419:                        return is;
420:                    }
421:
422:                    //
423:                    //  Let's fall back to default behaviour of the container, and let's
424:                    //  also let the user know what is going on.  This caught me by surprise
425:                    //  while running JSPWiki on an unconnected laptop...
426:                    //
427:                    //  The DTD needs to be resolved and read because it contains things like
428:                    //  entity definitions...
429:                    //
430:                    log
431:                            .info("Please note: There are no local DTD references in /WEB-INF/dtd/"
432:                                    + file
433:                                    + "; falling back to default behaviour."
434:                                    + " This may mean that the XML parser will attempt to connect to the internet to find the DTD."
435:                                    + " If you are running JSPWiki locally in an unconnected network, you might want to put the DTD files in place to avoid nasty UnknownHostExceptions.");
436:
437:                    // Fall back to default behaviour
438:                    return null;
439:                }
440:            }
441:
442:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.