深入剖析Tomcat(How Tomcat works)读书笔记

2019-12-08  本文已影响0人  抬头挺胸才算活着

参考资料:
[1]. 深入剖析Tomcat(How Tomcat works)书籍代码下载地址

第八章:载入器
第九章:Session管理器
第十章:安全性

  1. 因为使用系统的类加载器,servlet可以访问所有的类,这是非常危险的,servlet应该只允许载入WEB-INF/classes目录下的所有类和库。2. 为了提供自动重载的功能,当类的目录下的类方式变化时,WEB应用会重新载入这些类。类加载器使用一个额外的线程来不断地检查servlet类及其他类的文件的时间戳,若要支持自动重载功能,类加载器要实现Reloader接口。类记载器要实现Loader接口。
  1. 为了在加载器中指定某些规则
  2. 为了缓存已经载入的类
  3. 为了实现类的预载入,方便使用
public final class Bootstrap1 {
  public static void main(String[] args) {

    LifecycleListener listener = new SimpleContextConfig();
    ((Lifecycle) context).addLifecycleListener(listener);

    // add constraint
    SecurityCollection securityCollection = new SecurityCollection();
    securityCollection.addPattern("/");
    securityCollection.addMethod("GET");

    SecurityConstraint constraint = new SecurityConstraint();
    constraint.addCollection(securityCollection);
    constraint.addAuthRole("manager");
    LoginConfig loginConfig = new LoginConfig();
    loginConfig.setRealmName("Simple Realm");
    // add realm
    Realm realm = new SimpleRealm();

    context.setRealm(realm);
    context.addConstraint(constraint);
    context.setLoginConfig(loginConfig);
    }
}

public class SimpleContextConfig implements LifecycleListener {

  private Context context;
  public void lifecycleEvent(LifecycleEvent event) {
    if (Lifecycle.START_EVENT.equals(event.getType())) {
      context = (Context) event.getLifecycle();
      authenticatorConfig();
      context.setConfigured(true);
    }
  }

  private synchronized void authenticatorConfig() {
    // Does this Context require an Authenticator?
    SecurityConstraint constraints[] = context.findConstraints();
    if ((constraints == null) || (constraints.length == 0))
      return;
    LoginConfig loginConfig = context.getLoginConfig();
    if (loginConfig == null) {
      loginConfig = new LoginConfig("NONE", null, null, null);
      context.setLoginConfig(loginConfig);
    }

    // Has an authenticator been configured already?
    Pipeline pipeline = ((StandardContext) context).getPipeline();
    if (pipeline != null) {
      Valve basic = pipeline.getBasic();
      if ((basic != null) && (basic instanceof Authenticator))
        return;
      Valve valves[] = pipeline.getValves();
      for (int i = 0; i < valves.length; i++) {
        if (valves[i] instanceof Authenticator)
        return;
      }
    }
    else { // no Pipeline, cannot install authenticator valve
      return;
    }

    // Has a Realm been configured for us to authenticate against?
    if (context.getRealm() == null) {
      return;
    }

    // Identify the class name of the Valve we should configure
    String authenticatorName = "org.apache.catalina.authenticator.BasicAuthenticator";
    // Instantiate and install an Authenticator of the requested class
    Valve authenticator = null;
    try {
      Class authenticatorClass = Class.forName(authenticatorName);
      authenticator = (Valve) authenticatorClass.newInstance();
      ((StandardContext) context).addValve(authenticator);
      System.out.println("Added authenticator valve to Context");
    }
    catch (Throwable t) {
    }
  }
}

authenticatorConfig方法首先检查了是否配置了SecurityConstraint,是否已经实现了安装了Authenticator,Context是否已经配置了Realm(因为Authenticator最后验证还是调用的Realm),最后再给Context配置一个阀门BasicAuthenticator。

