1. 程式人生 > >How Tomcat works 10: Security類

How Tomcat works 10: Security類

    1. 概述:     WebApp的資源的訪問限制可以通過web.xml檔案來支撐。Servlet容器可以通過叫做Authenticator valve類來支援。Authenticator valve會呼叫context's realms的authenticate方法校驗user     2. Realm類     (1)一個Realm通常附屬於一個context, 一個container只能有一個realm【container.setRealm(realm)】     (2)預設下,Tomcat的預設認證資訊儲存在tomcat-users.xml中。當然也可以使用別的認證資源,如database     (3)Realm介面包含四個overload方法       

		public interface Realm {
			public Principal authenticate(String username, String credentials);
			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 cters[]);
			
			public boolean hasRole(Principal principal, String role);
		}

         3. GenericPrincipal:     (1)是Principal介面的實現類         

		public class GenericPrincipal implements Principal {
		
			protected Realm realm;
			private String name;
			private String password;
			private String[] roles;
			
			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);
					}
				}
			}
			public boolean hasRole(String role) {
				if("*".equals(role)) {
					return true;
				}
				if(role == null) {
					return false;
				}
				return (Arrays.binarySearch(roles, role)>=0);
			}
			@Override
			public String getName() {		
				return name;
			}
		
		}

         4. LoginConfig類     (1)包含了realm name和authentication方法authentication name必須是其中之一:BASIC,DIGEST,FORM,CLIENT-CERT     (2)部署過程中,Tomcat啟動時讀取web.xml檔案,若包含了login-config元素, tomcat將建立以惡LoginConfig物件     5. Authenticator介面     (1)代表一個認證介面,沒有任何方法,僅僅是一個標記     (2)UML          6. Bootstrap:     在啟動過程中,使用context.getLoginConfig()->然後使用反射查詢相應的authenticator,新增對應的valve到pipeline    

	private synchronized void authenticatorConfig() {
			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) {
	
			}
		}