tomcat(10)安全性
case1)用户输入了正确的username 和 pwd:验证器阀会调用后续的阀;case2)用户输入错误:验证器阀会返回,不会调用后续的阀;
private void createUserDatabase() {// SimpleRealm.createUserDatabase() 创建了users 列表;User user1 = new User("ken", "blackcomb");user1.addRole("manager");user1.addRole("programmer");User user2 = new User("cindy", "bamboo");user2.addRole("programmer");users.add(user1);users.add(user2);}
public Principal authenticate (String username, String credentials); // generally used
public Principal authenticate (String username, byte[] credentials);
public Principal authenticate (String username, String digest, String nonce, String nc, String cnonce, String qop, String realm, String md5a2);
public Principal authenticate (X509Certificate cents[]);;
3)在catalina中, Realm接口的基本实现形式是org.apache.catalina.realm.RealmBase类;其UML类图如下:
public class GenericPrincipal implements Principal { //org.apache.catalina.realm.GenericPrincipal,代表一个用户(封装了username,password,role,realm)public GenericPrincipal(Realm realm, String name, String password) {this(realm, name, password, null);}public GenericPrincipal(Realm realm, String name, String password,List roles) {super();this.realm = realm;this.name = name;this.password = password;if (roles != null) {this.roles = new String[roles.size()];this.roles = (String[]) roles.toArray(this.roles);if (this.roles.length > 0)Arrays.sort(this.roles);}}protected String name = null;public String getName() {return (this.name);}protected String password = null; public String getPassword() {return (this.password);}protected Realm realm = null; public Realm getRealm() {return (this.realm);}protected String roles[] = new String[0]; public String[] getRoles() {return (this.roles);}public boolean hasRole(String role) { // highlight line.if (role == null)return (false);return (Arrays.binarySearch(roles, role) >= 0);}public String toString() {StringBuffer sb = new StringBuffer("GenericPrincipal[");sb.append(this.name);sb.append("]");return (sb.toString());}
}
step1)如果web.xml 文件包含 login-config 元素的配置,则tomcat会创建一个 LoginConfig对象,并设置其相应属性;(干货——tomcat创建一个 LoginConfig对象的条件)step2)验证器阀会调用 LoginConfig.getRealmName() 获取领域对象名,并将领域对象名发送到 browser,显示在登录对话框中;case2.1)如果getReamlName()方法的返回值是null,则会将服务器名和相应端口发送给 browser;
public final class LoginConfig { //org.apache.catalina.deploy.LoginConfigpublic LoginConfig() {super();} public LoginConfig(String authMethod, String realmName,String loginPage, String errorPage) {super();setAuthMethod(authMethod);setRealmName(realmName);setLoginPage(loginPage);setErrorPage(errorPage);}// ------------------------------------------------------------- Properties private String authMethod = null;public String getAuthMethod() {return (this.authMethod);}public void setAuthMethod(String authMethod) {this.authMethod = authMethod;}private String errorPage = null;public String getErrorPage() {return (this.errorPage);}public void setErrorPage(String errorPage) { this.errorPage = RequestUtil.URLDecode(errorPage);} private String loginPage = null;public String getLoginPage() {return (this.loginPage);}public void setLoginPage(String loginPage) { this.loginPage = RequestUtil.URLDecode(loginPage);} private String realmName = null;public String getRealmName() {return (this.realmName);}public void setRealmName(String realmName) {this.realmName = realmName;} public String toString() {StringBuffer sb = new StringBuffer("LoginConfig[");sb.append("authMethod=");sb.append(authMethod);if (realmName != null) {sb.append(", realmName=");sb.append(realmName);}if (loginPage != null) {sb.append(", loginPage=");sb.append(loginPage);}if (errorPage != null) {sb.append(", errorPage=");sb.append(errorPage);}sb.append("]");return (sb.toString());}
}
A1)BasicAuthenticator:用来支持基本的身份验证;A2)FormAuthenticator:提供了基于表单的身份验证;A3)DigestAuthenticator:提供了基于信息摘要的身份验证;A4)SSLAuthenticator:用于对SSL 进行身份验证;A5)当tomcat 用户没有指定验证方法名时,NonLoginAuthenticator类用于对来访者的身份进行验证。NonLoginAuthenticator类实现的验证器只会检查安全限制,而不会涉及用户身份的验证;
A1)验证器的重要工作:是对用户进行身份验证;(干货——验证器的重要工作是对用户进行身份验证)A2)当看到 AuthenticatorBase.invoke() 方法调用 authenticate() 抽象方法时:后者的实现依赖于子类;(而authenticate()方法会使用基本身份验证来验证用户的身份信息);
public class BasicAuthenticator extends AuthenticatorBase { <span style="font-family: SimSun;">//org.apache.catalina.authenticator.BasicAuthenticator,这里仅以BasicAuthenticator 为例po出 source code.</span>// ----------------------------------------------------- Instance Variables protected static final Base64 base64Helper = new Base64(); protected static final String info ="org.apache.catalina.authenticator.BasicAuthenticator/1.0"; public String getInfo() {return (this.info);}public boolean authenticate(HttpRequest request,HttpResponse response,LoginConfig config)throws IOException {// Have we already authenticated someone?Principal principal =((HttpServletRequest) request.getRequest()).getUserPrincipal();String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);if (principal != null) {if (debug >= 1)log("Already authenticated '" + principal.getName() + "'");// Associate the session with any existing SSO sessionif (ssoId != null)associate(ssoId, getSession(request, true));return (true);}// Is there an SSO session against which we can try to reauthenticate?if (ssoId != null) {if (debug >= 1)log("SSO Id " + ssoId + " set; attempting reauthentication"); if (reauthenticateFromSSO(ssoId, request))return true;}// Validate any credentials already included with this requestHttpServletRequest hreq =(HttpServletRequest) request.getRequest();HttpServletResponse hres =(HttpServletResponse) response.getResponse();String authorization = request.getAuthorization();String username = parseUsername(authorization);String password = parsePassword(authorization);principal = context.getRealm().authenticate(username, password);if (principal != null) {register(request, response, principal, Constants.BASIC_METHOD,username, password);return (true);}// Send an "unauthorized" response and an appropriate challengeString realmName = config.getRealmName();if (realmName == null)realmName = hreq.getServerName() + ":" + hreq.getServerPort(); hres.setHeader("WWW-Authenticate","Basic realm=\"" + realmName + "\"");hres.setStatus(HttpServletResponse.SC_UNAUTHORIZED);// hres.flushBuffer();return (false);}// ------------------------------------------------------ Protected Methodsprotected String parseUsername(String authorization) {if (authorization == null)return (null);if (!authorization.toLowerCase().startsWith("basic "))return (null);authorization = authorization.substring(6).trim();// Decode and parse the authorization credentialsString unencoded =new String(base64Helper.decode(authorization.getBytes()));int colon = unencoded.indexOf(':');if (colon < 0)return (null);String username = unencoded.substring(0, colon);// String password = unencoded.substring(colon + 1).trim();return (username);}protected String parsePassword(String authorization) {if (authorization == null)return (null);if (!authorization.startsWith("Basic "))return (null);authorization = authorization.substring(6).trim();// Decode and parse the authorization credentialsString unencoded =new String(base64Helper.decode(authorization.getBytes()));int colon = unencoded.indexOf(':');if (colon < 0)return (null);// String username = unencoded.substring(0, colon).trim();String password = unencoded.substring(colon + 1);return (password);}
}
A1)若没有设置 auth-method元素:则 LoginConfig 对象 的 atuh-method属性的值默认为 NONE,使用 NonLoginAuthenticator 进行安全验证;A2)由于使用的验证器类是在运行时才确定的,故该类是动态载入的;A3)StandardContext容器使用 org.apahce.catalina.startup.ContextConfig类来对 StandardContext 实例的属性进行设置:这些设置包括 实例化一个验证器类,并将该实例与Context实例相关联;
// Identify the class name of the Valve we should configureString authenticatorName = "org.apache.catalina.authenticator.BasicAuthenticator";// Instantiate and install an Authenticator of the requested classValve 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) {}
step1)先检查在相关联的Context容器是否有安全限制,若没有直接返回,而不会安装验证器;// Does this Context require an Authenticator?SecurityConstraint constraints[] = context.findConstraints();if ((constraints == null) || (constraints.length == 0))return;
step2)若当前Context容器有一个或多个安全限制,authenticatorConfig() 方法会检查该Context实例是否有 LoginConfig对象。若没有,则它会创建一个新的 LoginConfig实例:LoginConfig loginConfig = context.getLoginConfig();if (loginConfig == null) {loginConfig = new LoginConfig("NONE", null, null, null);context.setLoginConfig(loginConfig);}
step3)检查管道中的基础阀或附加阀是否是验证器。因为一个Context实例只能有一个验证器,所以当发现某个阀是验证器后,直接返回:// 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 valvereturn;}
step4)查找当前Context实例是否有与之关联的领域对象(Realm)。如果没有领域对象,就不需要安装验证器了,因为用户是无法通过身份验证的;// Has a Realm been configured for us to authenticate against?if (context.getRealm() == null) {return;}
step5)若找到了领域对象,则会动态载入 BasicAuthenticator类,创建该类的一个实例,并将其作为阀添加到 StandardContext实例中;// Identify the class name of the Valve we should configureString authenticatorName = "org.apache.catalina.authenticator.BasicAuthenticator";// Instantiate and install an Authenticator of the requested classValve 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) {}}
public class SimpleRealm implements Realm {public SimpleRealm() {createUserDatabase(); //highlight line.}private void createUserDatabase() { // there are 2 roles.User user1 = new User("ken", "blackcomb");user1.addRole("manager"); // manager role.user1.addRole("programmer"); // programmer role.User user2 = new User("cindy", "bamboo");user2.addRole("programmer");users.add(user1);users.add(user2);// private ArrayList users = new ArrayList();}
}
public Principal authenticate(String username, String credentials) {System.out.println("SimpleRealm.authenticate()");if (username==null || credentials==null)return null;User user = getUser(username, credentials);if (user==null)return null;return new GenericPrincipal(this, user.username, user.password, user.getRoles()); // highlight line.}
public class GenericPrincipal implements Principal { // 该类封装了用户的一些信息,如username,pass,role,realm等info;public GenericPrincipal(Realm realm, String name, String password) { this(realm, name, password, null);} public GenericPrincipal(Realm realm, String name, String password,List roles) {super();this.realm = realm;this.name = name;this.password = password;if (roles != null) {this.roles = new String[roles.size()];this.roles = (String[]) roles.toArray(this.roles);if (this.roles.length > 0)Arrays.sort(this.roles);}}protected String name = null;public String getName() {return (this.name);}protected String password = null;public String getPassword() {return (this.password);}protected Realm realm = null;public Realm getRealm() {return (this.realm);}protected String roles[] = new String[0];public String[] getRoles() {return (this.roles);} public boolean hasRole(String role) {if (role == null)return (false);return (Arrays.binarySearch(roles, role) >= 0);} public String toString() {StringBuffer sb = new StringBuffer("GenericPrincipal[");sb.append(this.name);sb.append("]");return (sb.toString());}
}
// tomcat-users.xml 的源码如下:
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users><role rolename="tomcat"/><role rolename="role1"/><role rolename="manager"/><role rolename="admin"/><user username="tomcat" password="tomcat" roles="tomcat"/><user username="role1" password="tomcat" roles="role1"/><user username="both" password="tomcat" roles="tomcat,role1"/><user username="admin" password="admin" roles="admin,manager"/>
</tomcat-users>
// 以下代码是 Bootstrap2.java 中的源码Realm realm = new SimpleUserDatabaseRealm();String filedir = new File(System.getProperty("user.dir")).getParent() + File.separator +"conf" + File.separator + "tomcat-users.xml";((SimpleUserDatabaseRealm) realm).createDatabase(filedir); // highlight line.
public void createDatabase(String path) { // SimpleUserDatabaseRealm.createDatabase().database = new MemoryUserDatabase(name);((MemoryUserDatabase) database).setPathname(path);try {database.open(); // highlight line.}catch (Exception e) {}}
public void open() throws Exception { // org.apache.catalina.users.MemoryUserDatabase.open().synchronized (groups) {synchronized (users) {// Erase any previous groups and usersusers.clear();groups.clear();roles.clear();// Construct a reader for the XML input file (if it exists)File file = new File(pathname);if (!file.isAbsolute()) {file = new File(System.getProperty("catalina.base"),pathname);}if (!file.exists()) {return;}FileInputStream fis = new FileInputStream(file);// Construct a digester to read the XML input fileDigester digester = new Digester();digester.addFactoryCreate("tomcat-users/group",new MemoryGroupCreationFactory(this));digester.addFactoryCreate("tomcat-users/role",new MemoryRoleCreationFactory(this));digester.addFactoryCreate("tomcat-users/user",new MemoryUserCreationFactory(this));// Parse the XML input file to load this databasetry {digester.parse(fis);fis.close();} catch (Exception e) {try {fis.close();} catch (Throwable t) {;}throw e;} } } }
public final class Bootstrap1 {public static void main(String[] args) {//invoke: http://localhost:8080/Modern or http://localhost:8080/PrimitiveSystem.setProperty("catalina.base", System.getProperty("user.dir"));System.out.println("user.dir = " + System.getProperty("user.dir"));Connector connector = new HttpConnector();Wrapper wrapper1 = new SimpleWrapper();wrapper1.setName("Primitive");wrapper1.setServletClass("servlet.PrimitiveServlet");Wrapper wrapper2 = new SimpleWrapper();wrapper2.setName("Modern");wrapper2.setServletClass("servlet.ModernServlet");Context context = new StandardContext(); // highlight line.// StandardContext's start method adds a default mappercontext.setPath("/myApp");context.setDocBase("myApp");LifecycleListener listener = new SimpleContextConfig();// highlight line.((Lifecycle) context).addLifecycleListener(listener);context.addChild(wrapper1);context.addChild(wrapper2);// for simplicity, we don't add a valve, but you can add// valves to context or wrapper just as you did in Chapter 6Loader loader = new WebappLoader();context.setLoader(loader);// context.addServletMapping(pattern, name);context.addServletMapping("/Primitive", "Primitive");context.addServletMapping("/Modern", "Modern");// add ContextConfig. This listener is important because it configures// StandardContext (sets configured to true), otherwise StandardContext// won't start// add constraintSecurityCollection securityCollection = new SecurityCollection();// highlight line.securityCollection.addPattern("/");// highlight line.securityCollection.addMethod("GET");// highlight line.SecurityConstraint constraint = new SecurityConstraint();// highlight line.constraint.addCollection(securityCollection);// highlight line.constraint.addAuthRole("manager");// highlight line.LoginConfig loginConfig = new LoginConfig();// highlight line.loginConfig.setRealmName("Simple Realm");// add realmRealm realm = new SimpleRealm();// highlight line.context.setRealm(realm);// highlight line.context.addConstraint(constraint);// highlight line.context.setLoginConfig(loginConfig);// highlight line.connector.setContainer(context);// add a ManagerManager manager = new StandardManager();context.setManager(manager);try {connector.initialize();((Lifecycle) connector).start();((Lifecycle) context).start();// make the application wait until we press a key.System.in.read();((Lifecycle) context).stop();}catch (Exception e) {e.printStackTrace();}}
}
A1)创建StandardContext对象:设置其path属性和 documentBase属性,并添加一个 SimpleContextConfig 类的监听器。该监听器会把一个 BasicAuthenticator 对象安装到 StandardContext 对象中;A2)创建SecurityColleciton对象:并调用其addPattern和 addMethod方法,addPattern方法指定某个url 要遵循哪个安全限制, 而addMethod方法会指定该安全限制要使用哪种验证方法;在addMethod()方法中设置为GET, 则使用GET 方法提交的http 请求会遵循安全限制;A3)创建 SecurityManager对象:并将其添加到 安全限制集合中,且还设置了哪种角色可以访问这些受限资源。A4)创建LoginConfig对象 和 SimpleRealm对象;A5)将领域对象,安全限制对象,登录配置对象 与 StandardContext实例相关联;A6)接着,启动Context实例。。。。。。。
<pre name="code" class="java">E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;lib/catalina-5.5.4.jar;lib/naming-common
jar;lib/commons-collections.jar;lib/naming-resources.jar;lib/;lib/catalina.jar;E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\webroot com.tomc
t.chapter10.startup.Bootstrap1
HttpConnector Opening server socket on all host IP addresses
HttpConnector[8080] Starting background thread
WebappLoader[/myApp]: Deploying class repositories to work directory E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src\work\_\_\myApp
Starting Wrapper Primitive
Starting Wrapper Modern
Added authenticator valve to Context
StandardManager[/myApp]: Seeding random number generator class java.security.SecureRandom
StandardManager[/myApp]: Seeding of random number generator has been completed
StandardManager[/myApp]: IOException while loading persisted sessions: java.io.EOFException
// 这是从文件中加载 session对象到内存,由于没有相关文件,所以加载失败,抛出异常,但这不会影响我们访问servlet,大家不要惊慌;
java.io.EOFExceptionat java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)at java.io.ObjectInputStream.readStreamHeader(Unknown Source)at java.io.ObjectInputStream.<init>(Unknown Source)at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:103)at org.apache.catalina.session.StandardManager.load(StandardManager.java:408)at org.apache.catalina.session.StandardManager.start(StandardManager.java:655)at org.apache.catalina.core.StandardContext.start(StandardContext.java:3570)at com.tomcat.chapter10.startup.Bootstrap1.main(Bootstrap1.java:84)
StandardManager[/myApp]: Exception loading sessions from persistent storage
java.io.EOFExceptionat java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)at java.io.ObjectInputStream.readStreamHeader(Unknown Source)at java.io.ObjectInputStream.<init>(Unknown Source)at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:103)at org.apache.catalina.session.StandardManager.load(StandardManager.java:408)at org.apache.catalina.session.StandardManager.start(StandardManager.java:655)at org.apache.catalina.core.StandardContext.start(StandardContext.java:3570)at com.tomcat.chapter10.startup.Bootstrap1.main(Bootstrap1.java:84)
SimpleRealm.authenticate()
SimpleRealm.authenticate()
ModernServlet -- init
SimpleRealm.authenticate()
SimpleRealm.authenticate()
SimpleRealm.authenticate()
SimpleRealm.authenticate()
SimpleRealm.authenticate()
SimpleRealm.authenticate()
init
SimpleRealm.authenticate()
from service
from service
public final class Bootstrap2 {public static void main(String[] args) {//invoke: http://localhost:8080/Modern or http://localhost:8080/PrimitiveSystem.setProperty("catalina.base", System.getProperty("user.dir"));Connector connector = new HttpConnector();Wrapper wrapper1 = new SimpleWrapper();wrapper1.setName("Primitive");wrapper1.setServletClass("servlet.PrimitiveServlet");Wrapper wrapper2 = new SimpleWrapper();wrapper2.setName("Modern");wrapper2.setServletClass("servlet.ModernServlet");Context context = new StandardContext(); // highlight line.// StandardContext's start method adds a default mappercontext.setPath("/myApp");context.setDocBase("myApp");LifecycleListener listener = new SimpleContextConfig();// highlight line.((Lifecycle) context).addLifecycleListener(listener);context.addChild(wrapper1);context.addChild(wrapper2);// for simplicity, we don't add a valve, but you can add// valves to context or wrapper just as you did in Chapter 6Loader loader = new WebappLoader();context.setLoader(loader);// context.addServletMapping(pattern, name);context.addServletMapping("/Primitive", "Primitive");context.addServletMapping("/Modern", "Modern");// add ContextConfig. This listener is important because it configures// StandardContext (sets configured to true), otherwise StandardContext// won't start// add constraintSecurityCollection securityCollection = new SecurityCollection();// highlight line.securityCollection.addPattern("/");// highlight line.securityCollection.addMethod("GET");// highlight line.SecurityConstraint constraint = new SecurityConstraint();// highlight line.constraint.addCollection(securityCollection);// highlight line.constraint.addAuthRole("manager");// highlight line.constraint.addAuthRole("tomcat");// highlight line.注意这里的角色,必要要和tomcat-users.xml 中的users 列表相对应,如果要设置某个用户有权限访问servlet资源,则需要添加其所属的角色;LoginConfig loginConfig = new LoginConfig();// highlight line.loginConfig.setRealmName("Simple User Database Realm");// add realmRealm realm = new SimpleUserDatabaseRealm();// highlight line.String filedir = new File(System.getProperty("user.dir")).getParent() + File.separator + "conf" + File.separator + "tomcat-users.xml"; ((SimpleUserDatabaseRealm) realm).createDatabase(filedir); // highlight line.设置tomcat-users.xml 的文件路径 以载入其内容到内存进行身份验证工作;context.setRealm(realm);// highlight line.context.addConstraint(constraint);// highlight line.context.setLoginConfig(loginConfig);// highlight line.connector.setContainer(context);try {connector.initialize();((Lifecycle) connector).start();((Lifecycle) context).start();// make the application wait until we press a key.System.in.read();((Lifecycle) context).stop();}catch (Exception e) {e.printStackTrace();}}}
// tomcat-users.xml 的源码如下:
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users><role rolename="tomcat"/><role rolename="role1"/><role rolename="manager"/><role rolename="admin"/><user username="tomcat" password="tomcat" roles="tomcat"/><user username="role1" password="tomcat" roles="role1"/><user username="both" password="tomcat" roles="tomcat,role1"/><user username="admin" password="admin" roles="admin,manager"/>
</tomcat-users>
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;lib/catalina-5.5.4.jar;lib/naming-common.
jar;lib/commons-collections.jar;lib/naming-resources.jar;lib/;lib/catalina.jar;lib\commons-digester.jar;lib\commons-logging.jar;E:\bench-cluster\cloud
-data-preprocess\HowTomcatWorks\webroot com/tomcat/chapter10/startup/Bootstrap2
HttpConnector Opening server socket on all host IP addresses
HttpConnector[8080] Starting background thread
WebappLoader[/myApp]: Deploying class repositories to work directory E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src\work\_\_\myApp
Starting Wrapper Primitive
Starting Wrapper Modern
Added authenticator valve to Context
StandardManager[/myApp]: Seeding random number generator class java.security.SecureRandom
StandardManager[/myApp]: Seeding of random number generator has been completed
StandardManager[/myApp]: IOException while loading persisted sessions: java.io.EOFException // 这是从文件中加载 session对象到内存,由于没有相关文件,所以加载失败,抛出异常,但这不会影响我们访问servlet,大家不要惊慌;
java.io.EOFExceptionat java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)at java.io.ObjectInputStream.readStreamHeader(Unknown Source)at java.io.ObjectInputStream.<init>(Unknown Source)at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:103)at org.apache.catalina.session.StandardManager.load(StandardManager.java:408)at org.apache.catalina.session.StandardManager.start(StandardManager.java:655)at org.apache.catalina.core.StandardContext.start(StandardContext.java:3570)at com.tomcat.chapter10.startup.Bootstrap2.main(Bootstrap2.java:84)
StandardManager[/myApp]: Exception loading sessions from persistent storage
java.io.EOFException at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)at java.io.ObjectInputStream.readStreamHeader(Unknown Source)at java.io.ObjectInputStream.<init>(Unknown Source)at org.apache.catalina.util.CustomObjectInputStream.<init>(CustomObjectInputStream.java:103)at org.apache.catalina.session.StandardManager.load(StandardManager.java:408)at org.apache.catalina.session.StandardManager.start(StandardManager.java:655)at org.apache.catalina.core.StandardContext.start(StandardContext.java:3570)at com.tomcat.chapter10.startup.Bootstrap2.main(Bootstrap2.java:84)
ModernServlet -- init
tomcat(10)安全性相关推荐
- 应用发布服务器_Apache Tomcat 10.0.0-M1 发布,开源 Web 应用服务器
Apache Tomcat 10.0.0 发布了第一个里程碑版本.Tomcat 是 Java Servlet.JavaServer Pages.Java 表达式语言和 Java WebSocket 技 ...
- javaWeb 中Tomcat 10 jsp文件内置对象不能正常使用的问题(已解决)
在这段时间学习javaweb时,因为是自己找的视频,下载了最新版本的Tomcat,Tomcat 10 ,然后就发现了很多问题,Tomcat 10 跟之前的版本 有很大的区别,以至于,10以下的版本的文 ...
- Tomcat 10 调用Servlet提示 500 实例化Servlet类异常
最近在做Java EE的项目时把Tomcat服务器更新到了10.0.21,然后在测试调用Servlet中出现了如下异常 注意看红框框里面的内容 通过对错误信息的解读我们不难发现Tomcat 10版本的 ...
- Tomcat【环境搭建 02】Web端403 Access Denied You are not authorized to view this page解决方法(Tomcat 10.2.12 版本)
1. 问题说明 启动Tomcat之后,我们常常是要打开Web端进行验证,其实Web端的功还有很多,但是有一些管理页面权限不足: 我们点击 Manager Status 或 Manager App 链接 ...
- psa name_Windows 10安全性PSA:启用自动商店更新
psa name Microsoft sometimes distributes important security updates through the Microsoft Store. Tha ...
- tomcat(12)org.apache.catalina.core.StandardContext源码剖析
[0]README 0)本文部分文字描述转自 "how tomcat works",旨在学习 "tomcat(12)StandardContext源码剖析" 的 ...
- tomcat(11)org.apache.catalina.core.StandardWrapper源码剖析
[0]README 0.0)本文部分文字描述转自 "how tomcat works",旨在学习 "tomcat(11)StandardWrapper源码剖析" ...
- Apache Tomcat 安全性指南
Apache Tomcat 在安全性方面拥有令人印象深刻的记录.根据官方 Apache Tomcat Wiki Pages,从未报告过由于对任何 Apache Tomcat 实例的恶意攻击而导致实际损 ...
- Tomcat 又爆出高危漏洞!Tomcat 8.5~10 中招…
作者 | 栈长 来源 | Java技术栈 开源界最近很热闹啊,各个主流软件或框架漏洞频发,比如像 Struts2.FastJSON.Dubbo.Redis.Tomcat 等都存在各种各样的漏洞. 不要 ...
最新文章
- LIS ZOJ - 4028
- 判断一个请求是否为Ajax请求
- 矩阵的直接LU分解法
- android横竖屏切换不刷新,关于Android中使用BottomNavigationView切换横屏导致返回主页的问题...
- 解决Cygwin编译cocos2dx 遇到的 error: 'UINT64_C' was not declared in this scope 问题
- 这8种SQL用法,我用错吗?求答案!!!
- [Redis6]key键操作
- java 无锁框架_高性能无锁并发框架 Disruptor,太强了!
- 详述一条SQL引发的高CPU故障处理过程
- 关于MATLAB实现的数字信号处理(二)
- Exchange 2010与Exchange Online混合部署PART 3:混合准备
- lm358 pdf应用电路资料及引脚图
- bootstarp怎么使盒子到最右边_基于Android血统的NAS+盒子共生体——零刻GS-king X 开箱初体验...
- 【Pytorch】测试单张图片(调用transforms)
- win7连接远程桌面时出现黑屏的解决方法(亲测有效)——终于找到解决办法了
- 【程序设计训练】棋盘
- Ubuntu14.04安装有道词典
- 2020年总结 - 不纠结当下,不忧虑未来
- Shell脚本:循环for / while / until
- 在线查询IP及IP信息
热门文章
- Pool construction UVA - 1515 最小割模型
- [牛客] Tree-换根dp(预防加法取模导致等0)
- 【学习笔记】WQS二分详解及常见理解误区解释
- NOIP2018洛谷P5021:修建赛道
- 51nod1227-平均最小公倍数【杜教筛,欧拉函数】
- CF1039D-You Are Given a Tree【根号分治,贪心】
- P4780-Phi的反函数【dfs】
- P4655-[CEOI2017]Building Bridges【斜率优化dp,CDQ分治】
- 【KMP】周期长度和(luogu 3435/ybtoj KMP-3)
- 2、oracle数据库的用户和权限