📄 accessinterceptor.java
字号:
/*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.tomcat.request;
import org.apache.tomcat.core.*;
import org.apache.tomcat.core.Constants;
import org.apache.tomcat.util.*;
import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import java.util.*;
// XXX maybe it's a good idea to use a different model for adding secuirty
// constraints - we use Container now because we want to generalize all
// per/URL properties.
/**
* Access control - find if a request matches any web-resource-collection
* and set the "required" attributes.
*
* The spec requires additive checking ( i.e. there is no "best match"
* defined, but "all requests that contain a request path that mathces the
* URL pattern in the resource collection are subject to the constraing" ).
*
* In "integrated" mode this interceptor will be no-op, we'll use the
* web server ( assuming we can map the security to web-server equivalent
* concepts - I think we can do that, but need to experiment with that)
*/
public class AccessInterceptor extends BaseInterceptor {
ContextManager cm;
// Security mapping note
int secMapNote;
// Required roles attribute
int reqRolesNote;
int reqTransportNote;
public AccessInterceptor() {
}
/* -------------------- Initialization -------------------- */
/** Set the context manager. To keep it simple we don't support
* dynamic add/remove for this interceptor.
*/
public void engineInit(ContextManager cm) throws TomcatException {
super.engineInit( cm );
this.cm=cm;
// set-up a per/container note for maps
try {
secMapNote = cm.getNoteId( ContextManager.CONTAINER_NOTE,
"map.security");
// Used for inter-module communication - required role, tr
reqRolesNote = cm.getNoteId( ContextManager.REQUEST_NOTE,
"required.roles");
reqTransportNote = cm.getNoteId( ContextManager.REQUEST_NOTE,
"required.transport");
} catch( TomcatException ex ) {
ex.printStackTrace();
throw new RuntimeException( "Invalid state ");
}
}
public void contextInit( Context ctx)
throws TomcatException
{
String login_type=ctx.getAuthMethod();
if( debug > 0 ) log( "Init " + ctx.getHost() + " " +
ctx.getPath() + " " + login_type );
if( null==ctx.getErrorPage( "403" )) {
ctx.addServlet( new SSLRequiredHandler());
ctx.addErrorPage( "403", "tomcat.sslRequiredHandler");
}
if( "FORM".equals( login_type )) {
String page=ctx.getFormLoginPage();
String errorPage = ctx.getFormErrorPage();
if(page==null || errorPage==null) {
ctx.log( "Form login without form pages, defaulting to basic "
+ page + " " + errorPage);
// if the user specifies a 401 page do nothing
if( null==ctx.getErrorPage( "401" )) {
ctx.addServlet( new BasicAuthHandler());
ctx.addErrorPage( "401", "tomcat.basicAuthHandler");
}
return;
}
// Workaround for common error - no "/" at start of page
if( ! page.startsWith("/")) {
ctx.log("FORM: login page doesn't start with / " + page );
page="/" + page;
}
if( ! errorPage.startsWith("/")) {
ctx.log("FORM: error page doesn't start with / " + errorPage );
errorPage="/" + errorPage;
}
String cpath=ctx.getPath();
// Workaround for common error - ctx path included
if( page.startsWith( cpath ) ) {
if( ! ("".equals(cpath) || "/".equals(cpath)) )
ctx.log("FORM: WARNING, login page starts with " +
"context path " + page + " " + cpath );
} else
page= cpath + page;
if( errorPage.startsWith( cpath ) ) {
if( ! ("/".equals(cpath) || "".equals( cpath )) )
ctx.log("FORM: WARNING, error page starts with " +
"context path " + errorPage);
} else
errorPage= cpath + errorPage;
// Adjust login and error paths - avoid computations in handlers
ctx.setFormLoginPage( page );
ctx.setFormErrorPage( errorPage );
FormAuthHandler formH=new FormAuthHandler();
formH.setDebug(0);
ctx.addServlet( formH );
ctx.addServlet( new FormSecurityCheckHandler() );
ctx.addErrorPage( "401", "tomcat.formAuthHandler");
// Add mapping for the POST handler
String pageP=page.substring( cpath.length());
int lastS=pageP.lastIndexOf( "/" );
String location="/j_security_check";
if( lastS > 0 ) {
location=pageP.substring( 0, lastS) +
"/j_security_check";
}
ctx.addServletMapping( location,
"tomcat.formSecurityCheck");
if( debug > 0 )
ctx.log( "Map " + location +
" to tomcat.formSecurityCheck for " +
page);
} else if( "BASIC".equals( login_type )) {
if( null==ctx.getErrorPage( "401" )) {
ctx.addServlet( new BasicAuthHandler());
ctx.addErrorPage( "401", "tomcat.basicAuthHandler");
}
} else {
// if unknown, leave the normal 404 error handler to deal
// with unauthorized access.
}
}
// XXX not implemented - will deal with that after everything else works.
public void removeContainer( Container ct )
throws TomcatException
{
}
/**
*/
public void addContainer( Container ct )
throws TomcatException
{
Context ctx=ct.getContext();
Container ctxCt=ctx.getContainer();
SecurityConstraints ctxSecurityC=(SecurityConstraints)ctxCt.
getNote( secMapNote );
if( ctxSecurityC==null)
ctxCt.setNote( secMapNote, new SecurityConstraints() );
if( ct.getRoles()!=null || ct.getTransport()!=null ) {
if( debug > 0 )
log( "addContainer() " + ctx.getHost() + " " +
ctx.getPath() + " " +
ct.getPath() );
ctxSecurityC.addContainer( ct );
}
}
/* -------------------- Request mapping -------------------- */
/** Check if this request requires auth, and if so check the roles.
*/
public int requestMap( Request req )
{
Context ctx=req.getContext();
SecurityConstraints ctxSec=(SecurityConstraints)ctx.getContainer().
getNote( secMapNote );
if( ctxSec.patterns==0 ) return 0; // fast exit
String reqURI = req.getRequestURI();
// Servlet spec would allow it to pass. A better fix is to "normalize"
// the URL
if( reqURI.indexOf( "//" ) >= 0 )
return 403;
String ctxPath= ctx.getPath();
String path=reqURI.substring( ctxPath.length());
String method=req.getMethod();
if( debug > 1 ) log( "checking " + path );
for( int i=0; i< ctxSec.patterns ; i++ ) {
Container ct=ctxSec.securityPatterns[i];
if( match( ct, path, method ) ) {
String roles[]=ct.getRoles();
String methods[]=ct.getMethods();
String transport=ct.getTransport();
if( debug>0) {
StringBuffer sb=new StringBuffer("matched ");
sb.append(ct.getPath()).append(" ");
if(methods!=null)
for( int j=0; j< methods.length; j++ )
sb.append(methods[j]).append(" ");
sb.append(transport).append(" ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -