当前位置: 首页 > news >正文

网站设计南方企业网南充网络推广

网站设计南方企业网,南充网络推广,广州商务网站建设,游戏网站代理【0】README0.0#xff09;本文部分描述转自“深入剖析tomcat”#xff0c;旨在学习 tomcat(10)安全性 的基本知识#xff1b;0.1#xff09;servlet技术支持通过配置部署描述器#xff08;web.xml#xff09;文件来对这些内容进行访问控制#xff1b;#xff08;干货—…【0】README0.0本文部分描述转自“深入剖析tomcat”旨在学习 tomcat(10)安全性 的基本知识0.1servlet技术支持通过配置部署描述器web.xml文件来对这些内容进行访问控制干货——web.xml又名 配置部署描述器0.2servlet容器是通过一个名为验证器的阀来支持安全限制的该阀会被添加到Context的管道中并且会先于 Wrapper阀的调用干货——引入了验证器阀0.3调用验证器阀case1用户输入了正确的username 和 pwd验证器阀会调用后续的阀 case2用户输入错误验证器阀会返回不会调用后续的阀 0.4验证器阀会调用Context容器的领域对象的 authenticate()方法传入用户输入的username 和 pwd来对用户进行身份验证干货——引入了领域对象0.5for source code , please visit  https://github.com/pacosonTang/HowTomcatWorks/tree/master/chapter10【1】领域Realm用来对用户进行身份验证的组件1intro to 领域对象该对象用来对用户进行身份验证的组件1.1领域对象通常与一个Context容器相关联setRealm方法来将领域对象与Context容器相关联1.2领域对象如何验证用户身份呢它保存了所有有效用户的username 和 pwd对或者它会访问存储这些dta的存储器在tomcat中有效info 存储在tomcat-user.xml文件中现在你知道tomcat-user.xml文件的作用是什么了吧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);}2领域对象是 org.apache.catalina.Realm 接口的实例该接口的 authenticate方法最为重要方法签名如下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类图如下3.1default case会使用 MemoryRealm 类的实例作为验证用的领域对象干货——MemoryRealm 类的实例作为验证默认用的领域对象3.2当第一次调用 MemoryRealm实例时它会读取 tomcat-user.xml 文档的内容Attention在catalina中 验证器阀会调用附加到其中的领域对象的 authenticate()方法来验证用户身份【2】GenericPrincipal类实现接口 java.security.Principalpublic class GenericPrincipal implements Principal { //org.apache.catalina.realm.GenericPrincipal代表一个用户封装了username,password,role,realmpublic 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());} }1intro to GenericPrincipal1.1GenericPrincipal实例必须始终与一个领域对象相关联1.2GenericPrincipal实例必须有一个用户名和密码对且该用户名和密码对所对应的角色列表是可选的1.3调用hasRole()方法传入1个字符串形式的角色名来检查该主体对象是否拥有该指定角色【3】LoginConfig类org.apache.catalina.deploy.LoginConfig1intro to LoginConfig登录配置是 LoginConfig类的实例其中包含一个领域对象的名字其实例封装了领域对象名和所要使用的身份验证方法getRealmName()方法用来获取领域对象的名字2getAuthName()方法获取身份验证方法的名字名字范围是BASIC, DIGEST, FORM 或 CLIENT-CERT3实际部署中tomcat在启动时需要读取 web.xml 文件的内容step1如果web.xml 文件包含 login-config 元素的配置则tomcat会创建一个 LoginConfig对象并设置其相应属性干货——tomcat创建一个 LoginConfig对象的条件 step2验证器阀会调用 LoginConfig.getRealmName() 获取领域对象名并将领域对象名发送到 browser显示在登录对话框中 case2.1如果getReamlName()方法的返回值是null则会将服务器名和相应端口发送给 browser 看个荔枝下图展示了 XP 系统中使用 IE6 进行基本身份验证的登录对话框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());} }【4】Authenticator接口org.apache.catalina.Authenticator1intro to Authenticator验证器接口只是起到了标记作用这样其他组件就可以使用 instanceof 来检查某个组件是否是一个验证器干货——验证器接口只是起到了标记作用2org.apache.catalina.Authenticator的UML类图如下对上图的分析AnalysisA1BasicAuthenticator用来支持基本的身份验证 A2FormAuthenticator提供了基于表单的身份验证 A3DigestAuthenticator提供了基于信息摘要的身份验证 A4SSLAuthenticator用于对SSL 进行身份验证 A5当tomcat 用户没有指定验证方法名时NonLoginAuthenticator类用于对来访者的身份进行验证。NonLoginAuthenticator类实现的验证器只会检查安全限制而不会涉及用户身份的验证 AttentionA1验证器的重要工作是对用户进行身份验证干货——验证器的重要工作是对用户进行身份验证 A2当看到 AuthenticatorBase.invoke() 方法调用 authenticate() 抽象方法时后者的实现依赖于子类而authenticate()方法会使用基本身份验证来验证用户的身份信息 public class BasicAuthenticator extends AuthenticatorBase { span stylefont-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);} }【5】安装验证器阀1一个Context实例只能有一个 LoginConfig实例和利用一个验证类的实现2也就是说在部署描述器tomcat-user.xml中login-config元素只出现一次login-config元素包含一个auth-method 元素来指定身份验证方法3使用AuthenticatorBase类的哪个子类作为Context实例中的验证器阀依赖于 部署描述器中 auth-method元素4下表给出了 auth-method 元素的值和对应的验证器的类名对上表的分析AnalysisA1若没有设置 auth-method元素则 LoginConfig 对象 的 atuh-method属性的值默认为 NONE使用 NonLoginAuthenticator 进行安全验证 A2由于使用的验证器类是在运行时才确定的故该类是动态载入的 A3StandardContext容器使用 org.apahce.catalina.startup.ContextConfig类来对 StandardContext 实例的属性进行设置这些设置包括 实例化一个验证器类并将该实例与Context实例相关联 【6】应用程序【6.1】SimpleContextConfig类 1intropublic class SimpleContextConfig implements LifecycleListener ,仅仅是个监听器而已不要惊慌2SimpleContextConfig.authenticatorConfig()方法该方法实例化BasicAuthenticator类并将其作为阀添加到 StandardContext实例的管道中干货——注意其实例化BasicAuthenticator类的技巧// 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) {}3下面对SimpleContextConfig.authenticatorConfig()方法的调用过程 进行 detailed analysis: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) {}} 【6.2】SimpleRealm类简单领域对象领域对象是用来对用户身份验证的组件1SimpleRealm类实现了Realm接口2在构造函数中它调用了createUserDatabase()方法创建两个用户并将这两个用户添加到users中干货——创建用户并设置角色功能同tomcat-users.xml 的内容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();} }3再看其 authenticate() 验证方法该方法由验证器调用若用户提供的用户名或密码无效则返回null否则返回一个代表该用户的 Principal对象public Principal authenticate(String username, String credentials) {System.out.println(SimpleRealm.authenticate());if (usernamenull || credentialsnull)return null;User user getUser(username, credentials);if (usernull)return null;return new GenericPrincipal(this, user.username, user.password, user.getRoles()); // highlight line.}public class GenericPrincipal implements Principal { // 该类封装了用户的一些信息如usernamepassrolerealm等infopublic 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());} }【6.3】SimpleUserDatabaseRealm它是SimpleRealm的变体类 1introSimpleUserDatabaseRealm类表示一个复杂一点的领域对象它并不将用户列表存储到对象自身中。相反它会读取conf 目录下的 tomcat-users.xml文件将内容载入内存然后依据该列表进行身份验证。干货——读取conf 目录下的 tomcat-users.xml文件将内容载入内存然后依据该列表进行身份验证// tomcat-users.xml 的源码如下 ?xml version1.0 encodingutf-8? tomcat-usersrole rolenametomcat/role rolenamerole1/role rolenamemanager/role rolenameadmin/user usernametomcat passwordtomcat rolestomcat/user usernamerole1 passwordtomcat rolesrole1/user usernameboth passwordtomcat rolestomcat,role1/user usernameadmin passwordadmin rolesadmin,manager/ /tomcat-users2在实例化SimpleUserDatabaseRealm类后 必须调用它的 createDatabase()方法并向包含用户列表的xml 文档传递路径。// 以下代码是 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;} } } }【6.4】Bootstrap1.java应用程序11Bootstrap1.java 的源代码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.// StandardContexts 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 dont 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// wont 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();}} }对以上代码的分析AnalysisA1创建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实例。。。。。。。 Supplement-补充 S1本文还是给出了如何验证用户合法性的调用过程 S2结合S1中的第一张图本文关联性地给出了 server处理http 客户端请求的调用过程 2打印结果pre namecode classjavaE:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\srcjava -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【6.5】Bootstrap2.java应用程序2 1Bootstrap2的源程序和 Bootstrap1.java 的源程序差不多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.// StandardContexts 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 dont 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// wont 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 version1.0 encodingutf-8? tomcat-usersrole rolenametomcat/role rolenamerole1/role rolenamemanager/role rolenameadmin/user usernametomcat passwordtomcat rolestomcat/user usernamerole1 passwordtomcat rolesrole1/user usernameboth passwordtomcat rolestomcat,role1/user usernameadmin passwordadmin rolesadmin,manager/ /tomcat-users2它们唯一的差别在于以不同的方式获取用户列表Bootstrap1.java 是在对象中创建用户列表保存在 ArrayList中而Bootstrap2.java 通过读取conf目录下的 tomcat-users.xml文件将其内容载入到内存中干货——Bootstrap1.java 和 Bootstrap2.java的唯一差别干货——你现在知道 tomcat-users.xml 的作用了以及如何利用它进行安全性访问的限制E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\srcjava -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 -- init3打印结果
http://www.zqtcl.cn/news/813076/

相关文章:

  • 邢台建设企业网站房地产宣传推广方案
  • 建设机械网站案例分析餐饮vi设计开题报告范文
  • 做本地生活网站深圳建设工程信息网站
  • C2C电商网站做博客的网站有哪些
  • 住房和城乡建设部网站 事故安微省建设厅田网站
  • 百度一下你就知道官页淘宝seo搜索引擎优化
  • 网站平台维护phpwind做的网站
  • 网站怎么做移动适配怎么样才算是一个网站页面
  • 做pc端网站策划百度网站建立
  • 高级网站开发技术青岛网站建设方案服务
  • 深圳公司网站建设设房地产网址大全
  • 怎么里ip做网站女生学广告学后悔死了
  • 做西餐网站wordpress 作者栏
  • 创建了网站安卓做视频网站
  • asp自助建站系统房地产楼盘微信网站建设营销方案
  • 网站建设公司发展方向及趋势低代码小程序开发平台
  • 临沂网站建设企业响应式网站首页
  • 福州网上商城网站建设wordpress登录界面logo
  • 子目录网站wordpress无中断音乐插件
  • 网站开发算是研发支出吗淘宝客网站建设的策略
  • 如果在工商局网站上做股权质押刷推广链接的网站
  • 保定建站公司模板wordpress 华为云
  • 好的网页设计网站推荐开发定制软件公司
  • 深圳做网站设计多媒体网站开发
  • 什么是网站组件高端网站设计高端网站制作
  • 网易网站建设深圳专业营销网站制作
  • 有口碑的佛山网站建设东莞网约车资格证官网登录入口
  • 网站建设合同 保密条款wordpress网站手机端
  • 汕头建站费用wordpress转cms
  • 全美网站开发PHP 网站开发 重点知识