`

Using JAAS with Tomcat

阅读更多

back to index

Using JAAS with Tomcat

Although it is possible to use JAAS within Tomcat as an authentication mechanism (JAASRealm), the flexibility of the JAAS framework is lost once the user is authenticated. This is because the principals are used to denote the concepts of "user" and "role", and are no longer available in the security context in which the webapp is executed. The result of the authentication is available only through request.getRemoteUser() and request.isUserInRole().

This reduces the JAAS framework for authorization purposes to a simple user/role system that loses its connection with the Java Security Policy. This tutorial's purpose is to put a full-blown JAAS authorisation implementation in place, using a few tricks to deal with some of Tomcat's idiosyncrasies.

Basic Design

The goal of the exercise is to be able to wrap the execution of our servlets/jsps in our own JAAS implementation, which allows us to enforce access control with a simple call in our code to AccessController.checkPermission(MyOwnPermission). We achieve this by wrapping each request in a security filter. This is configured in our web.xml. Most of this is covered in widely available JAAS tutorials on the net, so we only have some code fragments here.

web.xml

  <filter>
    <filter-name>SecurityFilter</filter-name>
    <filter-class>security.SecurityFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>SecurityFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!-- Define a Security Constraint on this Application -->
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Entire Application</web-resource-name>
      <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>authenticateduser</role-name>
    </auth-constraint>
  </security-constraint>

  <!-- Define the Login Configuration for this Application -->
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>My Realm</realm-name>
  </login-config>

login.conf

To start tomcat in security mode we call startup.sh with the -security flag. Furthermore we need to call our login module by setting $JVM_OPTS to something like -Djava.security.auth.login.config=/usr/local/tomcat/webapps/jaastest/WEB-INF/login.conf

Jaas {
    security.HttpLoginModule required debug=true;
};

HttpLoginModule

public class HttpLoginModule implements LoginModule {
...
    public boolean commit() throws LoginException {
        if (debug)
        	System.err.println("HttpLoginModule: Commit");

        if (!succeeded) {
            // We didn't authenticate the user, but someone else did.
            // Clean up our state, but don't add our principal to
            // the subject
            userName = null;
            return false;
        }
        
        assignPrincipal(new UserPrincipal(userName));

	//Based on the username, we can assign principals here
        //Some examples for test....
        assignPrincipal(new RolePrincipal("authenticateduser")); 
        assignPrincipal(new RolePrincipal("administrator")); 
        assignPrincipal(new CustomPrincipal("company1")); 
       
        // Clean up our internal state
        userName = null;
        commitSucceeded = true;
        return true;
    }

    private void assignPrincipal(Principal p)
    {
	// Make sure we dont add duplicate principals
	if (!subject.getPrincipals().contains(p)) {
	    subject.getPrincipals().add(p);
	}
	    
	if(debug) System.out.println("Assigned principal "+p.getName()+" of type "+ p.getClass().getName() +" to user "+userName);
    }

HttpAuthCallbackHandler

We have Tomcat or Apache do the authentication for us, so we just rely on request.getRemoteUser() to tell us the user name. Feel free to extend...

class HttpAuthCallbackHandler implements CallbackHandler {

  private String userName;

  public HttpAuthCallbackHandler (HttpServletRequest request) {
    userName = request.getRemoteUser();
    System.out.println("Remote user is: " + request.getRemoteUser());
  }

  public void handle(Callback[] cb) throws IOException, UnsupportedCallbackException {
	
    for (int i = 0; i < cb.length; i++) {
      if (cb[i] instanceof NameCallback) {
        NameCallback nc = (NameCallback) cb[i];
        nc.setName(userName);
      } else throw new
        UnsupportedCallbackException(cb[i], "HttpAuthCallbackHandler");
    }
  }
}

CustomPolicy

We install a Policy that adds Custom Permissions to the existing PermissionCollection

public class CustomPolicy extends Policy {

	private Policy deferredPolicy;
	
	public CustomPolicy(Policy p) {
		deferredPolicy = p;
	}

	public PermissionCollection getPermissions(CodeSource cs) {
		PermissionCollection pc = deferredPolicy.getPermissions(cs);
		System.out.println("getPermissions was called for codesource");
		return pc;
	}

	public PermissionCollection getPermissions(ProtectionDomain domain) {

		PermissionCollection pc = deferredPolicy.getPermissions(domain);
		System.out.println("getPermissions was called for domain");
		Principal[] principals = domain.getPrincipals();
		System.out.println("retrieved " + principals.length + " principals");
		
		for (int i=0; i< principals.length; i++) {
			
			Principal p = principals[i];
			System.out.println("This is principal" + p);
			CustomPermission[] pms = null;
			if (p instanceof CustomPrincipal ) {
				
				System.out.println(p.getName()  + " is a CustomPrincipal");
				
				// Get the permissions belonging to the principal here.
				// Here we just add an example permission
				CustomPermission[] test =  { new CustomPermission("AccessToCompany1Building") };
				pms = test;
			} else {
			  System.out.println(p.getName()  + " is not a CustomPrincipal");
			}

			// Nothing to do
			if (pms == null)  continue;

			for(int j=0; j< pms.length; j++) {
				System.out.println("Adding permission = " + pms[j]);
				pc.add(pms[j]);
			}

		}

		System.out.println(pc);
		return pc;
	}

	public void refresh() {
		deferredPolicy.refresh();
	}
}

SecurityFilter

This is the core of our solution. We install our CustomPolicy here (note that this is definitely not redeployment-safe!). Note that we the feed our authenticated subject into the session. Tomcat then uses this subject when calling your servlets. This is the trick that makes the whole thing work; without it, the Subject is lost.

public class SecurityFilter implements Filter {
	
	public void init(FilterConfig config) throws ServletException {
		Policy orgPolicy = Policy.getPolicy();

		if (orgPolicy instanceof CustomPolicy) {
			// we already did this once upon a time..
			System.out.println("Policy is a CustomPolicy,we already did this once upon a time");
		} else {
			Policy.setPolicy(new CustomPolicy(orgPolicy));
			System.out.println("Policy is not a CustomPolicy");
		}
	}
	
	public void destroy() {
		//config = null;
	}
	
	public void doFilter(ServletRequest sreq, ServletResponse sres,
						 FilterChain chain) throws IOException, ServletException {
		System.out.println("Starting SecurityFilter.doFilter");
		
		HttpServletResponse response = (HttpServletResponse)sres;
		HttpServletRequest request = (HttpServletRequest)sreq;
		
		HttpSession session = request.getSession(true);
		Subject subject = (Subject)session.getAttribute("javax.security.auth.subject");
		
		if (subject == null) {
			subject = new Subject();
		}
		
		session.setAttribute("javax.security.auth.subject", subject);
		
		LoginContext lc = null;
		try {
			lc = new LoginContext("Jaas", subject, new HttpAuthCallbackHandler(request));
			System.out.println("established new logincontext");
		} catch (LoginException le) {
			le.printStackTrace();
			response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
			return;
		} 

		try {
			lc.login();
			// if we return with no exception, authentication succeeded
		} catch (Exception e) {
			System.out.println("Login failed: " + e);
			response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
			return;
		}
		
		try {
			System.out.println("Subject is " + lc.getSubject());
			chain.doFilter(request, response);
		} catch(SecurityException se) {
			response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
		}
	}
}

Testing it out

If you want to test your subject, a simple JSP like the one below is a great help

<%@page import="java.security.*" %>
<%@page import="javax.security.auth.*" %>
<html>
<h1>Hello World!</h1>

<pre>
<% Subject subject = Subject.getSubject(AccessController.getContext()); %> 


<b>Subject</b> = <%= subject %>

-----------------------------------------------

<b>RemoteUser</b> = <%= request.getRemoteUser() %>

-----------------------------------------------

<%
	out.print("Is user in role \"authenticateduser\"?: ");
	if (request.isUserInRole("authenticateduser")) {
		out.println("yes");
	} else {
		out.println("no");
	}
%> 

-----------------------------------------------

<b>Session Contents</b>
<% 
	java.util.Enumeration atts = session.getAttributeNames();
	while (atts.hasMoreElements()) {
		String elem = (String)atts.nextElement();
		out.println(elem + " -> " + session.getAttribute(elem));
		out.println( );
	}
%>


</pre>

</html>

Copyright (c) 2004 Michiel Toneman : rot13(zvpuvry@xbcm.bet)
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. The full text of the license is found at: http://www.gnu.org/copyleft/fdl.html

分享到:
评论

相关推荐

    JAAS认证(mac版tomcat)

    **Java Authentication and Authorization Service (JAAS) 认证在Mac版Tomcat中的应用** Java Authentication and Authorization Service (JAAS) 是Java平台的核心组件,用于提供安全的用户认证和权限管理。在Mac版...

    JBOSS security using JAAS

    【JBOS安全与JAAS详解】 JBOS(Java EE Application Server)是Red Hat公司推出的开源应用服务器,它为开发和部署企业级Java应用程序提供了一个强大而灵活的平台。在JBOS中,安全性是至关重要的一个方面,因为它...

    tomcat_jaas_demo

    tomcat下jaas配置实例(文档有不完善的地方) 1、需要修改 bin\startup.bat(根据自己的环境修改) SET JAVA_HOME=C:\programs\Java\jdk1.8.0_211 SET TOMCAT_HOME=C:\programs\apache-tomcat-5.5.20 2、需要修改 bin...

    Using JAAS in Java EE and SOA Environments

    ### 使用JAAS在Java EE与SOA环境中的关键知识点 #### 一、JAAS简介及其历史背景 **Java Authentication and Authorization Service(JAAS)** 是Java平台提供的一个强大的安全框架,用于实现用户身份验证和授权...

    jaas详细配置精讲

    综上所述,JAAS在Tomcat中的配置涉及到多个文件和组件,包括自定义LoginModule、JAAS配置文件、Tomcat的`server.xml`和`tomcat-users.xml`,以及Web应用的`web.xml`。理解并熟练掌握这些配置,对于构建安全的J2EE...

    java JAAS登陆验证

    在Java Web应用中,如Tomcat、Jetty等,JAAS可以与Servlet容器进行集成,实现Web应用的安全管理。容器通常有自己的安全配置,但可以通过配置使其与JAAS交互,从而利用JAAS的认证和授权能力。 **总结** Java JAAS为...

    jaas.jar jaas.jar

    jaas.jar jaas.jar jaas.jar

    JAAS灵活的Java安全机制

    Java Authentication and Authorization Service (JAAS) 是Java平台中用于实现用户认证和权限授权的一个核心组件。它为开发者提供了一种灵活的方式来实现安全控制,确保只有经过验证和授权的用户能够访问敏感资源或...

    JAAS简介及实例

    Java Authentication and Authorization Service (JAAS) 是Java平台提供的一种安全框架,用于实现用户身份验证和权限管理。这个框架使得开发者可以轻松地在Java应用程序中集成安全性,而不必深入理解底层的复杂安全...

    tomcat5/tomcat5.5安装包

    【标题】"Tomcat5/tomcat5.5安装包" 涵盖了两个不同版本的Apache Tomcat服务器,即Tomcat 5.0和Tomcat 5.5。Tomcat是一个开源的、免费的应用服务器,主要用于部署和运行Java Servlets和JavaServer Pages(JSP)。它...

    JAAS认证与授权教程

    `i`和`j-sec2`可能是文档或示例项目的部分,它们可能提供了关于如何配置和使用JAAS的详细指南,或者展示了如何将JAAS集成到具体的应用服务器如Tomcat或JBoss中的实例。 学习JAAS对于任何希望构建安全Java应用程序的...

    Tomcat7.0 tomcat最新版本

    4. **增强的安全性**:Tomcat 7.0加强了安全特性,提供了更强的身份验证和授权机制,如集成Spring Security和JAAS,以及对SSL/TLS的改进支持,帮助保护Web应用程序免受攻击。 5. **更好的管理工具**:Tomcat 7.0...

    JAAS in Web Applications

    - **Servlet容器支持**:大多数现代Servlet容器如Tomcat、Jetty都内置了对JAAS的支持,可以通过容器配置进行集成。 - **Web.xml配置**:在Web应用的部署描述符中,可以配置安全管理器,指定使用哪个JAAS Realm进行...

    jaas规范实现代码

    Java Authentication and Authorization Service (JAAS) 是 Java 平台中用于安全管理的重要组件,它提供了一种框架,使得应用程序可以进行用户身份验证和权限控制。在本文中,我们将深入探讨 JAAS 的核心概念、工作...

    JAAS简介及示例代码

    Java Authentication and Authorization Service (JAAS) 是Java平台中用于安全性的核心组件,它为开发者提供了一种机制来处理用户身份验证和权限控制。这个服务允许应用程序执行基于角色的安全性,这意味着用户的...

    Tomcat 接口文档 API

    10. **Security**: Tomcat提供了丰富的安全功能,如角色基的安全约束、SSL/TLS支持、JAAS集成等。开发者可以使用Realm组件进行身份验证,定义AccessControlList来控制访问权限。 在学习Tomcat API时,阅读官方文档...

    tomcat8和tomcat7

    5. **安全增强**:支持JAAS集成,增强了安全管理,如角色认证和授权。 **Tomcat8** Tomcat8于2013年发布,主要支持Java EE 7规范,包括Servlet 3.1、JSP 2.3和EL 3.0等,相比Tomcat7有以下改进: 1. **Servlet 3.1...

    tomcat7源码下载

    它支持JAAS(Java Authentication and Authorization Service),可以根据需要配置不同的 Realm 来实现用户认证。 六、Tomcat7性能优化 优化Tomcat7涉及多个方面,包括调整JVM参数、减少上下文重启、优化连接器...

    tomcat压缩包

    5. **安全性**:Tomcat提供了多种安全机制,包括角色基础的访问控制(RBAC)、SSL/TLS支持、Jaas集成等,确保应用的安全运行。 6. **配置文件**:主要的配置文件有`server.xml`(定义服务器的全局配置)、`web.xml`...

Global site tag (gtag.js) - Google Analytics