J2EE 中的安全第二部分 - J2EE安全应用

机器学习项目(四)疫情期间网民情绪识别 (一) 疫情期间网民情绪识别 赛题背景 2019新型冠状病毒(2019-nCoV)感染的肺炎疫情发生对人们生活生产的方方面面产生了重要影响,并引发国内舆论的广泛关注,众多网民参与疫情相关话题的讨论。为了帮助政府掌握真实社会舆论情况,科学高效地做好防控宣传和舆情引导工作,本赛题针对疫情相关话题开展网民情绪识别的任务。 数据介绍 训练集 10万条 无标记样本90万条 测试集1万条 数据集依据与“新冠肺炎”相关... 阅读详情
http://www-900.ibm.com/developerWorks/cn/java/l-j2eesecurity2/index.shtml

在本系列文章的第一部分作者介绍了j2ee的安全概念、验证模型和授权模型,这部分更偏重于理论的介绍。本文的第二部分作者将通过具体的例子向读者展示如何在开发中应用j2ee提供的安全服务。本部分的重点在于应用与实践。

注释:本文的目的是介绍如何应用j2ee提供的安全服务,而并不针对特定的产品。因此作者选择sun的 j2ee参考实现(j2sdkee)作为演示平台。因为j2sdkee是完全遵照j2ee规范开发的,虽然它不像IBM WebSphere 、BEA WebLogic等j2ee产品那么产品化和商业化,但它绝对是学习j2ee的理想平台。你可以通过http://java.sun.com/j2ee/ 获取sun 的j2ee参考实现的最新版本。本文选择的是Sun的j2sdkee1.3.1。

本文将包括以下内容:

  1. 一个采用HTTP基本的验证的例子
  2. 一个采用基于表单的验证的例子
  3. 一个ejb方法授权的例子
  4. 一个可编程安全性和传播调用者身份标识的例子

采用HTTP基本的验证的例子

http基本验证是Web客户端验证的一种,它和系统的授权机制一起控制受保护资源的访问。

步骤:

1. 创建一个j2ee应用

在应用程序部署工具的File菜单选中New子菜单中的Application菜单项(见图1)。会弹出新建应用程序对话框。填写应用程序文件名和应用程序显示名(见图2)。

图1
图1

图2
图2

2. 创建一个web组件

在应用程序部署工具的File菜单选中New子菜单中的Web Compent菜单项,会弹出新建web组件向导对话框(见图3)。选择Create New WAR File in Application,在下拉框中选择步骤1创建的应用test,在WAR Display Name框中填写WebAppTest.点击Content栏中的Eidt按钮选择此Web组件包含的文件。在这个例子中只有一个webtest.jsp文件。然后点击Next,进入下一个对话框(见图4)。由于我们的web组件是一个jsp文件,因此在组件类型中选择JSP。然后一直按Next直到结束。此时我们已经创建了一个只包含一个jsp文件的web组件。接下来是配置安全属性的步骤。

图3
图3

图4
图4

3. 配置安全属性

3.1创建安全角色

在部署工具的左导航栏中点中步骤2创建的web组件WebAppTest,在右边的属性页中选择Roles属性页(见图5)。点击Add按钮,在Name栏中填写安全角色名user,Description栏填写描述信息。安全角色代表具有相同安全权限用户的集合。

图5
图5

3.2 配置安全策略

创建了安全角色后,应该对安全角色配置相应的安全策略。点击Security属性页(见图6)。

图6
图6

首先选择你想用的验证方式,从User Authentication Method下拉框中选择Basic。这意味着你将通过基本的HTTP验证方式验证用户。下面我们进行web资源的授权。点击Security Constraint栏中的Add按钮添加一条安全约束,约束名可以自定。接下来对创建好的约束添加Web资源。首先在Web Resource Collections中添加资源集合,然后选取资源集合包含的资源。此例中WRCollection资源集合中包含webtest.jsp文件,也可以包含各种属于这个web组件的文件。接下来选择哪些web操作要收到约束,j2sdkee1.3.1中只包含两种操作(GET和POST),不同的产品支持的操作有所不同,在开发是应结合具体产品提供的操作来选取。现在应该指定安全角色了,点击Authorized Roles栏中的Edit按钮,会弹出安全角色列表对话框,从中选取已定义的安全角色。本例中选择user。至此安全策略已经配置完毕,下面的步骤是将实际环境中的用户和用户组映射与安全角色进行映射。

4. 映射

