blob: 075f0723e634004c26f360440ace17cff7c00ce1 [file] [log] [blame]
/*
* Copyright 2002,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.jelly.tags.jetty;
import org.apache.commons.jelly.JellyTagException;
import org.apache.commons.jelly.TagSupport;
import org.apache.commons.jelly.XMLOutput;
import org.mortbay.http.BasicAuthenticator;
import org.mortbay.http.ClientCertAuthenticator;
import org.mortbay.http.DigestAuthenticator;
import org.mortbay.http.SecurityConstraint.Authenticator;
import org.mortbay.http.SecurityConstraint;
import org.mortbay.http.handler.SecurityHandler;
import org.mortbay.jetty.servlet.FormAuthenticator;
import org.mortbay.util.Code;
import org.mortbay.xml.XmlParser;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
/**
* Declare a security handler for a Jetty http server
*
* @author rtl
* @version $Id: SecurityHandlerTag.java,v 1.3 2002/07/14 12:38:22 dion Exp $
*/
public class SecurityHandlerTag extends TagSupport {
/** a form authenticator used by this tag */
private transient FormAuthenticator _formAuthenticator;
/** parameter authentication method, defaults to BASIC in Jetty */
private String _authenticationMethod;
/** Creates a new instance of SecurityHandlerTag */
public SecurityHandlerTag() {
}
/**
* Perform the tag functionality. In this case, add a security handler
* to the parent context, setting the authentication method if required
* The security constraints should be specified as the body of this tag
* using the same format as a web.xml file wrapped in a single
* <constraints> tag to allow parsing of a well-formed snippet, e.g.
*
* <constraints>
* <security-constraint>
* <web-resource-collection>
* <web-resource-name>Default</web-resource-name>
* <url-pattern>/</url-pattern>
* </web-resource-collection>
* <auth-constraint/>
* </security-constraint>
*
* <security-constraint>
* <web-resource-collection>
* <url-pattern>/docRoot/resourceHandlerTest/*</url-pattern>
* <http-method>GET</http-method>
* <http-method>HEAD</http-method>
* </web-resource-collection>
* <auth-constraint>
* <role-name>*</role-name>
* </auth-constraint>
* </security-constraint>
*
* <login-config>
* <auth-method>BASIC</auth-method>
* <realm-name>Jetty Demo Realm</realm-name>
* </login-config>
*
* </constraints>
*
* @param xmlOutput where to send output
* @throws Exception when an error occurs
*/
public void doTag(XMLOutput xmlOutput) throws JellyTagException {
HttpContextTag httpContext = (HttpContextTag) findAncestorWithClass(
HttpContextTag.class);
if ( httpContext == null ) {
throw new JellyTagException( "<securityHandler> tag must be enclosed inside a <httpContext> tag" );
}
SecurityHandler securityHandler = new SecurityHandler();
if (getauthenticationMethod() != null) {
securityHandler.setAuthMethod(getauthenticationMethod());
}
httpContext.addHandler(securityHandler);
// get the security constraints from the body of this tag
// by parsing the body of the parent (so it will be well formed)
String bodyText = getBodyText();
StringReader reader = new StringReader(bodyText);
InputSource inputSource = new InputSource(reader);
// crate a non-validating parser
XmlParser xmlParser = new XmlParser(false);
XmlParser.Node node = null;
try {
node = xmlParser.parse(inputSource);
}
catch (IOException e) {
throw new JellyTagException(e);
}
catch (SAXException e) {
throw new JellyTagException(e);
}
Iterator iter=node.iterator();
XmlParser.Node currNode = null;
while (iter.hasNext())
{
Object o = iter.next();
if (!(o instanceof XmlParser.Node))
continue;
currNode=(XmlParser.Node)o;
String name=currNode.getTag();
if ("security-constraint".equals(name)) {
initSecurityConstraint(currNode, httpContext);
} else if ("login-config".equals(name)) {
initLoginConfig(currNode, httpContext);
} else {
throw new JellyTagException("Invalid element in <securityHandler> tag. Are you using the <constraints> tag?: " + currNode);
}
}
}
/* ------------------------------------------------------------
* This is the code from Jetty's WebApplicationContext
* with the HttpContextTag parameter added
*
* Process a parsed xml node to setup the security constraints
* for an http server
*
* @param node the parsed xml starting node of the constraints
* @param httpContext the tag to add the security constraint to
*/
protected void initSecurityConstraint(XmlParser.Node node,
HttpContextTag httpContext)
{
SecurityConstraint scBase = new SecurityConstraint();
XmlParser.Node auths=node.get("auth-constraint");
if (auths!=null)
{
scBase.setAuthenticate(true);
// auth-constraint
Iterator iter= auths.iterator("role-name");
while(iter.hasNext())
{
String role=((XmlParser.Node)iter.next()).toString(false,true);
scBase.addRole(role);
}
}
XmlParser.Node data=node.get("user-data-constraint");
if (data!=null)
{
data=data.get("transport-guarantee");
String guarantee = data.toString(false,true).toUpperCase();
if (guarantee==null || guarantee.length()==0 ||
"NONE".equals(guarantee))
scBase.setDataConstraint(SecurityConstraint.DC_NONE);
else if ("INTEGRAL".equals(guarantee))
scBase.setDataConstraint(SecurityConstraint.DC_INTEGRAL);
else if ("CONFIDENTIAL".equals(guarantee))
scBase.setDataConstraint(SecurityConstraint.DC_CONFIDENTIAL);
else
{
Code.warning("Unknown user-data-constraint:"+guarantee);
scBase.setDataConstraint(SecurityConstraint.DC_CONFIDENTIAL);
}
}
Iterator iter= node.iterator("web-resource-collection");
while(iter.hasNext())
{
XmlParser.Node collection=(XmlParser.Node)iter.next();
String name=collection.getString("web-resource-name",false,true);
SecurityConstraint sc = (SecurityConstraint)scBase.clone();
sc.setName(name);
Iterator iter2= collection.iterator("http-method");
while(iter2.hasNext())
sc.addMethod(((XmlParser.Node)iter2.next())
.toString(false,true));
iter2= collection.iterator("url-pattern");
while(iter2.hasNext())
{
String url=
((XmlParser.Node)iter2.next()).toString(false,true);
httpContext.addSecurityConstraint(url,sc);
}
}
}
/* ------------------------------------------------------------
* This is the code from Jetty's WebApplicationContext
* with the HttpContextTag parameter added
*
*
* Process a parsed xml node to setup the authenticator and realm
* for an http server
*
* @param node the parsed xml starting node of the login configuration
* @param httpContext the tag to add the authenticator and realm to
*/
protected void initLoginConfig(XmlParser.Node node,
HttpContextTag httpContext)
{
XmlParser.Node method=node.get("auth-method");
if (method!=null)
{
Authenticator authenticator=null;
String m=method.toString(false,true);
if (SecurityConstraint.__FORM_AUTH.equals(m))
authenticator=_formAuthenticator=new FormAuthenticator();
else if (SecurityConstraint.__BASIC_AUTH.equals(m))
authenticator=new BasicAuthenticator();
else if (SecurityConstraint.__DIGEST_AUTH.equals(m))
authenticator=new DigestAuthenticator();
else if (SecurityConstraint.__CERT_AUTH.equals(m))
authenticator=new ClientCertAuthenticator();
else
Code.warning("UNKNOWN AUTH METHOD: "+m);
httpContext.setAuthenticator(authenticator);
}
XmlParser.Node name=node.get("realm-name");
if (name!=null)
httpContext.setRealmName(name.toString(false,true));
XmlParser.Node formConfig = node.get("form-login-config");
if(formConfig != null)
{
if (_formAuthenticator==null)
Code.warning("FORM Authentication miss-configured");
else
{
XmlParser.Node loginPage = formConfig.get("form-login-page");
if (loginPage != null)
_formAuthenticator.setLoginPage(loginPage.toString(false,true));
XmlParser.Node errorPage = formConfig.get("form-error-page");
if (errorPage != null)
_formAuthenticator.setErrorPage(errorPage.toString(false,true));
}
}
}
//--------------------------------------------------------------------------
// Property accessors/mutators
//--------------------------------------------------------------------------
/**
* Getter for property authenticationMethod.
*
* @return value of property authenticationMethod.
*/
public String getauthenticationMethod() {
return _authenticationMethod;
}
/**
* Setter for property authenticationMethod.
*
* @param authenticationMethod Type of authentication (BASIC, FORM, DIGEST, CLIENT-CERT)
* Note that only BASIC and CLIENT-CERT are supported by Jetty as of v4.1.1
*/
public void setauthenticationMethod(String authenticationMethod) {
_authenticationMethod = authenticationMethod;
}
}