public abstract class AuthenticatorBase
    extends ValveBase
    implements Authenticator, Lifecycle {

    public void invoke(Request request, Response response,
                       ValveContext context)
        throws IOException, ServletException {

        // If this is not an HTTP request, do nothing
        if (!(request instanceof HttpRequest) ||
            !(response instanceof HttpResponse)) {
            context.invokeNext(request, response);
            return;
        }
        if (!(request.getRequest() instanceof HttpServletRequest) ||
            !(response.getResponse() instanceof HttpServletResponse)) {
            context.invokeNext(request, response);
            return;
        }
        HttpRequest hrequest = (HttpRequest) request;
        HttpResponse hresponse = (HttpResponse) response;
        if (debug >= 1)
            log("Security checking request " +
                ((HttpServletRequest) request.getRequest()).getMethod() + " " +
                ((HttpServletRequest) request.getRequest()).getRequestURI());
        LoginConfig config = this.context.getLoginConfig();

        // Have we got a cached authenticated Principal to record?
        if (cache) {
            Principal principal =
                ((HttpServletRequest) request.getRequest()).getUserPrincipal();
            if (principal == null) {
                Session session = getSession(hrequest);
                if (session != null) {
                    principal = session.getPrincipal();
                    if (principal != null) {
                        if (debug >= 1)
                            log("We have cached auth type " +
                                session.getAuthType() +
                                " for principal " +
                                session.getPrincipal());
                        hrequest.setAuthType(session.getAuthType());
                        hrequest.setUserPrincipal(principal);
                    }
                }
            }
        }

        // Special handling for form-based logins to deal with the case
        // where the login form (and therefore the "j_security_check" URI
        // to which it submits) might be outside the secured area
        String contextPath = this.context.getPath();
        String requestURI = hrequest.getDecodedRequestURI();
        if (requestURI.startsWith(contextPath) &&
            requestURI.endsWith(Constants.FORM_ACTION)) {
            if (!authenticate(hrequest, hresponse, config)) {
                if (debug >= 1)
                    log(" Failed authenticate() test");
                return;
            }
        }

        // Is this request URI subject to a security constraint?
        SecurityConstraint constraint = findConstraint(hrequest);
        if ((constraint == null) /* &&
            (!Constants.FORM_METHOD.equals(config.getAuthMethod())) */ ) {
            if (debug >= 1)
                log(" Not subject to any constraint");
            context.invokeNext(request, response);
            return;
        }
        if ((debug >= 1) && (constraint != null))
            log(" Subject to constraint " + constraint);

        // Make sure that constrained resources are not cached by web proxies
        // or browsers as caching can provide a security hole
        if (!(((HttpServletRequest) hrequest.getRequest()).isSecure())) {
            HttpServletResponse sresponse = 
                (HttpServletResponse) response.getResponse();
            sresponse.setHeader("Pragma", "No-cache");
            sresponse.setHeader("Cache-Control", "no-cache");
            sresponse.setDateHeader("Expires", 1);
        }

        // Enforce any user data constraint for this security constraint
        if (debug >= 1)
            log(" Calling checkUserData()");
        if (!checkUserData(hrequest, hresponse, constraint)) {
            if (debug >= 1)
                log(" Failed checkUserData() test");
            // ASSERT: Authenticator already set the appropriate
            // HTTP status code, so we do not have to do anything special
            return;
        }

        // Authenticate based upon the specified login configuration
        if (constraint.getAuthConstraint()) {
            if (debug >= 1)
                log(" Calling authenticate()");
            if (!authenticate(hrequest, hresponse, config)) {
                if (debug >= 1)
                    log(" Failed authenticate() test");
                // ASSERT: Authenticator already set the appropriate
                // HTTP status code, so we do not have to do anything special
                return;
            }
        }

        // Perform access control based on the specified role(s)
        if (constraint.getAuthConstraint()) {
            if (debug >= 1)
                log(" Calling accessControl()");
            if (!accessControl(hrequest, hresponse, constraint)) {
                if (debug >= 1)
                    log(" Failed accessControl() test");
                // ASSERT: AccessControl method has already set the appropriate
                // HTTP status code, so we do not have to do anything special
                return;
            }
        }

        // Any and all specified constraints have been satisfied
        if (debug >= 1)
            log(" Successfully passed all security constraints");
        context.invokeNext(request, response);

    }
}
上一篇下一篇

猜你喜欢

热点阅读