在左导航栏中选中应用程序test在右边选择Security属性页(见图7),在Role Name Reference栏中选中user,点击正下方的Add按钮,会弹出用户和用户组列表对话框,从中选择要映射成安全角色user的用户或组。此例中我们将用户j2ee映射为安全角色user。这样用户J2ee将具有为安全角色user分配的访问授权。

图7
图7

5. 部署应用

选中Web Context属性页,在Context Root文本框中填写test,右键点击左导航栏的应用test,在弹出菜单中选择deploy完成应用程序的发布。至此我们完成了第一个例子的全部步骤。

部署描述文件

这个例子使用了说明性的安全服务,因此我们不需要编写任何的安全相关的代码,而是完全通过配置组件的部署描述文件来实现的。下面是这个web组件的部署描述文件。


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
'-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN'
'http://java.sun.com/dtd/web-app_2_3.dtd'>
<web-app>
  <display-name>WebAppTest</display-name>     //Web组件名称
  <servlet>
    <servlet-name>webtest</servlet-name>
    <display-name>webtest</display-name>
    <jsp-file>/webtest.jsp</jsp-file>              //组件中包含的jsp文件
  </servlet>
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config>
  <security-constraint>                                //安全约束部分
    <web-resource-collection>                         //受约束的web资源集
      <web-resource-name>WRCollection</web-resource-name>  //资源集名
      <url-pattern>/webtest.jsp</url-pattern>                  //资源的url表达式
      <http-method>GET</http-method>                     //受约束的资源操作方法
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>                                    //对安全角色授权
      <role-name>user</role-name>                        //安全角色名
    </auth-constraint>
    <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
  </security-constraint>
  <login-config>                                        //验证方式设置
    <auth-method>BASIC</auth-method>                   //使用基本的HTTP验证方式
    <realm-name></realm-name>
  </login-config>
  <security-role>                                        //定义安全角色
    <description>this is a user</description>                      
    <role-name>user</role-name>
  </security-role>
</web-app>

从部署描述文件可以知道这是一个名为WebAppTest的web组件,包含一个名为webtest.jsp的文件,只有被赋予user安全角色的用户或用户组才有权对webtest.jsp进行GET或POST操作。这里并没有包含安全角色对实际用户的映射,j2ee部署描述文件的DTD中并没有定义用于安全角色和实际用户的映射的元素,因为实际环境中有多种不同的用户系统(如关系数据库,系统文件形式和LDAP系统等)。因此安全角色和实际用户的映射方式是由j2ee产品厂商制定的。

测试运行结果

打开ie,在导航栏输入http://localhost:8000/test/webtest.jsp回车,会弹出验证对话框,要求用户提供用户名和密码(见图8),输入用户名j2ee和密码j2ee。通过用户验证后执行jsp文件,webtest.jsp打印出"hello!"(见图9)。

图8
图8

图9
图9

注释:在第一个例子中已经详细的描述了各个步骤,在接下来的例子中会有一些与第一个例子相同的操作,因此对下面的例子只描述与第一个例子不同的步骤。

基于表单的验证的例子

基于表单的验证与基本的HTTP验证的唯一区别是基本的HTTP验证用浏览器提供的验证信息对话框收集用户验证信息,而基于表单的验证允许自定义登陆页面来收集用户验证信息。本例子与第一个例子的步骤基本相同,不同的地方在于此例子要提供登陆页面和出错页面。

登陆页面login.html


<form method="POST" action="j_security_check">
<input type=text name="j_username">
<input type=password name="j_password">
<input type=submit name="login" value="login">
</form>

此文件有几个地方值得注意:

  1. Action的值必须为"j_security_check"
  2. 获取用户名的域名必须是"j_username"
  3. 获取用户密码的域必须是" j_password"

出错页面 error.html


<html>
用户名或密码不正确!
</html>

出错页面只是简单的显示出错信息。

配置基于表单的验证

首先将login.html和error.html加入到WebAppTest组件中。
然后见图10选择Security属性页,在User Authentication Method下拉框中选择Form
Based选项。点击Settings…弹出用户验证设置对话框,在Login Page下拉框选login.html,在Error Page下拉框选error.html。

图10
图10

重新部署应用,再一次访问http://localhost:8000/test/webtest.jsp 会出现login页面(见图11),如果用户名或密码错误,error.html将显示给用户。

图11
图11

部署描述文件


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
'-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN'
'http://java.sun.com/dtd/web-app_2_3.dtd'>
<web-app>
  <display-name>WebAppTest</display-name>     
                 .
                 .
                 .
<transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
  </security-constraint>
