`
tiandiyixian
  • 浏览: 2010 次
社区版块
存档分类
最新评论

扩展JAAS实现类实例级授权(转)

    博客分类:
  • java
阅读更多
大多数 Java 应用程序都需要某种类实例级的访问控制。例如,基于 Web 的、自我服务的拍卖应用程序的规范可能有下列要求:
任何已注册(经过认证)的用户都可以创建一个拍卖,但只有创建拍卖的用户才可以修改这个拍卖。
这意味着任何用户都可以执行被编写用来创建 Auction 类实例的代码,但只有拥有该实例的用户可以执行用来修改它的代码。通常情况下,创建 Auction 实例的用户就是所有者。这被称为 类实例所有者关系(class instance owner relationship)。
该应用程序的另一个要求可能是:
任何用户都可以为拍卖创建一个投标,拍卖的所有者可以接受或拒绝任何投标。
再一次,任何用户都可以执行被编写用来创建 Bid 类实例的代码,但只有拥有该实例的用户会被授予修改该实例的许可权。而且, Auction 类实例的所有者必须能够修改相关的 Bid 类实例中的接受标志。这意味着在 Auction 实例和相应的 Bid 实例之间有一种被称为 特定关系(special relationship)的关系。
不幸的是,“Java 认证和授权服务”(JAAS)― 它是 Java 2 平台的一部分 ― 没有考虑到类实例级访问控制或者特定关系。在本文中,我们将扩展 JAAS 框架使其同时包含这两者。推动这种扩展的动力是允许我们将访问控制分离到一个通用的框架,该框架使用基于所有权和特定关系的策略。然后管理员可以在应用程序的生命周期内更改这些策略。
在深入到扩展 JAAS 框架之前,我们将重温一下 Java 2 平台的访问控制机制。我们将讨论策略文件和许可权的使用,并讨论 SecurityManager 和 AccessController 之间的关系。
Java 2 平台中的访问控制
在 Java 2 平台中,所有的代码,不管它是本地代码还是远程代码,都可以由策略来控制。 策略(policy)由不同位置上的代码的一组许可权定义,或者由不同的签发者定义、或者由这两者定义。 许可权允许对资源进行访问;它通过名称来定义,并且可能与某些操作关联在一起。
抽象类 java.security.Policy 被用于表示应用程序的安全性策略。缺省的实现由 sun.security.provider.PolicyFile 提供,在 sun.security.provider.PolicyFile 中,策略被定义在一个文件中。清单 1 是一个典型策略文件示例:

清单 1. 一个典型的策略文件
// Grant these permissions to code loaded from a sample.jar file
// in the C drive and if it is signed by XYZ
grant codebase "file:/C:/sample.jar", signedby "XYZ" {
// Allow socket actions to any host using port 8080
permission java.net.SocketPermission "*:8080", "accept, connect,
  listen, resolve";
// Allows file access (read, write, execute, delete) in
// the user's home directory.
Permission java.io.FilePermission "${user.home}/-", "read, write,
  execute, delete";
};

SecurityManager 对 AccessController
在标准 JDK 分发版中,控制代码源访问的机制缺省情况下是关闭的。在 Java 2 平台以前,对代码源的访问都是由 SecurityManager 类管理的。 SecurityManager 是由 java.security.manager 系统属性启动的,如下所示:
java -Djava.security.manager

在 Java 2 平台中,可以将一个应用程序设置为使用 java.lang.SecurityManager 类或者 java.security.AccessController 类管理敏感的操作。 AccessController 在 Java 2 平台中是新出现的。为便于向后兼容, SecurityManager 类仍然存在,但把自己的决定提交 AccessController 类裁决。 SecurityManager 和 AccessController 都使用应用程序的策略文件确定是否允许一个被请求的操作。清单 2 显示了 AccessController 如何处理 SocketPermission 请求:

清单 2. 保护敏感操作
Public void someMethod() {
Permission permission =
  new java.net.SocketPermission("localhost:8080", "connect");
AccessController.checkPermission(permission);
// Sensitive code starts here
Socket s = new Socket("localhost", 8080);
}

在这个示例中,我们看到 AccessController 检查应用程序的当前策略实现。如果策略文件中定义的任何许可权暗示了被请求的许可权,该方法将只简单地返回;否则抛出一个 AccessControlException 异常。在这个示例中,检查实际上是多余的,因为缺省套接字实现的构造函数也执行相同的检查。
在下一部分,我们将更仔细地看一下 AccessController 如何与 java.security.Policy 实现共同合作安全地处理应用程序请求。
回页首
运行中的 AccessController
AccessController 类典型的 checkPermission(Permission p) 方法调用可能会导致下面的一系列操作:
AccessController 调用 java.security.Policy 类实现的 getPermissions(CodeSource codeSource) 方法。
getPermissions(CodeSource codeSource) 方法返回一个 PermissionCollection 类实例,这个类实例代表一个相同类型许可权的集合。
AccessController 调用 PermissionCollection 类的 implies(Permission p) 方法。
接下来, PermissionCollection 调用集合中包含的单个 Permission 对象的 implies(Permission p) 方法。如果集合中的当前许可权对象暗示指定的许可权,则这些方法返回 true ,否则返回 false 。
现在,让我们更详细地看一下这个访问控制序列中的重要元素。
PermissionCollection 类
大多数许可权类类型都有一个相应的 PermissionCollection 类。这样一个集合的实例可以通过调用 Permission 子类实现定义的 newPermissionCollection() 方法来创建。 java.security.Policy 类实现的 getPermissions() 方法也可以返回 Permissions 类实例 ― PermissionCollection 的一个子类。这个类代表由 PermissionCollection 组织的不同类型许可权对象的一个集合。 Permissions 类的 implies(Permission p) 方法可以调用单个 PermissionCollection 类的 implies(Permission p) 方法。
CodeSource 和 ProtectionDomain 类
许可权组合与 CodeSource (被用于验证签码(signed code)的代码位置和证书)被封装在 ProtectionDomain 类中。有相同许可权和相同 CodeSource 的类实例被放在相同的域中。带有相同许可权,但不同 CodeSource 的类被放在不同的域中。一个类只可属于一个 ProtectionDomain 。要为对象获取 ProtectionDomain ,请使用 java.lang.Class 类中定义的 getProtectionDomain() 方法。
许可权
赋予 CodeSource 许可权并不一定意味着允许所暗示的操作。要使操作成功完成,调用栈中的每个类必须有必需的许可权。换句话说,如果您将 java.io.FilePermission 赋给类 B,而类 B 是由 类 A 来调用,那么类 A 必须也有相同的许可权或者暗示 java.io.FilePermission 的许可权。
在另一方面,调用类可能需要临时许可权来完成另一个拥有那些许可权的类中的操作。例如,当从另一个位置加载的类访问本地文件系统时,我们可能不信任它。但是,本地加载的类被授予对某个目录的读许可权。这些类可以实现 PrivilegedAction 接口来给予调用类许可权以便完成指定的操作。调用栈的检查在遇到 PrivilegedAction 实例时停止,有效地将执行指定操作所必需的许可权授予所有的后继类调用。
回页首
使用 JAAS
顾名思义,JAAS 由两个主要组件组成:认证和授权。我们主要关注扩展 JAAS 的授权组件,但开始我们先简要概述一下 JAAS 认证,紧接着看一下一个简单的 JAAS 授权操作。
JAAS 中的用户认证
JAAS 通过添加基于 subject 的策略加强了 Java 2 中定义的访问控制安全性模型。许可权的授予不仅基于 CodeSource ,还基于执行代码的用户。显然,要使这个模型生效,每个用户都必须经过认证。
JAAS 的认证机制建立在一组可插登录模块的基础上。JAAS 分发版包含几个 LoginModule 实现。 LoginModules 可以用于提示用户输入用户标识和密码。 LoginContext 类使用一个配置文件来确定使用哪个 LoginModule 对用户进行认证。这个配置可以通过系统属性 java.security.auth.login.config 指定。一个示例配置是:
java -Djava.security.auth.login.config=login.conf

下面是一个登录配置文件的样子:
Example {
  com.ibm.resource.security.auth.LoginModuleExample required
    debug=true userFile="users.xml" groupFile="groups.xml";
};

认识您的主体
Subject 类被用于封装一个被认证实体(比如用户)的凭证。一个 Subject 可能拥有一个被称为 主体(principal)的身份分组。例如,如果 Subject 是一个用户,用户的名字和相关的社会保险号可能是 Subject 的某些身份或主体。主体是与身份名关联在一起的。
Principal 实现类及其名称都是在 JAAS 策略文件中指定的。缺省的 JAAS 实现使用的策略文件与 Java 2 实现的策略文件相似 ― 除了每个授权语句必须与至少一个主体关联在一起。 javax.security.auth.Policy 抽象类被用于表示 JAAS 安全性策略。它的缺省实现由 com.sun.security.auth.PolicyFile 提供,在 com.sun.security.auth.PolicyFile 中策略定义在一个文件中。清单 3 是 JAAS 策略文件的一个示例:

清单 3. 示例 JAAS 策略文件
// Example grant entry
grant codeBase "file:/C:/sample.jar", signedby "XYZ",
  principal com.ibm.resource.security.auth.PrincipalExample "admin" {
    // Allow socket actions to any host using port 8080
    permission java.net.SocketPermission
      "*:8080", "accept, connect, listen, resolve";
    // Allows file access (read, write, execute, delete) in
    // the user's home directory.
    Permission java.io.FilePermission
      "${user.home}/-", "read, write, execute, delete";
};

这个示例与清单 1 中所示的标准 Java 2 策略文件相似。实际上,唯一的不同是主体语句,该语句声明只有拥有指定主体和主体名字的 subject(用户)被授予指定的许可权。
再一次,使用系统属性 java.security.auth.policy 指出 JAAS 策略文件驻留在何处,如下所示:
java -Djava.security.auth.policy=policy.jaas

Subject 类包含几个方法来作为特殊 subject 执行工作;这些方法如下所示:
public static Object
  doAs(Subject subject, java.security.PrivilegedAction action)
public static Object
  doAs(Subject subject, java.security.PrivilegedAction action)
  throws java.security.PrivilegedActionException

注意,用来保护敏感代码的方法与“Java 2 代码源访问控制”(Java 2 CodeSource Access Control)概述中描述的方法相同。请参阅 参考资料部分以了解更多关于 JAAS 中代码源访问控制和认证的信息。
回页首
JAAS 中的授权
清单 4 显示一个授权请求的结果,该请求使用清单 3 中显示的 JAAS 策略文件。假设已经安装了 SecurityManager ,并且 loginContext 已经认证了一个带有名为“admin”的 com.ibm.resource.security.auth.PrincipalExample 主体的 Subject 。

清单 4. 一个简单的授权请求
public class JaasExample {
public static void main(String[] args) {
...
// where authenticatedUser is a Subject with
// a PrincipalExample named admin.
Subject.doAs(authenticatedUser, new JaasExampleAction());
...
}
}
public class JaasExampleAction implements PrivilegedAction {
public Object run() {
FileWriter fw = new FileWriter("hi.txt");
fw.write("Hello, World!");
fw.close();
}
}

这里,敏感代码被封装在 JaasExampleAction 类中。还要注意,调用类不要求为 JaasExampleAction 类代码源授予许可权,因为它实现了一个 PrivilegedAction 。
回页首
扩展 JAAS
大多数应用程序都有定制逻辑,它授权用户不仅仅在类上执行操作,而且还在该类的实例上执行操作。这种授权通常建立在用户和实例之间的关系上。这是 JAAS 的一个小缺点。然而,幸运的是,这样设计 JAAS 使得 JAAS 可以扩展。只要做一点工作,我们将可以扩展 JAAS,使其包含一个通用的、类实例级的授权框架。
在文章开头处我已经说明了,抽象类 javax.security.auth.Policy 被用于代表 JAAS 安全性策略。它的缺省实现是由 com.sun.security.auth.PolicyFile 类提供。 PolicyFile 类从 JAAS 格式的文件(象清单 3 中显示的那个一样)中读取策略。
我们需要向这个文件添加一个东西为类实例级授权扩展策略定义:一个与许可权语句相关的可选关系参数。
缺省 JAAS 许可权语句的格式如下:
permission <permission implementation class> [name], [actions];

我们在这个许可权语句的末尾添加一个可选的关系参数来完成策略定义。下面是新许可权语句的格式:
permission <permission implementation class>
  [name], [actions], [relationship];

在为类实例级授权扩展 JAAS 时要注意的最重要的一点是:许可权实现类必须有一个带三个参数的构造函数。第一个参数是名称参数,第二个是行为参数,最后一个是关系参数。
解析新文件格式
既然文件格式已经改变,就需要一个新的 javax.security.auth.Policy 子类来解析文件。
为简单起见,我们的示例使用了一个新的 javax.security.auth.Policy 子类 com.ibm.resource.security.auth.XMLPolicyFile ,来从 XML 文件读取策略。在实际的企业应用程序中,关系数据库更适合执行这个任务。
使用 XMLPolicyFile 类代替缺省的 JAAS 访问控制策略实现的最容易的方法是向 java.security 属性文件添加 auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile 条目。 java.security 属性文件位于 Java 2 平台运行时的 lib/security 目录下。清单 5 是与 XMLPolicyFile 类一起使用的样本 XML 策略文件:

清单 5. 一个 XML 策略文件
<?xml version="1.0"?>
<policy>
    <grant codebase="file:/D:/sample_actions.jar">
      <principal classname=
        "com.ibm.resource.security.auth.PrincipalExample" name="users">
        <permission classname=
          "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Auction"
          actions="create" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Auction"
          actions="read" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Auction"
          actions="write"
          relationship="owner" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="create" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="read" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="write"
          relationship="owner" />
        <permission classname=
         "com.ibm.resource.security.auth.ResourcePermission"
          name="com.ibm.security.sample.Bid"
          actions="accept"
          relationship="actionOwner" />
    </principal>
  </grant>
</policy>

在这个示例策略文件中,任何与名为 PrincipalExample 的用户有关的用户( Subject )都可以创建并读取一个 Auction.class 实例。但是,只有创建该实例的用户才可以更新(写)它。这是第三个 permission 元素定义的,该元素包含值为 owner 的 relationship 属性。 Bid.class 实例也是一样,除了相应 Auction.class 实例的所有者可以更改投标接受标志。
Resource 接口
要求类实例级访问控制的类必须实现 Resource 接口。该接口的 getOwner() 方法返回类实例的所有者。 fulfills(Subject subject, String relationship) 方法被用于处理特定关系。另外,这些类使用 com.ibm.resource.security.auth.ResourcePermission 类保护敏感代码。例如, Auction 类拥有下列构造函数:
public Auction() {
  Permission permission =
    new ResourcePermission("com.ibm.security.sample.Auction", "create");
  AccessController.checkPermission(permission);
}

所有者关系
ResourcePermission 类的 implies(Permission p) 方法是这个框架的关键。 implies() 方法就等同性比较名称和行为属性。如果定义了一个关系,那么必须把受保护的类实例( Resource )传递到 ResourcePermission 构造函数中。 ResourcePermission 类理解所有者关系。它将类实例的所有者与执行代码的 subject(用户)进行比较。特定关系被委托给受保护类的 fulfills() 方法。
例如,在清单 5 中所示的 XML 策略文件中,只有 Auction 类实例的所有者可以更新(写)文件。该类的 setter 方法使用清单 6 中显示的保护代码:

清单 6. 运行中的 implies(Permission) 方法
public void setName(String newName) {
  Permission permission =
    new ResourcePermission("com.ibm.security.sample.Auction", "write", this);
  AccessController.checkPermission(permission);
  // sensitive code
  this.name = newName;
}

被传递到 ResourcePermission 构造函数中的 this 引用代表 Auction 类实现的 Resource 接口。由于策略文件中列出的关系是 owner,所以 ResourcePermission 类使用这个引用检查当前 Subject (用户)是否拥有与实例所有者相匹配的主体。如果指定了另一个关系,那么 ResourcePermission 类调用 Auction 类的 fulfills(Subject subject, String relationship) 方法。由 Resource 实现类提供 fulfills() 方法中的逻辑。
XML 策略文件中列出的 Bid 类拥有清单 7 中所示的方法(假设 Bid 类实例有一个对相应 Auction 类实例的引用 ― auction)。

清单 7. 处理特定关系
public void setAccepted(boolean flag) {
  Permission permission =
    new ResourcePermission("com.ibm.security.sample.Auction", "accept", this);
  AccessController.checkPermission(permission);
  // sensitive code
  this.accepted = flag;
  }

public boolean fulfills(Subject user, String relationship) {
  if( relationship.equalsIgnoreCase("auctionOwner") ) {
    String auctionOwner = auction.getOwner();
    Iterator principalIterator = user.getPrincipals().iterator();
    while(principalIterator.hasNext()) {
      Principal principal = (Principal) principalIterator.next();
      if( principal.getName().equals(auctionOwner) )
        return true;
    }
  }
  return false;
}

传递到 fulfills() 方法中的关系字符串是策略文件中列出的关系。在这个案例中,我们使用了“ auctionOwner ”字符串。
缺省情况下, XMLPolicyFile 类在当前工作目录中查找名为 ResourcePolicy.xml 的文件。系统属性 com.ibm.resource.security.auth.policy 可以用于指定另一个不同的文件名和位置。
WebSphere Application Server 示例
除命令行示例之外,您可能还想运行这个简单的程序,该程序 为了 IBM WebSphere Application Server,version 4.0.2 而被优化。
回页首
一个可运行的示例
综合这些信息,我们将运行一个简单的命令行示例。该示例程序包含三个 jar 文件:
resourceSecurity.jar
example.jar
exampleActions.jar
resourceSecurity.jar 文件包含允许实例级访问控制的 JAAS 扩展框架。它还包含一个 LoginModuleExample 类,这个类从 XML 文件读取用户认证信息。用户标识和密码存储在 users.xml 文件中。用户组存储在 groups.xml 文件中。关于 LoginModuleExample 的更多信息,请参阅 参考资料部分。
该示例包含四个附加的文件:
login.conf
policy
resourcePolicy.xml
run.bat
在试图运行这个示例程序之前,请确保更新了 run.bat、policy 和 resourcePolicy.xml 文件中的路径。缺省情况下,所有的密码都是“passw0rd”。
示例如何工作
该示例程序提示输入用户标识和密码。它用 users.xml 文件中的条目核对所提供的用户标识和密码。在认证了用户之后,程序设法创建一个 UserProfile 类实例,修改它并从中读取。缺省情况下, UserProfile 类的所有者是 Jane(jane)。当 Jane 登录时,三个操作全部成功。当 John(john)登录时,只有创建操作成功。当 Jane 的经理 Lou(lou)登录时,只有第一个和最后一个操作成功。当系统管理员(admin)登录时,操作全部成功。当然,只有当提供的 ResourcePolicy.xml 文件未被修改时,上述这些才都是真的。
示例安装
下面的安装指导假设您正在使用 JDK 1.3 并且已经把文件解压缩到 d:\JaasExample 目录。通过将文件解压缩到这个目录,您可以省去一些工作;否则您就必须使用正确的路径名修改 policy 和 ResourceSecurity.xml 策略文件。
下面是运行该示例需要做的工作:
下载这个示例的 源文件。
把 jaas.jar 和 jaasmod.jar 复制到 JDK jre\lib\ext 目录(即 D:\JDK1.3\jre\lib\ext)。
向位于 JDK 的 jre\lib\security 目录(即 D:\JDK1.3\jre\lib\security)中的 java.security 文件的末尾添加下面的字符串: auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile 。
执行 run.bat 文件。
回页首
结束语
类实例级授权把访问控制分离到一个通用框架(该框架使用基于所有权和特定关系的策略)中。然后管理员可以在应用程序的生命周期内更改这些策略。用这种方法扩展 JAAS 减少了您或另一个程序员必须在应用程序生命周期内业务规则发生更改时重写代码的可能性。
通过将关系字符串抽象为类可以进一步扩展特定关系这个概念。不调用 Resource 实现类的 fulfills(Subject user, String relationship) 方法,而只要调用 Relationship 实现类中定义的新 fulfills(Subject user, Resource resource) 方法。这样就会允许许多 Resource 实现类使用相同的关系逻辑。

参考资料
您可以参阅本文在 developerWorks 全球站点上的 英文原文.

请单击文章顶部或底部的 讨论参与本文的 讨论论坛。


下载本文中所用示例的 源代码。


IBM 的 Preview technologies for Windows让您下载放在一个唾手可得的软件包中的 JDK 1.3 和 WebSphere Application Server。


要了解更多关于“Java 认证和授权服务”的知识,请参阅 JAAS 1.0 Developers Guide。


Java 2 API Documentation是另一个用于了解 Java 2 平台扩展的优秀参考资料。


访问 Sun Microsystems 的 Java 教程系列 Security in Java 2 SDK 1.2(它包括关于策略文件的课程),您可以了解更多关于 Java 平台的安全性模型的信息。


要进一步了解 Java 平台的安全性模型背景,请参阅 API for Privileged Blocks,它介绍了特权代码的概念。


关于 Java 安全性的深入介绍,请参阅 Scott Oaks 的 Java Security, 2nd Edition (O'Reilly & Associates,2001 年 5 月)。


为了更结合实际地学习 JAAS,请参阅 Thomas Owusu 的“ Enhance Java GSSAPI with a login interface using JAAS”( developerWorks,2001 年 11 月)


“ Single Sign On Support in WebSphere Portal Server 1.2”讨论了 WebSphere Portal Server 的 JAAS 实现并展示了如何抽取用户数据并将其提供给一个 portlet 的后端应用程序,或者提供给同一个安全性域中的另一个 WebSphere Application Server。


如果您想深入了解 IBM 在 Java 安全性的发展中所起的历史性作用,请参阅文章“ The evolution of Java security”,在这篇文章中 IBM 工程师讨论了 JDK 1.2 安全性模型的优缺点。


您将在 IBM developerWorks Java 技术专区找到数百篇关于 Java 编程各个方面的文章。

关于作者
Carlos Fonseca 目前是 IBM Research 的软件工程师,他已经做了 10 年的专职软件开发工作。他开始是从事 C 和 Visual Basic 编程,然后转向 C++ 编程。在 最近六年中,Carlos 致力于面向对象的设计和使用 Java 平台进行开发,把他的专业技术应用于从 Swing GUI 单机应用程序到使用 J2EE 的服务器端应用程序等项目。当 Carlos 不再从事专业软件开发时,他还喜欢把编程作为业余爱好。您可以通过 cafonseca@us.ibm.com与 Carlos 联系。
分享到:
评论

相关推荐

    高校学生选课系统项目源码资源

    项目名称: 高校学生选课系统 内容概要: 高校学生选课系统是为了方便高校学生进行选课管理而设计的系统。该系统提供了学生选课、查看课程信息、管理个人课程表等功能,同时也为教师提供了课程发布和管理功能,以及管理员对整个选课系统的管理功能。 适用人群: 学生: 高校本科生和研究生,用于选课、查看课程信息、管理个人课程表等。 教师: 高校教师,用于发布课程、管理课程信息和学生选课情况等。 管理员: 系统管理员,用于管理整个选课系统,包括用户管理、课程管理、权限管理等。 使用场景及目标: 学生选课场景: 学生登录系统后可以浏览课程列表,根据自己的专业和兴趣选择适合自己的课程,并进行选课操作。系统会实时更新学生的选课信息,并生成个人课程表。 教师发布课程场景: 教师登录系统后可以发布新的课程信息,包括课程名称、课程描述、上课时间、上课地点等。发布后的课程将出现在课程列表中供学生选择。 管理员管理场景: 管理员可以管理系统的用户信息,包括学生、教师和管理员账号的添加、删除和修改;管理课程信息,包括课程的添加、删除和修改;管理系统的权限控制,包括用户权限的分配和管理。 目标: 为高校学生提

    TC-125 230V 50HZ 圆锯

    TC-125 230V 50HZ 圆锯

    影音娱乐北雨影音系统 v1.0.1-bymov101.rar

    北雨影音系统 v1.0.1_bymov101.rar 是一个计算机专业的 JSP 源码资料包,它为用户提供了一个强大而灵活的在线影音娱乐平台。该系统集成了多种功能,包括视频上传、播放、分享和评论等,旨在为用户提供一个全面而便捷的在线视频观看体验。首先,北雨影音系统具有强大的视频上传功能。用户可以轻松地将本地的视频文件上传到系统中,并与其他人分享。系统支持多种视频格式,包括常见的 MP4、AVI、FLV 等,确保用户能够方便地上传和观看各种类型的视频。其次,该系统提供了丰富的视频播放功能。用户可以选择不同的视频进行观看,并且可以调整视频的清晰度、音量等参数,以适应不同的观看需求。系统还支持自动播放下一个视频的功能,让用户可以连续观看多个视频,无需手动切换。此外,北雨影音系统还提供了一个社交互动的平台。用户可以在视频下方发表评论,与其他观众进行交流和讨论。这为用户之间的互动提供了便利,增加了观看视频的乐趣和参与感。最后,该系统还具备良好的用户体验和界面设计。界面简洁明了,操作直观易用,让用户可以快速上手并使用各项功能。同时,系统还提供了个性化的推荐功能,根据用户的观看历史和兴趣,为用户推荐

    Tripp Trapp 儿童椅用户指南 STOKKE

    Tripp Trapp 儿童椅用户指南

    node-v8.13.0-linux-armv6l.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    谷歌浏览器 64位-89.0.4389.128.exe

    Windows版本64位谷歌浏览器,是由Google谷歌公司开发的一款电脑版网络浏览器,可以运行在Windows 10/8.1/8/7 64位的操作系统上。该浏览器是基于其它开放原始码软件所撰写,包括WebKit和Mozilla,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。软件的特点是简洁、快速。并且支持多标签浏览,每个标签页面都在独立的“沙箱”内运行,在提高安全性的同时,一个标签页面的崩溃也不会导致其他标签页面被关闭。此外,谷歌浏览器(Google Chrome)基于更强大的JavaScript V8引擎,这是当前Web浏览器所无法实现的。

    适用于鲲鹏麒麟的OpenJDK1.8

    适用于鲲鹏麒麟的OpenJDK1.8

    毕业设计-基于SSH的任务调度系统的设计与实现

    任务调度试系统,基本功能包括:用户的注册、用户的登录、发起项目、项目详细及搜索等。本系统结构如下: (1)用户的注册登录: 注册模块:完成用户注册功能; 登录模块:完成用户登录功能; (2)发起项目: 发起项目模块:完成了项目及项目下一个或者多个任务的添加; 项目详细:点击项目名称,可以看到项目及任务详细信息; 搜索项目:完成对项目名称的模糊搜索功能 任务调度试系统,基本功能包括:用户的注册、用户的登录、发起项目、项目详细及搜索等。本系统结构如下: (1)用户的注册登录: 注册模块:完成用户注册功能; 登录模块:完成用户登录功能; (2)发起项目: 发起项目模块:完成了项目及项目下一个或者多个任务的添加; 项目详细:点击项目名称,可以看到项目及任务详细信息; 搜索项目:完成对项目名称的模糊搜索功能

    30个炫酷的数据可视化大屏(含源码)

    大屏数据可视化是以大屏为主要展示载体的数据可视化设计,30个可视化大屏包含源码,直接运行文件夹中的index.html,即可看到大屏。 内含:数据可视化页面设计;数据可视化演示系统;大数据可视化监管平台;智能看板;翼兴消防监控;南方软件视频平台;全国图书零售监测数据;晋城高速综合管控大数据;无线网络大数据平台;设备大数据;游戏数据大屏;厅店营业效能分析;车辆综合管控平台;政务大数据共享交换平台;智慧社区;物流云数据看板平台;风机可视化大屏等。

    基于yolov5识别算法实现的DNF自动脚本源码.zip

    优秀源码设计,详情请查看资源源码内容

    毕业设计:基于SSM的mysql-在线网上书店(源码 + 数据库 + 说明文档)

    毕业设计:基于SSM的mysql_在线网上书店(源码 + 数据库 + 说明文档) 2.系统分析与设计 3 2.1系统分析 3 2.1.1需求分析 3 2.1.2必要性分析 3 2.2系统概要设计 3 2.2.1 项目规划 3 2.2.2系统功能结构图 4 2.3开发及运行环境 4 2.4逻辑结构设计 5 2.4.1 数据库概要说明 5 2.4.2 主要数据表结构 6 2.5文件夹架构 9 2.6编写JAVA BEAN 9 3.网站前台主要功能模块设计 10 3.1前台首页架构设计 10 3.2网站前台首页设计 11 3.3新书上市模块设计 12 3.4特价书籍模块设计 13 3.5书籍分类模块设计 14 3.6会员管理模块设计 15 3.7购物车模块设计 17 3.8收银台设计模块 19 3.9畅销书籍模块设计 20 4.网站后台主要功能模块设计 21 4.1网站后台文件夹架构设计 21 4.2后台主页面设计 21 4.3书籍管理模块设计 22 4.4会员管理模块设计 25 4.5订单管理模块设计 26 4.6公告管理模块设计 28 4.7退出系统页面设计 29 5.网站制作中遇到的问

    python 开发 python爬虫数据可视化分析项目源码加课题报告,源码注解清晰一看就懂,适合新手.zip

    python 开发 python爬虫数据可视化分析项目源码加课题报告,源码注解清晰一看就懂,适合新手

    node-v8.0.0-linux-armv7l.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    使用FPGA发送一个经过曼彻斯特编码的伪随机序列

    rtl中存放的是设计文件 sim中存放的是仿真文件

    基于Java的班级管理系统课程设计源码

    附件是基于 Java的班级管理系统课程设计源码,包含程序说明和运行环境要求,文件绿色安全,仅供学习交流使用,欢迎大家下载学习交流!

    最新获取QQ微信头像橘头像阁PHP源码下载.rar

    最新获取QQ微信头像橘头像阁PHP源码下载.rar最新获取QQ微信头像橘头像阁PHP源码下载.rar

    K-750 管道疏通机手册

    K-750 管道疏通机手册 Drain Cleaner Manual K-750 Drain Cleaning Machine

    基于哈希链表的简单人员信息管理系统

    实现基于哈希表的员工信息管理系统,该系统主要用于处理员工信息,主要包括员工个人信息的录入、删除、查找、修改等,同时支持数据的导入导出

    node-v6.16.0.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    3D模型007,可用于建模、GIS、BIM、CIM学习

    3D模型007,可用于建模、GIS、BIM、CIM学习

Global site tag (gtag.js) - Google Analytics