<login-config>
    <auth-method>FORM</auth-method>                   //使用基于表单的验证方式
    <realm-name>Default</realm-name>                    //使用缺省的安全域
    <form-login-config>
      <form-login-page>/login.html</form-login-page>        //定义登陆页面
      <form-error-page>/error.html</form-error-page>       //定义出错页面
    </form-login-config>
  </login-config>
<security-role>                                        
    <description>this is a user</description>                      
    <role-name>user</role-name>
  </security-role>
</web-app>

ejb方法授权的例子

从j2ee1.3开始便提供了对ejb的方法进行授权的安全服务,这种授权服务由ejb容器实现。当调用者调用ejb的方法时,ejb容器用调用者的身份来查找授予此调用者的访问权限条目,如果调用者调用的方法属于授权条目,那么ejb容器调用方法。否则,ejb容器拒绝调用此方法,并向调用者返回拒绝访问异常。可以对远程方法和home接口方法进行授权。本例中我们将对一个远程方法和一个home接口方法进行授权。


首先创建一个session bean CountEjb
远程接口 Count.java
import javax.ejb.*;
import java.rmi.RemoteException;

public interface Count extends EJBObject {

  /**
   * 远程方法count
   */
  public int count() throws RemoteException;
}

Home接口 CountHome.java
import javax.ejb.*;
import java.rmi.RemoteException;

/**
 * This is the home interface for CountBean.  
 * One create() method is in this Home Interface, which
 * corresponds to the ejbCreate() method in the CountBean file.
 */
public interface CountHome extends EJBHome {

   /*
    * This method creates the EJB Object.
    *
    * @param val Value to initialize counter to
    *
    * @return The newly created EJB Object.
    */
  Count create(int val) throws RemoteException, CreateException;
}

实现类 CountBean.java
import javax.ejb.*;
import java.security.Principal;

/**
 
public class CountBean implements SessionBean {
	
	// The current counter is our conversational state.
	public int val;
    private SessionContext sessionCtx;
        
	//
	// 远程商业方法实现
	public int count() {
		System.out.println("count()");
          
		return ++val;
	}

	//
	// home接口Create方法的实现
	//

	public void ejbCreate(int val) throws CreateException {
		this.val = val;
		System.out.println("ejbCreate()");
	}

	public void ejbRemove() {
		System.out.println("ejbRemove()");
	}

	public void ejbActivate() {
		System.out.println("ejbActivate()");
	}

	public void ejbPassivate() {
		System.out.println("ejbPassivate()");
	}

	public void setSessionContext(SessionContext ctx) {
            sessionCtx=ctx;
	}
}
客户端程序 CountClient.java
import javax.ejb.*;
import javax.naming.*;
import java.util.Properties;

/**
 * This class is a simple example of client code.
 */
public class CountClient {

	public static void main(String[] args) {

		try {
			
            InitialContext ctx = new InitialContext();
                        
			CountHome home = (CountHome)
			  javax.rmi.PortableRemoteObject.narrow(
			    ctx.lookup("java:comp/env/CountHome"), CountHome.class);
			   

			int countVal = 0;
			Count count=null;

			/*
			创建并执行远程方法			
*/
			System.out.println("Instantiating beans...");
			
				 
				count = home.create(countVal);
                               
				countVal = count.count();

				System.out.println(countVal);

			/*
			 remove Count对象 
			 */
			count.remove();
		
		} catch (Exception e) {
            System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
}

这个ejb包括一个远程商业方法count(),我们将将此方法授权给某个安全角色。此外还将home接口的Create()方法授权给安全角色。

步骤1

编译以上源程序并用j2sdkee1.3.1的组装发布工具(deploytool.bat)进行组装(如图12)。

图12
图12

步骤2:配置安全角色

在对方法进行授权前,必须创建将被授权的安全角色。创建安全角色的步骤前边已经介绍过了,此处不再重复。本例中我们创建名为admin的安全角色。

步骤3:方法授权

方法授权的过程是确定那些安全角色可以访问特定方法的过程。方法授权一般是应用程序组装或应用程序部署者的责任。他们根据企业特定的需求创建不同的安全角色,并授予这些安全角色特定的访问权限。

用鼠标选中CountBean,在右端的窗口选择Security属性页(如图13),在Security Identity选项中选择Use Caller ID,这意味着ejb容器将用方法调用者的身份来验证方法调用权限。 Run As Specified Role选项将在"传播调用者身份标识的例子"进行介绍。由于在前面创建了admin安全角色,因此你可以看到Method Permissions栏中出现admin列。首先对远程方法count()进行授权。选择Remote选项,并在count()方法的Availability列中选择Sel Roles,然后选中count()方法的admin列。到此为止我们已对远程方法count()进行了授权。接下来对home接口的create()方法进行授权。在Show栏中选择Remote Home,剩下的步骤与count()方法授权相同。我们已经将count()方法和create()方法授权给了admin安全角色。但安全角色这是一个逻辑的集合,并不代表具体的用户或用户组,因此结下来我们要做的就是将安全角色与实际的用户映射起来。

步骤4:角色映射

首先我们需要在我们的j2ee环境中创建一个用户,用户起名为Tony,密码为1。

图13
图13

这里我们使用用户名和密码的方式进行身份验证。我们在default Realm中创建此用户。可以使用命令行方式:"realmtool -add Tony 1 eng"。详细的使用方法参见j2sdk1.3.1文档的工具部分。接下来映射安全角色到用户。选中ejb应用CountEjb,在右边窗口中选择Security属性页(如图14),点击Edit Roles按钮,选择安全角色admin。再点击Add按钮选择Tony用户。这样已经将安全角色admin和用户Tony映射起来了。

步骤5:部署应用

部署应用到本地机,右键点击ejb应用CountEjb,选择弹出菜单的deploy项,按要求配置各项。

步骤6:创建客户端

创建客户端将客户端程序的主类和其他辅助类打包。创建端将客的过程比较简单,这里就不作描述了。

步骤7:运行程序

现在可以运行客户端程序来验证方法的授权了。通过命令runclient.bat -client客户端jar包文件名 -name 主类名来执行客户端程序。客户端程序的容器将显示一个对话框来提示用户输入用户名和密码(如图15),填写用户名和密码,按OK。

图15
图15

若用户名或密码与授权的方法不符,则会抛出没有权限异常(如图16)。

图16
图16

Countejb的部署描述文件ejb.xml


<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE ejb-jar PUBLIC 
'-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 
'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>

<ejb-jar>
  <display-name>count</display-name>     
  <enterprise-beans>
    <session>                          // CountBean属于session bean
      <display-name>CountBean</display-name>  //ejb组件的显示名
      <ejb-name>CountBean</ejb-name>         //ejb组件名

      <home>CountHome</home>          //Home接口
      <remote>Count</remote>             //远程接口
      <ejb-class>CountBean</ejb-class>      //实现类
      <session-type>Stateful</session-type>   // CountBean属于Stateful Bean
      <transaction-type>Container</transaction-type>    //CountBean事务类型为容器管理的
      <security-identity>                           //安全标识
        <description></description>
        <use-caller-identity></use-caller-identity>		//CountBean使用调用者的身份标识
      </security-identity>
    </session>
  </enterprise-beans>
  <assembly-descriptor>                           
    <security-role>
      <role-name>admin</role-name>             //定义安全角色admin
    </security-role>
    <method-permission>                //将方法count和remove授权给安全角色admin
      <role-name>admin</role-name>
      <method>                       //方法定义
        <ejb-name>CountBean</ejb-name>
        <method-intf>Remote</method-intf>
        <method-name>count</method-name>
        <method-params />
      </method>
      <method>
        <ejb-name>CountBean</ejb-name>
        <method-intf>Home</method-intf>
        <method-name>remove</method-name>
        <method-params>
          <method-param>java.lang.Object</method-param>
        </method-params>
      </method>
    </method-permission>
    <method-permission>
      <unchecked />              //不检查以下方法的授权
      <method>
        <ejb-name>CountBean</ejb-name>
        <method-intf>Remote</method-intf>
        <method-name>getHandle</method-name>
        <method-params />
      </method>
          .
          .
          .
          .
      <method>
        <ejb-name>CountBean</ejb-name>
        <method-intf>Remote</method-intf>
        <method-name>getEJBHome</method-name>
        <method-params />
      </method>
    </method-permission>
    <container-transaction>        // CountBean的事务属性
      <method>
        <ejb-name>CountBean</ejb-name>
        <method-intf>Remote</method-intf>
        <method-name>count</method-name>
        <method-params />
      </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>
  </assembly-descriptor>
</ejb-jar>

可编程安全性和传播调用者身份标识的例子

此例程包括两个部分,分别演示可编程安全性和调用者身份传播。

可编程安全性例程

可编程安全性可应用在web层和EJB层,分别是通过javax.servlet.http.HttpServletRequest接口的isUserInRole ()、getUserPrincipal ()方法和javax.ejb.EJBContext接口的isCallerInRole ()、getCallerPrincipal ()方法来实现的。 public boolean isUserInRole(java.lang.String role)方法此方法用来判断调用者是否属于某一特定的安全角色,如果属于返回true,否则返回false。参数role指定某一安全角色。通过此方法开发者可以在程序代码中加入自己的安全逻辑判断,从而增强了J2EE在安全方面的灵活性。

public java.security.Principal getUserPrincipal()方法调用此方法可以得到一个java.security.Principal对象,此对象包含了调用者的用户名,通过Principal.getName()方法可以得到用户名。通过调用getUserPrincipal()方法开发者可以得到调用者的用户名,然后对调用者的用户名进行特定的逻辑判断。

public java.security.Principal getCallerPrincipal()方法 和public boolean isCallerInRole(java.lang.String roleName)方法的作用和方法同上。

下面我们通过例程来演示这些方法的用法
程序清单:
webtest.jsp


<%@page contentType="text/html"%>
<html>
<head><title>JSP Page</title></head>
<body>

<%-- <jsp:useBean id="beanInstanceName" scope="session" class="package.class" /> --%>
<%-- <jsp:getProperty name="beanInstanceName"  property="propertyName" /> --%>
Hello!
the caller is <%=request.getUserPrincipal().getName()%><br/> <%--得到调用者的用户名--%>
<% if (request.isUserInRole("admin")){%>  <%--判断调用者是否属于"admin"安全角色--%>
the caller is admin Role;
<%} %>
</body>
</html>

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
'-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 
'http://java.sun.com/dtd/web-app_2_3.dtd'>
<web-app>
  <display-name>WebApp</display-name>
  <servlet>
    <servlet-name>webtest</servlet-name>
    <display-name>webtest</display-name>
    <jsp-file>/webtest.jsp</jsp-file>
    <security-role-ref>
      <role-name>adminref</role-name>
      <role-link>admin</role-link>
    </security-role-ref>
    <security-role-ref>
      <role-name>guestref</role-name>
      <role-link>guest</role-link>
    </security-role-ref>
  </servlet>
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>webtest.jsp</welcome-file>
  </welcome-file-list>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>WRCollection</web-resource-name>
      <url-pattern>/webtest.jsp</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>admin</role-name>
      <role-name>guest</role-name>
    </auth-constraint>
    <user-data-constraint>
      <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
  </security-constraint>
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name></realm-name>
  </login-config>
  <security-role>
    <role-name>admin</role-name>
  </security-role>
  <security-role>
    <role-name>guest</role-name>
  </security-role>
</web-app>

从web.xml文件的内容可以看出,只有安全角色为"admin"和"guest"的用户才有权对webtest.jsp文件进行POST和GET操作。

运行结果:

创建一个web应用,将webtest.jsp作为一个web组件,并按照web.xml的内容配置web应用,在运行环境中将用户j2ee分配为admin安全角色,将用户Tony分配为guest角色。发布web应用到本地j2ee Server上。用ie访问webtest.jsp 如图17用用户j2ee的身份进行验证,用户j2ee属于admin安全角色。显示结果见图18

图17
图17

图18
图18

如果用用户Tony进行验证,结果见图19

图19
图19

ejb中应用可编程的安全性与在web中的方法相似,本文不再进行介绍。

传播调用者身份标识例程

本例程将演示调用者身份标识如何在调用链中传递的,并且介绍如何应用"Run As"来实现在调用链中更改调用者的身份。本例将用一个web组件(一个jsp文件)和两个ejb组件来形成一个调用链。
程序清单:
webtest.jsp


<%@page contentType="text/html"%>
<%@page import="andy.*"%>
<%@page import="javax.naming.*"%>
<html>
<head><title>JSP Page</title></head>
<body>

<%-- <jsp:useBean id="beanInstanceName" scope="session" class="package.class" /> --%>
<%-- <jsp:getProperty name="beanInstanceName"  property="propertyName" /> --%>
Hello!
the caller is <%=request.getUserPrincipal().getName()%> <br/>
<% if (request.isUserInRole("admin")){%>
the caller is admin Role;
<%} %>
<%  
    try {
    Context ctx = new InitialContext();
    andy.CountHome home = 
(andy.CountHome)javax.rmi.PortableRemoteObject.narrow(
ctx.lookup("java:comp/env/CountHome"), andy.CountHome.class);
    andy.Count count = home.create(1);
    count.count();
    }catch (Exception e) 
    {
	e.printStackTrace();
    }
%>
</body>
</html>

CountBean.java


package andy;
import javax.ejb.*;
import javax.naming.*;
public class CountBean implements SessionBean {
	public int val;
    private SessionContext EjbCxt = null;
	public int count()
{
        int temp = 0;
		System.out.println("CountBean.count()");
		//打印调用者名
        System.out.println("the caller is "+EjbCxt.getCallerPrincipal().getName());
		//判断调用者的安全角色
        if(EjbCxt.isCallerInRole("adminref")) // adminref为安全角色admin的引用名
        {
            System.out.println("the caller is admin Role");
         }
         if(EjbCxt.isCallerInRole("guestref")) // guestref为安全角色guest的引用名
         {
              System.out.println("the caller is guest Role");
          }
         if(EjbCxt.isCallerInRole("userref")) // userref为安全角色user的引用名
         {
              System.out.println("the caller is user Role");
          }
         //调用另一个ejb的远程方法
          try {
                   Context ctx = new InitialContext();
                   CountHome1 home = 
(CountHome1)javax.rmi.PortableRemoteObject.narrow(
ctx.lookup("java:comp/env/CountHome1"), CountHome1.class);
          Count1 count = home.create(1);
          temp = count.count();
          }catch (Exception e) 
                {
                      e.printStackTrace();
                 }
		return ++temp;
	}
	public void ejbCreate(int val) throws CreateException {
		this.val = val;
	}
	public void ejbRemove() {
	}
	public void ejbActivate() {
	}
	public void ejbPassivate() {
	}
	public void setSessionContext(SessionContext ctx) {
            EjbCxt = ctx;  //获取EjbContext对象
	}
}

CountBean1.java
package andy;
import javax.ejb.*;

public class CountBean1 implements SessionBean {
	public int val;
    private SessionContext EjbCxt = null; 
	public int count() {
		System.out.println("CountBean1.count()");
        System.out.println("the caller is "+EjbCxt.getCallerPrincipal().getName());
                if(EjbCxt.isCallerInRole("adminref"))
                {
                    System.out.println("the caller is admin Role");
                }
                if(EjbCxt.isCallerInRole("guestref"))
                {
                    System.out.println("the caller is guest Role");
                }
                if(EjbCxt.isCallerInRole("userref"))
                {
                    System.out.println("the caller is user Role");
                }
                
		return ++val;
	}
	public void ejbCreate(int val) throws CreateException {
		this.val = val;
	}
	public void ejbRemove() {
	}
	public void ejbActivate() {
	}
	public void ejbPassivate() {
	}
	public void setSessionContext(SessionContext ctx) {
            EjbCxt = ctx;
	}
}

以上的三个文件分别是一个web组件和两个ejb组件的源代码,这三个组件构成了一个调用链.webtest.jsp中,首先通过HttpServletRequest..getUserPrincipal ()方法来得到调用webtest.jsp的用户的Principal对象,在通过Principal.getName()方法得到调用者的用户名. 然后通过HttpServletRequest..isUserInRole()方法来判断调用这是否属于特定的安全角色.CountBean是一个stateful SessoinBean,它拥有一个count()远程方法,在这个远程方法中写了用于得到调用者用户名和判断调用这安全角色的代码,还包括调用CountBean1对象的代码,用于展示调用者身份标识是如何在调用链中传递和调用者的安全角色如何被改变的.CountBean1也是一个stateful SessoinBean,它的代码内容与CountBean基本相同,只不过它不包含调用其他Bean的代码.

现在我们应该配置各组件的安全属性了.我们在组件webtest中创建安全角色admin,引用名为adminref,在组件CountBean和CountBean1中分别创建安全角色admin和user, 引用名分别为adminref和userref.将webtest组件配置为"HTTP Basic Authentication",给安全角色admin赋予访问webtest.jsp的权限.把CountBean设置为Run As Specified Role,选择user安全角色.在运行环境中将用户j2ee赋予admin安全角色和user安全角色.然后发布应用到服务器.用用户j2ee访问webtest.jsp.

执行结果:
客户端见图20

图20
图20

服务器端:
CountBean.count()
the caller is j2ee
the caller is admin Role
CountBean1.count()
the caller is j2ee
the caller is user Role

从运行结果看,访问webtest.jsp的用户为j2ee,其安全角色为admin,访问CountBean的用户名为j2ee,安全角色为admin.可以看到用户身份标识从web容器传递到了ejb容器.再看组件CountBean1的输出结果,由于CountBean被设置成了Run As Specified Role,因此在CountBean向下调用其他组件对象时,用户安全角色已经被改为指定的安全角色,这里是user.所以我们会看到,调用组件CountBean1的用户名为j2ee,安全角色为user.j2ee的这种安全特性满足了同一用户在不同应用中具有不同安全角色的需求.开发人员也可以利用这种特性进行灵活的安全逻辑判断.

相关推荐

baostock实战:如何用Python批量下载多只股票的历史数据(含常见错误排查)

本文详细介绍了如何使用Python和baostock库批量下载多只股票的历史数据。内容涵盖从环境搭建、代码标准化到构建稳健的批量下载框架的全过程,并重点提供了高级错误处理、网络重试、数据验证及内存管理等实战解决方案,帮助用户高效构建股票数据处理流水线。

nice1的博客 1003

Java官网

java最新下载地址: http://www.java.com/zh_CN/download/manual.jsp java官网: http://www.java.com/zh_CN

Java1997 3万+

华为手环实时心率数据导出到UWP项目中

hello大家好呀O(∩_∩)O最近在做毕设 其中有个小功能要用到实时心率数据。查找网上的资料发现只有小米手环的实时心率数据导出但是没有华为手环的,我试了华为手环但是并不能行得通哈哈哈。现在分享一下华为手环实时心率数据导出的代码。

apple_63713858的博客 1552

java官网下载

安装版 http://javadl.oracle.com/webapps/download/AutoDL?BundleId=234471_96a7b8442fe848ef90c96a2fad6ed6d1 win64 http://javadl.oracle.com/webapps/download/AutoDL?BundleId=234474_96a7b8442fe848ef90c96a2f...

weixin_30815469的博客 4万+

Maven 初学+http://mvnrepository.com/

了解 maven是一款服务于java平台的自动化构建工具 用来解决团队开发遇到的问题 如: 统一 jar包 统一配置文件,单元测试 的代码位置即 目录结构的统一 核心文件pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-inst...

凯凯的博客 33万+

win10 java更新失败_win10系统配置java环境及遇到问题的一些处理方法

O1 java安装:从java官网下载:https://www.java.com/zh_CN/安装教程:http://jingyan.baidu.com/article/03b2f78c137ec85ea237aec7.html1、...

weixin_26966397的博客 465

MyEclipse rest webservice (Jersey)使用 问题总结

java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer 从http://mvnrepository.com/artifact/com.sun.jersey/jersey-bundle 下载对应版本,放到WebRoot/WEB-INF/lib下,右击,并Add to Build

猿来这样-谢厂节的博客 1万+

起源之路——JSR?J2EE?JavaEE?

起源之路——JSR?J2EE?JavaEE? 前言 鉴于自己工作了一段时间对各种框架中间件处于知其然不知其所以然的状态中,所以萌生了追寻起源的想法,于是便开始准备编写该系列文章,系统的整理自己对J2EE的理解。若有发现理解不到位,或有不同见解的地方,欢迎各位大神拍砖。 什么是J2EE? J2EE的全称是Java 2 Platform Enterprise Edition,它是由多家公司共同参与并制...

LuoGuoHua_Xin的博客 865

J2EE是什么,主要包括哪些技术

https://blog.csdn.net/Ashes18/article/details/73614571 最近最为深刻的认识:被面试老师问到了的知识,哪些是在自己心中模棱两可,似是而非的概念都一目了然。而后,只有在顿悟中不断总结才能进步。今天,我总结的部分J2EE到底是什么东西,它包括了哪些技术。 一、J2EE是什么? 从整体上讲,J2EE 是使用 Java 技术开发企业级应用的工业标准,它...

QDShuai的博客 3万+

J2EE

J2EE是什么,主要包括哪些技术 一、J2EE是什么? 从整体上讲,J2EE 是使用 Java 技术开发企业级应用的工业标准,它是 Java 技术不断适应和促进企业级应用过程中的产物。 适用于企业级应用J2EE,提供一个平台独立的、可移植的、多用户的、安全的和基于标准的企业级平台,从而简化企业应用的 开发、管理和部署。J2EE 是一个标准,而不是一个现成的产品。(来自百度) 二、J2EE主要包括哪些技术 servlet Servlet是java平台上的CGI技术。Servlet在服务器端运行,动态地生成

qq_42918433的博客 8198

javaEE和j2EE一样吗?

javaEE和j2EE一样吗?从JDK 5.0开始 J2EE 改名为 java EE,J2SE 改名为 java SE,J2ME 改名成 java ME,其实是一回事,只是叫法改了而已java EE 是java的企业版,主要面向web应用,尤其是企业级开发,都提供了一套开发流程。(这句话个人感觉不好理解.)    1,JavaEE是标准集定义的技术架构    2,企业开发是一个面向企业开发的技术组...

dhtcdh的博客 1万+

J2EE的体系架构——J2EE

https://blog.csdn.net/dandanzmc/article/details/27355565 J2EE的体系架构 J2EE是Java2平台企业版(Java 2 Platform,Enterprise Edition),它的核心是一组技术规范与指南,提供基于组件的方式来设计、开发、组装和部署企业应用J2EE使用多层分布式的应用模型。 J2EE分层 客户层,运行在客户计算机...

try to do 1万+

JavaEE(J2EE)学习篇

一、简要介绍 Java EE,Java 平台企业版(Java Platform Enterprise Edition),之前称为Java 2 Platform, Enterprise Edition (J2EE),2018年3月更名为 Jakarta EE, 是 Sun 公司为企业级应用推出的标准平台,用来开发B/S架构软件,可以说是一个框架或是一种规范。 Java EE是 J2EE的一个新的名...

nann-viiv 的博客 907

J2EE笔记之JavaEE

一、JavaEE产生的背景 为了满足开发多层体系结构的企业级应用的需求,Java公司的创始人Sun公司在早期的J2SE(Java 2 Platform Standard Edition)基础上,针对企业级应用的各种需求,提出了J2EE(Java 2 Plantform Enterprise Edition). 企业级应用程序特点 定义:泛指那些为大型组织部门创建的应用程序。注:并不是特指为企业开发的应用软件。 企业级应用程序一般具有以下特点: 1)分布式:通过局域网运行在一个组织内部,或通过Int

Zxy_zzz的博客 1296

java的发展-J2EE和JavaEE的区别

为了自己更好的了解java! 一直分不清楚J2EE和JavaEE的区别,根据百度百科上的解释:“此时,Java的各种版本已经更名,已取消其中的数字2,如J2EE更名为JavaEE,J2SE更名为JavaSE,J2ME更名为JavaME。”他们是一个东西。那他们是什么? java的开发平台提供的开发包,叫做jdk(java development kit)也可以叫做java sdk(java pla...

buzhiweibuzhi的博客 1万+

javaEE5.0与J2EE1.4比较

<br />在新建web工程时,如果选的是javaEE5自带的jstl,仅能够使用tomcat6.x才能正常使用el <br />如果选的是j2ee1.4或者j2ee1.3时,需要手动添加jstl, <br />默认与tomcat5.x兼容,所以你修改一下web.xml,因为javaEE5.0和j2ee1.4,1.3是不一样的 <br />所以对jstl和el的支持也并不相同! <br />------------------------------------------<br />在新建web工程时,如

gyflyx的专栏 5181

JavaEE——Http请求和响应,https的加密

http请求报文中的一些重要概念及解析,构造请求的三种方式,响应的状态码的具体含义,https的对称和不对称加密

m0_60867520的博客 2865

入职java学习总结

java学习总结

Mr. Ding的小博客 3841

中高级JAVA工程师-面试题汇总

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/shengqianfeng/article/details/102572691 ———————————————— 版权声明:本文为CSDN博主「Jeff.Smile」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链...

weixin_43651188的博客 424

JavaWeb-Web入门

文章目录1 Http1.1 什么是http1.2 http的两个时代1.3 http请求1.4 http响应2 Maven2.1 什么是maven2.2 配置环境变量2.3 阿里云镜像2.4 本地仓库3 Servlet3.1 什么是Servlet3.2 HelloServlet实现3.3 Servlet原理3.4 mapping3.5 ServletContext3.5.1 共享数据3.5.2 获取初始化参数3.5.3 请求转发3.5.4 读取资源文件3.6 HttpServletResponse3.6.1

h1429541165的博客 232

面向 Java 开发人员的区块链链代码

面向 Java 开发人员的链代码简介 点击查看视频演示查看抄本 您或许听说过区块链,但可能不确定它对 Java™ 开发人员有何用。本教程将帮助大家解惑。我将分步展示如何使用 Hyperledger Fabric v0.6 来构建、运行和执行使用 Java 语言编写的智能合约或链代码。您将安装一些工具,定义本地区块链网络,构建并运行一个链代码智能合约。 有关区块链的概述,请参阅 devel

龙慧空羽 2万+

Java与Http协议(HttpURLConnection和HttpClient)

转载:http://www.csdn123.com/html/blogs/20130505/9360.htm   引言                                               http(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式。HTTP协议的主要特点是:      1.支持客户/服务器模式。      2...

leiyongping的专栏 479

基于双二阶广义积分器的三相锁相环(DSOGI-PLL)附Simulink仿真.rar

1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

一个基于php的入侵检测与防御系统源码.zip

一个基于php的入侵检测与防御系统源码.zip

上一篇: 实用EJB开发技巧
下一篇: J2EE 中的安全第一部分 - J2EE安全介绍
jery_lee
博客等级 码龄25年 53粉丝 294原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值