- 浏览: 155659 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (113)
- Java工具类 (3)
- Hibernate (1)
- Struts>1&2 (0)
- Spring (0)
- Web前端 (1)
- 数据库 (2)
- 中间件 (3)
- 搜索引擎 (11)
- EJB (1)
- Log日志 (1)
- OS操作系统 (7)
- Java文档 (4)
- Security (1)
- Exception&Error (7)
- 日志&心情 (7)
- 开心一下 (3)
- 云计算 (41)
- Cache缓存 (4)
- MongoDB (1)
- OS操作系统 Linux (7)
- jquery (1)
- 机器学习 (2)
- Plugins (2)
- AJAX (1)
- Java工具 (1)
- WebService (1)
最新评论
-
a420144030:
你好,我想计算n篇文章的相似度,用mahout能处理吗,如何做 ...
mahout使用 -
di1984HIT:
OK,真的很牛啊
hadoop常见错误 -
xwl1991:
还真是这个问题 !
quartz报错java.lang.NoSuchMethodError: org.apache.commons.collections.SetUtils.ord
原文地址:http://www.ibm.com/developerworks/cn/views/java/tutorials.jsp?cv_doc_id=84887
关于作者
Brad Rubin 是 Brad Rubin & Associates Inc. 的负责人,该公司是一家专门从事无线网络与 Java 应用程序安全性和教育的计算机安全性咨询公司。Brad 在 IBM(位于明尼苏达州的 Rochester)工作了 14 年,从 AS/400 的第一个发行版开始, 就从事它的硬件和软件所有方面的开发。他是促使 IBM 转向支持 Java 平台的关键人物,并且是 IBM 最大的 Java 应用程序(称为 SanFrancisco (现在是 WebSphere 的一部分) 的商业应用程序框架产品)的首席架构设计师。他还是 Imation Corp. 数据存储部门(Data Storage Division)的首席技术官, 还是其研发组织的领导。
Brad 拥有计算机和电子工程学位,以及威斯康星大学麦迪逊分校计算机科学博士头衔。 他目前在明尼苏达大学教授电子和计算机工程高级设计(Senior Design)课程,并将于 2002 年秋季开发和教授该大学的计算机安全性(Computer Security)课程。可以通过 BradRubin@BradRubin.com 与 Brad 联系。
工具、代码样本和安装需求
JAAS 本来是 Java 2 平台标准版的扩展。然而,最近已将它添加到版本 1.4 中。要完成本教程,需要下列各项:
- JDK 1.4,标准版
- 教程源代码和类,以便您可以跟上我们的进度并理解示例。
- 支持 Java 1.4 插件的浏览器。
可以使用 JDK 1.3.x,但您必须自行安装 JCE 和 JSSE。
认证与授权
认证 是用户或计算设备用来验证身份的过程。授权 是根据请求用户的身份允许访问和操作一段敏感软件的过程。 这两个概念密不可分。没有授权, 就无需知道用户的身份。没能认证,就不可能区分可信和不可信用户, 更不可能安全地授权访问许多系统部分。
不一定要标识或认证个别实体;在某些情况下,可以通过分组,对给定组中的所有实体授予某种权限来进行认证。 在某些情况下,个别认证是系统安全性必不可少的环节。
认证与授权的另一个有趣方面是,一个实体在系统中可以有几个角色。 例如,用户可以同时是公司职工(表示他需要对公司的电子邮件有访问权)和该公司的会计师(表示他需要对公司财务系统有访问权)。
认证元素
认证基于以下一个或多个元素:
- 您知道什么。 该类别包括个别人知道而其它人一般不知道的信息。示例包括 PIN、密码和个人信息(如母亲的婚前姓)。
- 您有些什么。 该类别包括使个人能够访问资源的物理项。 示例包括 ATM 卡、Secure ID 令牌和信用卡。
- 您是谁。 该类别包括如指纹、视网膜剖面和面部照片等生物测定信息。
通常,对于授权只使用一种类别是不够的。例如,ATM 卡通常与 PIN 结合在一起使用。 即使物理卡丢失,用户和系统也能够安然无恙,因为小偷还必须知道 PIN 才能访问任何资源。
授权元素
有两种控制访问敏感代码的基本方法:
- 声明性 授权可以由系统管理员执行,他配置系统的访问权(即,声明谁可以访问系统中的哪些应用程序)。 通过声明性授权,可以添加、更改或取消用户访问特权,而不影响底层应用程序代码。
- 程序性 授权使用 Java 应用程序代码来做授权决定。 当授权决定需要更复杂的逻辑和决定(超出了声明性授权的能力范围)时,程序性授权是必需的。 因为程序性授权被构建到应用程序代码中,所以更改程序性授权时要求重写应用程序的部分代码。
您将在本教程中学习声明性和程序性授权技术。
保护用户和代码
根据用户在代码中的可信度,Java 平台允许对计算资源(如磁盘文件和网络连接)进行细颗粒度的访问控制。Java 平台的大多数基本安全性特性都是为保护用户免受潜在的恶意代码破坏而设计的。例如, 第三方证书支持的数字签名代码确保代码来源的身份。 根据用户对代码来源的了解,他可以选择授予或拒绝对该代码的执行权。同样,用户可以根据给定代码来源的下载 URL 授予或拒绝访问权。
基于 Java 的系统上的访问控制是通过策略文件实现的,该文件包含的语句如下:
grant signedBy "Brad", codeBase "http://www.bradrubin.com" {
permission java.io.FilePermission "/tmp/abc", "read";
};
该语句允许由“Brad”签署并从 http://www.bradrubin.com 装入的代码读取 /tmp/abc 目录。
其它 Java 平台特性(如缺少指针)进一步保护用户免受潜在的恶意代码破坏。JAAS 的认证和授权服务一起工作,提供了补充功能:它们防止敏感的 Java 应用程序代码遭到潜在的恶意用户破坏。
可插入认证模块
JAAS 实现“可插入认证模块(Pluggable Authentication Module(PAM))”框架的 Java 版本。Sun Microsystems 为其 Solaris 操作系统创建了 PAM;通过 JAAS,现在可以以独立于平台的形式使用 PAM。
PAM 的主要用途是允许应用程序开发人员在开发时写入标准认证接口, 并将使用哪些认证技术(以及如何使用它们)的决策留给系统管理员。 认证技术是在登录模块中实现的, 这些登录模块是在编写了应用程序之后部署的,并且在称为登录配置文件 (本教程中名为 login.config)的文本文件中指定。login.config 文件不仅可以指定要调用哪些模块,而且还可以指定总体认证成功的条件。
PAM 使新的认证技术或技巧能更方便地添加到现有应用程序中。 同样,可以通过更新 login.config 文件来更改认证策略,而不是重写整个应用程序。
JDK 1.4 是与下列 PAM 模块一起提供的。稍后,我们将在本教程中使用其中一个模块,并还要练习编写我们自己的两个模块:
-
com.sun.security.auth.module.NTLoginModule
-
com.sun.security.auth.module.NTSystem
-
com.sun.security.auth.module.JndiLoginModule
-
com.sun.security.auth.module.KeyStoreLoginModule
-
com.sun.security.auth.module.Krb5LoginModule
-
com.sun.security.auth.module.SolarisSystem
-
com.sun.security.auth.module.UnixLoginModule
-
com.sun.security.auth.module.UnixSystem
JAAS 示例和图
在本教程中,我们将逐一研究 JAAS 示例应用程序的代码。为了对总体情况有所了解, 下图显示了所有这些代码是如何组合在一起的。正在运行的示例(主程序 JAASExample)先使用两种技术(即两个登录模块)来认证用户,然后根据认证步骤的结果允许或禁止(或授权)访问两段敏感代码。
下面是 JAASExample 程序的图。下一页将描述操作流。
JAASExample 操作流
下面是由 JAASExample 图说明的总体认证与授权流的简要描述。以下每个步骤将在本教程的其它地方进行更为详细的描述。
我们从认证的第一步开始,就是要创建登录环境并试图登录。LoginContext
是一个 Java 类,它使用 login.config 文件中的信息来决定要调用哪些登录模块以及将使用什么标准来确定是否成功。 对本示例,有两个登录模块。 第一个登录模块是 AlwaysLoginModule
,它不需要密码,所以它总是成功的(这是不切实际的,但它足以说明 JAAS 是如何工作的)。 该模块用关键字 required
标记,表示它是成功所必需的(它总是成功)。第二个登录模块是PasswordLoginModule
,它需要密码,但该模块的成功与否是可选的,因为它用关键字 optional
标记。这表示即使 PasswordLoginModule
失败,但总体登录仍可成功。
初始化之后,选择的登录模块经历由 LoginContext
控制的两阶段提交过程。 作为该过程的一部分,调用 UsernamePasswordCallbackHandler
以获取个人(用 Subject
对象表示)的用户名和密码。如果认证成功,则 Principal
被添加到 Subject
中。Subject
可以有许多 Principal
(在该示例中,是“Brad”和“joeuser”),每个 Principal
都授予用户对系统的不同级别的访问权。这样就完成了认证步骤。
一旦认证完成,通过使用程序认证技术和 doAs
方法,用 Subject
来尝试执行一些敏感的工资单操作代码。JAAS 检查是否授予 Subject
访问权。 如果 Subject
有一个授权访问工资单代码的 Principal
, 那么允许继续执行。否则,将拒绝执行。
接下来,我们尝试使用声明性授权技术和 doAsPrivilaged
方法来执行一些敏感的职员信息操作代码。这次,JAAS 部署用户定义的特权(PersonnelPermission
)、Java 策略文件(jaas.policy)和 Java 访问控制器(AccessController
)用来决定是否可以继续执行。
Subject 和 Principal
Subject
是一种 Java 对象,它表示单个实体,如个人。 一个 Subject
可以有许多个相关身份,每个身份都由一个 Principal
对象表示。那么,比方说一个 Subject
表示要求访问电子邮件系统和财务系统的雇员。 该 Subject
将有两个 Principal
, 一个与用于电子邮件访问的雇员的用户标识关联, 另一个与用于财务系统访问的用户标识关联。
Principal
不是持久性的,所以每次用户登录时都必须将它们添加到 Subject
。Principal
作为成功认证过程的一部分被添加到 Subject
。 同样,如果认证失败,则从 Subject
中除去 Principal
。 不管认证成功与否,当应用程序执行注销时,将除去所有 Principal
。
除了包含一组 Principal
外,Subject
还可以包含两组凭证:公用和专用。credential
是密码、密钥和令牌等。对公用和专用凭证集的访问是由 Java 特权控制的, 稍后,我们将在本教程中讨论它。对凭证的完整讨论超出了本教程的范围。
Subject 的方法
Subject
对象有几个方法,其中一些方法如下:
-
subject.getPrincipals()
返回一组Principal
对象。因为结果是Set
,所以适用操作remove()
、add()
和contains()
。 -
subject.getPublicCredentials()
返回一组与Subject
相关的公用可访问凭证。 -
subject.getPrivateCredentials()
返回一组与Subject
相关的专用可访问凭证。
Principal 接口
Principal
是一个 Java 接口。程序员编写的 PrincipalImpl
对象与 Serializable
接口、名称字符串、返回该字符串的 getName()
方法以及其它支持方法(如 hashCode()
、toString()
和 equals()
)一起实现 Principal
接口。
在登录过程期间,Principal
被添加到 Subject
。正如我们稍后将看到的那样, 声明性授权基于策略文件中的项。进行授权请求时,将系统的授权策略与包含在 Subject
中的 Principal
进行比较。如果 Subject
有一个满足策略文件中安全性需求的 Principal
,则授权;否则拒绝。
PrincipalImpl
这里是我们将在本教程中使用的 PrincipalImpl
。
import java.io.Serializable;
import java.security.Principal
;
//
// This class defines the principle object, which is just an encapsulated
// String name
public class PrincipalImpl implements Principal, Serializable {
private String name;
public PrincipalImpl(String n) {
name = n;
}
public boolean equals(Object obj) {
if (!(obj instanceof PrincipalImpl)) {
return false;
}
PrincipalImpl pobj = (PrincipalImpl)obj;
if (name.equals(pobj.getName())) {
return true;
}
return false;
}
public String getName() {
return name;
}
public int hashCode() {
return name.hashCode();
}
public String toString() {
return getName();
}
}
登录配置
JAAS 允许在以下几个方面有极大的灵活性:Subject
需要的认证过程种类、它们的执行顺序以及在 Subject
被认为是已认证的之前要求的认证成功或失败的组合。
JAAS 使用 login.config 文件来指定每个登录模块的认证项。login.config
文件是在 Java 执行命令行上用特性 -Djava.security.auth.login.config==login.config
指定的。Java 有缺省登录配置文件,所以双等于号(==
)替换系统登录配置文件。如果使用一个等于号,login.config 文件将被添加到(而不是替换)系统登录配置文件。因为我们不知道您的系统文件中可能会有什么, 所以我们这样做来确保对于各种各样的教程用户都可以得到可靠的结果。
login.config 文件包含 LoginContext
构造器中引用的文本字符串和登录过程列表。 几个参数用于指定一个给定的登录过程的成功或失败对总体认证过程的影响。 有如下参数:
-
required
表示登录模块必须成功。即使它不成功,还将调用其它登录模块。 -
optional
表示登录模块可以失败,但如果另一个登录模块成功,总体登录仍可以成功。 如果所有登录模块都是可选的,那么要使整个认证成功至少必须有一个模块是成功的。 -
requisite
表示登录模块必须成功,而且如果它失败,将不调用其它登录模块。 -
sufficient
表示如果登录模块成功,则总体登录将成功,同时假设没有其它必需或必不可少的登录模块失败。
示例 login.config 文件
我们将在本教程中使用的 login.config 文件如下:
JAASExample {
AlwaysLoginModule required;
PasswordLoginModule optional;
};
正如您看到的那样,AlwaysLoginModule
必须成功,而 PasswordLoginModule
可以成功也可以失败。
这不是一种现实的情形,稍后我们将修改这些参数来查看不同的配置如何更改代码行为。
对于这项登录配置技术,应该认识到它将所有主要决定(如所需的认证类型和认证成功或失败的特定标准)都留到建立部署时决定,这很重要。 成功的登录将导致新的 Subject
添加到 LoginContext
, 同时将所有成功认证的 Principal
添加到该 Subject
。
登录环境
LoginContext
是一种用于设置登录过程的 Java 类,它进行实际的登录,如果登录成功,获取 Subject
。 它有如下四种主要方法:
-
LoginContext("JAASExample", newUsernamePasswoerdCallbackHandler())
是构造器。 它把 login.config 文件中使用的字符串作为其第一个参数,把执行实际任务的回调处理程序作为其第二个参数。 (接下来,我们将讨论回调处理程序。) -
login()
,它根据 login.config 文件中指定的规则实际尝试登录。 -
getSubject()
,如果登录总体成功,它返回经认证的Subject
。 -
logout()
,它向LoginContext
注销Subject
。
回调处理程序
JAAS 登录使用回调处理程序来获取用户的认证信息。CallbackHandler
是在 LoginContext
对象的构造函数中指定的。在本教程中,回调处理程序使用几个提示来获取用户的用户名和密码信息。 从登录模块调用的处理程序的 handle()
方法将 Callback
数组对象作为其参数。在登录期间,处理程序遍历 Callback
数组。handle()
方法检查 Callback
对象的类型并执行适当的用户操作。Callback
类型如下:
-
NameCallback
-
PasswordCallback
-
TextInputCallback
-
TextOutputCallback
-
LanguageCallback
-
ChoiceCallback
-
ConfirmationCallback
在某些应用程序中,因为 JAAS 将用于与操作系统的认证机制相互操作,所以不需要任何用户交互。 在这种情况下,LoginContext
对象中的 CallbackHandler
参数将是空的。
回调处理程序代码
下面是本教程中使用的 UsernamePasswordCallbackHandler
的代码。它由 AlwaysLoginModule
调用一次(仅一次回调以获取用户标识),由 PasswordLoginModule
调用一次(两次回调以获取用户标识和密码)。
import java.io.*;
import java.security.*;
import javax.security.auth.*;
import javax.security.auth.callback.*;
//
// This class implements a username/password callback handler that gets
// information from the user
public class UsernamePasswordCallbackHandler implements CallbackHandler {
//
// The handle method does all the work and iterates through the array
// of callbacks, examines the type, and takes the appropriate user
// interaction action.
public void handle(Callback[] callbacks) throws
UnsupportedCallbackException, IOException {
for(int i=0;i<callbacks.length;i++) {
Callback cb = callbacks[i];
//
// Handle username aquisition
if (cb instanceof NameCallback) {
NameCallback nameCallback = (NameCallback)cb;
System.out.print( nameCallback.getPrompt() + "? ");
System.out.flush();
String username = new BufferedReader(
new InputStreamReader(System.in)).readLine();
nameCallback.setName(username);
//
// Handle password aquisition
} else if (cb instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback)cb;
System.out.print( passwordCallback.getPrompt() + "? ");
System.out.flush();
String password = new BufferedReader(
new InputStreamReader(System.in)).readLine();
passwordCallback.setPassword(password.toCharArray());
password = null;
//
// Other callback types are not handled here
} else {
throw new UnsupportedCallbackException(cb, "Unsupported
Callback Type");
}
}
}
}
登录模块
LoginModule
是参与 JAAS 认证过程所需的方法的接口。 因为可能要到执行其它登录过程时才知道特定登录过程是成功还是失败,所以用两阶段提交过程来确定是否成功。 下列方法由 LoginModule
对象实现:
-
initialize( subject, callbackHandler, sharedState, options)
初始化LoginModule
。(注:对sharedState
和options
的讨论超出了本教程的范围。) -
login()
设置任何必需的回调,调用CallbackHandler
来处理它们, 并将返回的信息(即用户名和密码)与允许值进行比较。如果匹配,则登录模块成功, 尽管仍可能因为另一个登录模块不成功而异常终止它,这取决于 login.config 文件中的设置。 -
commit()
作为两阶段提交过程的一部分被调用以确定是否成功。 如果根据 login.config 文件中指定的约束,所有登录模块都是成功的, 那么新的Principal
随同用户名一起创建,并被添加到Subject
的主体集。 -
abort()
,如果总体登录未成功,则调用它;如果发生异常终止,必须清除内部的LoginModule
状态。 -
logout()
被调用以除去Subject
的主体集中的Principal
并执行其它内部状态清除。
下面两页说明了两个登录模块。第一个是 AlwaysLoginModule
,它始终是成功的。 第二个是 PasswordLoginModule
,仅当用户标识和密码与某些硬编码值匹配时,它才会成功。 虽然两个示例模块都不是合乎实际的实现,但它们共同演示了各种 JAAS 选项的结果。
AlwaysLoginModule
AlwaysLoginModule
认证将始终成功, 所以实际上它仅用于通过 NameCallback
函数获取用户名。 假设其它登录模块都成功,AlwaysLoginModule
的 commit()
方法将创建一个带用户名的新 PrincipalImpl
对象并将它添加到 Subject
的 Principal
集中。注销将除去 Subject
的 Principal
集 中的 PrincipalImpl
。
import java.security.*;
import javax.security.auth.*;
import javax.security.auth.spi.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import java.io.*;
import java.util.*;
// This is a JAAS Login Module that always succeeds. While not realistic,
// it is designed to illustrate the bare bones structure of a Login Module
// and is used in examples that show the login configuration file
// operation.
public class AlwaysLoginModule implements LoginModule {
private Subject
subject;
private Principal
principal;
private CallbackHandler callbackHandler;
private String username;
private boolean loginSuccess;
//
// Initialize sets up the login module. sharedState and options are
// advanced features not used here
public void initialize(Subject
sub, CallbackHandler cbh,
Map sharedState, Map options) {
subject = sub;
callbackHandler = cbh;
loginSuccess = false;
}
//
// The login phase gets the userid from the user
public boolean login() throws LoginException {
//
// Since we need input from a user, we need a callback handler
if (callbackHandler == null) {
throw new LoginException( "No CallbackHandler defined");
}
Callback[] callbacks = new Callback[1];
callbacks[0] = new NameCallback("Username");
//
// Call the callback handler to get the username
try {
System.out.println( "\nAlwaysLoginModule Login" );
callbackHandler.handle(callbacks);
username = ((NameCallback)callbacks[0]).getName();
} catch (IOException ioe) {
throw new LoginException(ioe.toString());
} catch (UnsupportedCallbackException uce) {
throw new LoginException(uce.toString());
}
loginSuccess = true;
System.out.println();
System.out.println( "Login: AlwaysLoginModule SUCCESS" );
return true;
}
//
// The commit phase adds the principal if both the overall authentication
// succeeds (which is why commit was called) as well as this particular
// login module
public boolean commit() throws LoginException {
//
// Check to see if this login module succeeded (which it always will
// in this example)
if (loginSuccess == false) {
System.out.println( "Commit: AlwaysLoginModule FAIL" );
return false;
}
//
// If this login module succeeded too, then add the new principal
// to the subject (if it does not already exist)
principal = new PrincipalImpl(username);
if (!(subject.getPrincipals().contains(principal))) {
subject.getPrincipals().add(principal);
}
System.out.println( "Commit: AlwaysLoginModule SUCCESS" );
return true;
}
//
// The abort phase is called if the overall authentication fails, so
// we have to clean up the internal state
public boolean abort() throws LoginException {
if (loginSuccess == false) {
System.out.println( "Abort: AlwaysLoginModule FAIL" );
principal = null;
return false;
}
System.out.println( "Abort: AlwaysLoginModule SUCCESS" );
logout();
return true;
}
//
// The logout phase cleans up the state
public boolean logout() throws LoginException {
subject.getPrincipals().remove(principal);
loginSuccess = false;
principal = null;
System.out.println( "Logout: AlwaysLoginModule SUCCESS" );
return true;
}
}
PasswordLoginModule
PasswordLoginModule
使用 NameCallback
来获取用户名并使用 PasswordCallback
来获取密码。如果用户名是“joeuser”,密码是“joe”, 则该认证将成功。
import java.security.*;
import javax.security.auth.*;
import javax.security.auth.spi.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import java.io.*;
import java.util.*;
//
// This is a JAAS Login Module that requires both a username and a
// password. The username must equal the hardcoded "joeuser" and
// the password must match the hardcoded "joeuserpw".
public class PasswordLoginModule implements LoginModule {
private Subject
subject;
private Principal
principal;
private CallbackHandler callbackHandler;
private String username;
private char[] password;
private boolean loginSuccess;
//
// Initialize sets up the login module. sharedState and options are
// advanced features not used here
public void initialize(Subject
sub, CallbackHandler cbh,
Map sharedState,Map options) {
subject = sub;
callbackHandler = cbh;
loginSuccess = false;
username = null;
clearPassword();
}
//
// The login phase gets the userid and password from the user and
// compares them to the hardcoded values "joeuser" and "joeuserpw".
public boolean login() throws LoginException {
//
// Since we need input from a user, we need a callback handler
if (callbackHandler == null) {
throw new LoginException("No CallbackHandler defined");
}
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("Username");
callbacks[1] = new PasswordCallback("Password", false);
//
// Call the callback handler to get the username and password
try {
System.out.println( "\nPasswordLoginModule Login" );
callbackHandler.handle(callbacks);
username = ((NameCallback)callbacks[0]).getName();
char[] temp = ((PasswordCallback)callbacks[1]).getPassword();
password = new char[temp.length];
System.arraycopy(temp, 0, password, 0, temp.length);
((PasswordCallback)callbacks[1]).clearPassword();
} catch (IOException ioe) {
throw new LoginException(ioe.toString());
} catch (UnsupportedCallbackException uce) {
throw new LoginException(uce.toString());
}
System.out.println();
//
// If username matches, go on to check password
if ( "joeuser".equals(username)) {
System.out.println
( "Login: PasswordLoginModule Username Matches" );
if ( password.length == 5 &&
password[0] == 'j' &&
password[1] == 'o' &&
password[2] == 'e' &&
password[3] == 'p' &&
password[4] == 'w' ) {
//
//If userid and password match, then login is a success
System.out.println
( "Login: PasswordLoginModule Password Matches" );
loginSuccess = true;
System.out.println
( "Login: PasswordLoginModule SUCCESS" );
clearPassword();
return true;
} else {
System.out.println
( "Login: PasswordLoginModule Password Mismatch" );
}
} else {
System.out.println( "Login: PasswordLoginModule Username Mismatch" );
}
//
// If either mismatch, then this login module fails
loginSuccess = false;
username = null;
clearPassword();
System.out.println( "Login: PasswordLoginModule FAIL" );
throw new FailedLoginException();
}
//
// The commit phase adds the principal if both the overall
// authentication succeeds (which is why commit was called)
// as well as this particular login module
public boolean commit() throws LoginException {
//
// Check to see if this login module succeeded
if (loginSuccess == false) {
System.out.println( "Commit: PasswordLoginModule FAIL" );
return false;
}
// If this login module succeeded too, then add the new principal
// to the subject (if it does not already exist)
principal = new PrincipalImpl(username);
if (!(subject.getPrincipals().contains(principal))) {
subject.getPrincipals().add(principal);
}
username = null;
System.out.println( "Commit: PasswordLoginModule SUCCESS" );
return true;
}
//
// The abort phase is called if the overall authentication fails, so
// we have to cleanup the internal state
public boolean abort() throws LoginException {
if (loginSuccess == false) {
System.out.println( "Abort: PasswordLoginModule FAIL" );
principal = null;
username = null;
return false;
}
System.out.println( "Abort: PasswordLoginModule SUCCESS" );
logout();
return true;
}
//
// The logout phase cleans up the state
public boolean logout() throws LoginException {
subject.getPrincipals().remove(principal);
loginSuccess = false;
username = null;
principal = null;
System.out.println( "Logout: PasswordLoginModule SUCCESS" );
return true;
}
//
// Private helper function to clear the password, a good programming
// practice
private void clearPassword() {
if (password == null) {
return;
}
for (int i=0;i<password.length;i++) {
password[i] = ' ';
}
password = null;
}
}
Java 平台使用访问控制环境(access control context)
的概念来确定当前执行线程的权限。
从概念上讲,可以将它视作与每个执行线程连接的令牌。 在 JAAS 之前,访问控制基于了解当前 Java .class
文件的代码来源或数字签名者的身份。在这种模型下, 访问控制是基于了解代码出自于何处。有了 JAAS,我们将模型转了个向。通过将 Subject
添加到访问控制环境, 我们可以开始根据谁正在执行(或要求执行)一段给定代码来授予或拒绝访问权。
访问控制和权限
因为执行线程可以跨越多个具有不同环境特征的模块,所以 Java 平台实现了最小特权 这一概念。 在属于给定执行线程的整个调用程序栈中,调用栈的成员具有不同特征, 用于确定权限的结果是所有这些特征的交集或最小公分母。例如, 如果一段调用代码有受限权限(可能由于未对它签名,所以它不可信),但它调用一段信任度较高的代码(可能有一个签名), 则降低 被调用代码中的权限来匹配较低的信任度。
将包含在访问控制环境中的权限特征与策略文件中的 Java 权限 grant
语句进行比较,以表明是否允许敏感操作。这是由名为 AccessController
的 Java 实用程序完成的,它的接口用于通过程序检查特权以及将当前的 Subject
与活动的访问控制环境相关联。(较旧的 Java 安全性管理器(Java Security Manager)接口已经过时,所以一定要使用 AccessController
方法。)
将 Subject 绑定到访问控制环境
因为可以在应用程序启动之后认证 Subject
, 所以必须有一个将 Subject
动态绑定到访问控制环境的方法,以创建一个包含代码权限(从何处装入它以及谁对它进行签名)和用户权限(Subject
)环境。 为此,我们使用方法 Object doAs(Subject subject, PrivilegedAction action)
。 这个 doAs
方法调用特别为授权设计的类, 该类实现 PrivilegedAction
接口。
如果不使用线程的当前方法,则可以使用另一种调用方法 Object doAsPrivileged(Subject, PrivilegedAction action, AccessControlContext acc)
来指定访问控制环境。它的特殊用法是将 AccessControlContext
设置为空, 在 doAsPrivileged
调用发生时,可以使调用栈短路,并且在 PrivilegedAction
对象中时,允许增加
权限。稍后,当对象返回到调用程序时,将减少权限。本教程稍后将说明这两种技术。
doAs
和 doAsPrivileged
方法形式上都允许抛出 PrivilegedActionException
。
权限
Java 平台有许多用于控制对系统资源的访问的内置权限。 例如:
grant signedBy "Brad", codeBase "http://www.bradrubin.com" {
permission java.io.FilePermission "/tmp/abc", "read";
};
允许由“Brad”签名的并从“http://www.bradrubin.com”装入的代码读取 /tmp/abc
目录。有关 Java 权限的完整列表,请参阅参考资料
。
创建您自己的权限
Java 平台允许您创建自己的权限对象。与正规的权限相似, 可以将这些对象放在策略文件中,并在部署时配置它们。 为了进行演示,请查看下面的 PersonnelPermission
。 稍后,我们将使用这些代码以允许访问一些敏感的职员信息操作的代码。
import java.security.*;
//
// Implement a user defined permission for access to the personnel
// code for this example
public class PersonnelPermission extends
BasicPermission {
public PersonnelPermission(String name) {
super(name);
}
public PersonnelPermission(String name, String action) {
super(name);
}
}
对于上面的权限,您应该注意以下几点:
第一,构造器使用用户定义的特权名称(在这个示例中,只有一种名为
access
的类型)。另外一个构造器使用名为 action
的附加的改进的参数,虽然这里不使用它。对于这个示例,将使用 BasicPermission
类。
如果我们需要更多特性,可以使用 Permission
类。
策略文件
策略文件是控制对系统资源(包括敏感代码)访问的主要机制。 本示例中的策略文件名为 jaas.policy,并且在 Java 命令行中由特性 -Djava.security.policy==jaas.policy
指定。双等于号(==
)表明将替换系统策略文件, 而不是添加到系统策略文件权限中。下面是我们正在本教程中使用的 jaas.policy 文件:
grant {
permission javax.security.auth.AuthPermission "createLoginContext";
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.AuthPermission "doAsPrivileged";
permission javax.security.auth.AuthPermission "modifyPrincipals";
permission javax.security.auth.AuthPermission "getSubject"; };
grant principal PrincipalImpl "Brad" {
permission PersonnelPermission "access";
};
为了使 JAAS 机制自举,系统必须有某些特权 — 即示例中的前五个。 通过这些适当的权限,将访问权 PersonnelPermission
(用户定义的权限)授予“Brad”主体。
JAAS 主程序示例
下面是这个示例的主应用程序(从命令行调用)。 它实例化登录环境、然后登录、尝试执行两个敏感对象(一个对象使用程序性授权,另一个对象使用声明性授权),最后注销。 接下来,我们将更深入地研究主程序的两个元素:程序性授权和声明性授权。
import java.security.*;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
//
// This is the main program in the JAAS Example. It creates a Login
// Context, logs the user in based on the settings in the Login
// Configuration file,and calls two sensitive pieces of code, the
// first using programmatic authorization, and the second using
// declarative authorization.
public class JAASExample {
static LoginContext lc = null;
public static void main( String[] args) {
//
// Create a login context
try {
lc = new LoginContext("JAASExample",
new UsernamePasswordCallbackHandler());
} catch (LoginException le) {
System.out.println( "Login Context Creation Error" );
System.exit(1);
}
//
// Login
try {
lc.login();
} catch (LoginException le) {
System.out.println( "\nOVERALL AUTHENTICATION FAILED\n" );
System.exit(1);
}
System.out.println( "\nOVERALL AUTHENTICATION SUCCEEDED\n" );
System.out.println( lc.getSubject() );
//
// Call the sensitive PayrollAction code, which uses programmatic
// authorization.
try {
Subject
.doAs( lc.getSubject(), new PayrollAction() );
} catch (AccessControlException e) {
System.out.println( "Payroll Access DENIED" );
}
//
// Call the sensitive PersonnelAction code, which uses declarative
// authorization.
try {
Subject
.doAsPrivileged( lc.getSubject(), new PersonnelAction(), null );
} catch (AccessControlException e) {
System.out.println( "Personnel Access DENIED" );
}
try {
lc.logout();
} catch (LoginException le) {
System.out.println( "Logout FAILED" );
System.exit(1);
}
System.exit(0);
}
}
程序性授权示例
在这个示例中,我们将了解如何编码程序权限决定。PrivilegedAction
类由主 JAASExample 程序的 doAs
方法调用,因此当它输入 run
方法时,经认证的 Subject
被绑定到线程上的应用程序环境。
我们从访问控制器检索当前的 Subject
,遍历任何包含的经认证的 Principal
,以查找“joeuser”。如果找到他,则可以进行敏感的操作并返回。 如果找不到,我们抛出一个 AccessControlException
。显然,在现实生活中我们应该使用更易于管理且可伸缩的技术, 而不是将用户名直接硬编码到应用程序中。
import java.io.*;
import java.security.*;
import javax.security.auth.*;
import javax.security.auth.login.*;
import java.util.*;
//
// This class is a sensitive Payroll function that demonstrates the
// use of programmatic authorization which only allows a subject
// that contains the principal "joeuser" in
class PayrollAction implements PrivilegedAction {
public Object run() {
// Get the passed in subject from the DoAs
AccessControlContext context = AccessController.getContext();
Subject
subject = Subject
.getSubject(context );
if (subject == null ) {
throw new AccessControlException("Denied");
}
//
// Iterate through the principal set looking for joeuser. If
// he is not found,
Set principals = subject.getPrincipals();
Iterator iterator = principals.iterator();
while (iterator.hasNext()) {
PrincipalImpl principal = (PrincipalImpl)iterator.next();
if (principal.getName().equals( "joeuser" )) {
System.out.println("joeuser has Payroll access\n");
return new Integer(0);
}
}
throw new AccessControlException("Denied");
}
}
声明性授权示例
在这个示例中,我们将通过使用用户定义的权限 PersonnelPermission
, 来演示如何用策略文件中的权限授予以声明性授权的方式来控制授权检查。 我们只询问 AccessController
是否已经授予这个权限, 如果没有授予,它抛出一个 AccessControlException
,否则,如果已经授予,则保持运行。 我们用主 JAASExample 代码中的 doAsPrivileged
调用和空访问控制环境来调用 这个 PrivilegedAction
,以使调用时调用栈短路。 因为在将 Subject
与 doAsPrivileged
调用中的环境结合之前,Subject
不是环境的一部分,也未经 grant 语句授权,而且还因为使用了“最小特权”和权限的交集, 所以这是必需的,否则将不允许提高权限的级别。
import java.io.*;
import java.security.*;
//
// This class is a sensitive Personnel function that demonstrates
// the use of declarative authorization using the user defined
// permission PersonnelPermission, which throws an exception
// if it not granted
class PersonnelAction implements PrivilegedAction {
public Object run() {
AccessController.checkPermission(new PersonnelPermission("access"));
System.out.println( "Subject
has Personnel access\n");
return new Integer(0);
}
}
运行示例
设计 JAASExample 应用程序的目的是为了演示几种认证和授权技术以及一些配置设置的影响。 用下列语句开始运行该示例,可以在教程源文件(请参阅参考资料)中的文件 run.bat 中找到这些语句。
java -Djava.security.manager
-Djava.security.auth.login.config==login.config
-Djava.security.policy==jaas.policy JAASExample
语句指示系统的缺省安全性管理器使用名为 login.config 的登录配置文件,
使用名为 jaas.policy 的安全性策略文件,最后运行主应用程序 JAASExample。注:
双等于号(==
)表明系统缺省登录配置和策略文件不
应该添加到已在这里列出的各项中。
一个等于号(=
)表明应该将文件与系统缺省值并置。
示例结果和说明
下面是运行 JAASExample 的结果:
AlwaysLoginModule Login
Username? Brad
Login: AlwaysLoginModule SUCCESS
PasswordLoginModule Login
Username? joeuser
Password? joepw
Login: PasswordLoginModule Username Matches
Login: PasswordLoginModule Password Matches
Login: PasswordLoginModule SUCCESS
Commit: AlwaysLoginModule SUCCESS
Commit: PasswordLoginModule SUCCESS
OVERALL AUTHENTICATION SUCCEEDED
Subject
:
Principal
: Brad
Principal
: joeuser
joeuser has Payroll access
Subject
has Personnel access
Logout: AlwaysLoginModule SUCCESS
Logout: PassswordLoginModule SUCCESS
下面详尽地描述了上面结果中的正常执行情况:
-
login.config
定义两个登录模块;AlwaysLoginModule
是必需的。它先运行。 -
AlwaysLoginModule
在登录阶段启动,它调用回调处理程序来获取用户名(Brad
)。登录成功。 - 第二个登录模块
PasswordLoginModule
是可选的。它接下来运行,调用回调处理程序以获取用户名(joeuser
)和密码(joepw
),两者都是匹配的。该登录也是成功的。 - 因为必需的和可选的模块都成功,所以在两个登录模块上同时调用
commit
, 并且整个认证成功。结果,Subject
同时包含两个Principal
:Brad
和joeuser
。 - 使用程序性授权的工资单程序检查
joeuser
是否在Subject
的Principal
集中,如果是,授予它访问权。 - 使用声明性授权的职员信息程序查看 jaas.policy 文件中是否有授权语句,授予
Brad
PersonnelPermission
的特权,所以它也成功。 - 两个登录模块同时注销。
失败的认证
只是为了好玩,让我们看一下当我们出差错时会发生什么情况。 在下面的示例中,设置是相同的,但我们将为 joeuser
输入一个错误密码。请亲自检查下面的输出,看一下它与上面的结果有何不同。
AlwaysLoginModule Login
Username? Brad
Login: AlwaysLoginModule SUCCESS
PasswordLoginModule Login
Username? joeuser
Password? wrongpw
Login: PasswordLoginModule Username Matches
Login: PasswordLoginModule Password Mismatch
Login: PasswordLoginModule FAIL
Commit: AlwaysLoginModule SUCCESS
Commit: PasswordLoginModule FAIL
OVERALL AUTHENTICATION SUCCEEDED
Subject
:
Principal
: Brad
Payroll Access DENIED
Subject
has Personnel access
Logout: AlwaysLoginModule SUCCESS
Logout: PasswordLoginModule SUCCESS
正如您所看到的那样,PasswordLoginModule
登录已经失败。 但是,因为这个模块在 login.config 文件中配置为 optional
, 所以总体认证仍是成功的。区别在于只有 Brad Principal
被添加到 Subject
中。 工资单程序找不到 joeuser Principal
,所以访问被拒绝。 职员信息程序可以将 Brad Principal
与 Brad
授权语句匹配, 所以它被成功添加并授予访问权。
在接下来的几页中,我们将对 login.config 文件的配置作一些修改,然后检查每种新配置的结果。
变体 1:登录配置
首先,让我们看一下当我们将 login.config 文件更改为: 为了认证成功,两个 登录模块都是必需的,会是什么情况。新的 config 文件是:
JAASExample {
AlwaysLoginModule required;
PasswordLoginModule required;
};
这里是结果输出:
AlwaysLoginModule Login
Username? Brad
Login: AlwaysLoginModule SUCCESS
PasswordLoginModule Login
Username? joeuser
Password? wrongpw
Login: PasswordLoginModule Username Matches
Login: PasswordLoginModule Password Mismatch
Login: PasswordLoginModule FAIL
Abort: AlwaysLoginModule SUCCESS
Logout: AlwaysLoginModule SUCCESS
Abort: PasswordLoginModule FAIL
OVERALL AUTHENTICATION FAILED
当 joeuser
输入错误密码时,PasswordLoginModule
就会象先前那样失败。 然而,因为该模块是必需的,所以运行异常终止阶段并且总体认证失败。 不执行任何敏感代码。
变体 2:PAM 的能力
该变体是为演示可插入的认证模块的实用程序而设计的。我们回到原始的 login.config 文件,即 AlwaysLoginModule
是必需的,而 PasswordLoginModule
是可选的, 然后将 NTLoginModule
(或适用于您的平台的任何其它模块)添加到该文件。 新模块将是 required
。修改后的 login.config 文件应该看起来如下:
JAASExample {
AlwaysLoginModule required;
PasswordLoginModule optional;
com.sun.security.auth.module.NTLoginModule required;
};
接下来,运行示例。在下面的输出中,您将看到已经添加了一个新的认证方法以及几个全新的 Principal
(和一个公用凭证)。
AlwaysLoginModule Login
Username? Brad
Login: AlwaysLoginModule SUCCESS
PasswordLoginModule Login
Username? joeuser
Password? joepw
Login: PasswordLoginModule Username Matches
Login: PasswordLoginModule Password Matches
Login: PasswordLoginModule SUCCESS
Commit: AlwaysLoginModule SUCCESS
Commit: PasswordLoginModule SUCCESS
OVERALL AUTHENTICATION SUCCEEDED
Subject
:
Principal
: Brad
Principal
: joeuser
Principal
: NTUserPrincipal: Brad
Principal
: NTDomainPrincipal: WORKGROUP
Principal
: NTSidUserPrincipal:
S-1-5-21-2025429265-1580813891-854245398-1004
Principal
: NTSidPrimaryGroupPrincipal:
S-1-5-21-2025429265-1580418891-85 4245398-513
Principal
: NTSidGroupPrincipal:
S-1-5-21-2025429265-1580818891-854245398-513
Principal
: NTSidGroupPrincipal: S-1-1-0
Principal
: NTSidGroupPrincipal: S-1-5-32-544
Principal
: NTSidGroupPrincipal: S-1-5-32-545
Principal
: NTSidGroupPrincipal: S-1-5-5-0-49575
Principal
: NTSidGroupPrincipal: S-1-2-0
Principal
: NTSidGroupPrincipal: S-1-5-4
Principal
: NTSidGroupPrincipal: S-1-5-11
Public Credential: NTNumericCredential: 1240
joeuser has Payroll access
Subject
has Personnel access
Logout: AlwaysLoginModule SUCCESS
Logout: PasswordLoginModule SUCCESS
更酷的是,我们甚至不必自己改动我们的应用程序代码。上面所有的更改都是由本机 OS 认证机制完成的。 这应该向您暗示了 PAM 的能力。
变体 3:策略文件配置
在最后一个变体中,我们将查看当修改访问控制策略时会发生什么情况。 我们从修改原始 login.config
中的 grant 文件开始,以便 joeuser
(而不是 Brad
)有 PersonnelPermission
,如下所示:
grant Principal
PrincipalImpl "joeuser" {
permission PersonnelPermission "access";
};
接下来,运行应用程序,为 joeuser
输入错误密码。结果如下所示:
AlwaysLoginModule Login
Username? Brad
Login: AlwaysLoginModule SUCCESS
PasswordLoginModule Login
Username? joeuser
Password? wrongpw
Login: PasswordLoginModule Username Matches
Login: PasswordLoginModule Password Mismatch
Login: PasswordLoginModule FAIL
Commit: AlwaysLoginModule SUCCESS
Commit: PasswordLoginModule FAIL
OVERALL AUTHENTICATION SUCCEEDED
Subject
:
Principal
: Brad
Payroll Access DENIED
Personnel Access DENIED
Logout: AlwaysLoginModule SUCCESS
Logout: PasswordLoginModule SUCCESS
正如您所看到,Subject
的 Principal
集中只有 Brad
。 工资单访问和职员信息访问的尝试都已失败。为什么?第一次尝试失败是因为没有名为 joeuser
的 Principal
,第二次尝试失败是因为对于 Brad
没有授予权限语句。
不要在此止步
在本章中,我们已经将所有 JAAS 认证和授权片段合在一起来说明完整的 JAAS 应用程序的运行情况。 我们还对应用程序做了几次改动以观察它实际上发生了什么以及该体系结构在应用程序安全性方面有多灵活。
为了扩展您在这里学到的知识,您应该继续使用 JAAS 并查看当尝试不同的登录配置时会发生什么情况。 例如,如果在您的安装中运行着 Kerberos,尝试运行 Kerberos 登录模块。
参考资料
下载
- 下载本教程中使用的完整源代码和类。
- 可从 Sun Microsystems 获得 Java 2 平台,标准版 (http://java.sun.com/j2se/)。
文章、教程和其它在线参考资料
- 请阅读由 Brad Rubin 编写的本教程系列的第 1 部分,“Crypto basics ,”(http://www-106.ibm.com/developerworks/education/r-jsec1.html)。
- 请参阅 Java 开发人员连接(Java Developer Connection), 以获取完整的 Java 权限 (http://java.sun.com/j2se/1.4/docs/guide/security/permissions.html)的列表。
- 虽然本教程中未论及新近与 JDK 1.4 一起提供的 Java 通用安全性服务(Java General Security Service(JGSS)), 但它提供了用于在应用程序之间安全地交换消息的通用框架。Sun 最新发布的白皮书 (http://java.sun.com/j2se/1.4/docs/guide/security/jgss/single-signon.html)讨论了如何使用 JAAS、JGSS 和 Kerberos 来提供单点登录应用程序安全性。
- Sun 还拥有几个描述 JAAS 和 JGSS 的不同使用方法和过程的教程和用户指南 (http://java.sun.com/j2se/1.4/docs/guide/security/jgss/tutorials/)。有一个极好的参考指南描述了 when to use JGSS versus JSEE (http://java.sun.com/j2se/1.4/docs/guide/security/jgss/tutorials/JGSSvsJSSE.html)。
- 请参阅 Sun Microsystems 的 Java Security 站点 (http://java.sun.com/security),学习更多有关最新 Java 安全性技术的知识。
- Joseph Sinclair 在系列文章“Securing systems ”中, 提供了一篇“A three-pronged solution for identifying users”(developerWorks ,2001 年 6 月,http://www-106.ibm.com/developerworks/library/j-secure/index.html)。
- 一旦您掌握了基本知识,Carlos Fonseca 将向您展示如何“Extend JAAS for class instance-level authorization ”(developerWorks ,2002 年 4 月,http://www-106.ibm.com/developerworks/library/j-jaas/)。
- 在“Enhance Java GSSAPI with a login interface using JAAS ”中,Thomas Owusu 提供了有关凭证和秘钥的一些颇有见地的观点(developerWorks ,2001 年 11 月,http://www-106.ibm.com/developerworks/library/j-gssapi/)。
- 查找 WebSphere Portal Server 1.2 如何实现 JAAS 和单点登录安全性 (WebSphere 开发者园地,2001 年 10 月)。
书籍
- 有关 Web 安全性和 Java 技术的全面讨论,请参阅由 O’Reilly 于 2002 年出版的 Web Security, Privacy, and Commerce,第二版 (由 Simson Garfinkel 和 Gene Spafford 合著)。
- 如果您想更进一步了解 Java 安全性,请参阅 Wrox Press 于 2001 年出版的 Professional Java Security (http://www.amazon.com/exec/obidos/ASIN/1861004257/104-8739833-1347930)(由 Jess Garms 和 Daniel Somerfield 合著)。
- 另一本学习 Java 安全性的优秀参考资料是由 O’Reilly & Associates 于 2001 年出版的 Java Security (http://www.amazon.com/exec/obidos/ASIN/0596001576)(Scott Oaks 著)。
- 从 Secrets and Lies: Digital Security in a
发表评论
相关推荐
shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权 传统使用URL拦截的时候,要将所有的URL都配置起来,繁琐、不易维护 而我们的Shiro实现系统的权限管理,有效提高开发效率,从而...
Tomcat是一个流行的开源Java Servlet容器,它提供了内置的安全功能,包括用户认证和授权,这些功能是通过“域”这一概念来实现的。 域在Tomcat中是一个用户数据库,类似于Unix中的用户群组。它存储了用户信息,包括...
安全通道协议是在智能卡与外界设备通信时,保证数据传输的安全性。它确保了通信数据的机密性、完整性和认证性。SCP03使用特定密钥加密数据,这些密钥在安全域中管理,安全域可以理解为卡片上相对独立的安全存储空间...
总之,这个“简单发布到Twitter的脚本”是一个帮助开发者轻松实现本地内容同步到Twitter的工具,通过OAuth确保安全性,而提供的源码则有助于进一步学习和自定义。如果你正在寻找一种方式将本地系统(比如个人博客)...
5. **安全性**:介绍了 Java EE 6 中的安全性框架,包括认证、授权和加密机制。 6. **批处理和调度**:讨论了使用 Java Batch 和 Java EE 6 的定时任务机制来进行批量数据处理和任务调度的方法。 7. **消息传递**:...
影子库可以用于测试和验证新功能,而数据加密则保证了敏感数据的安全性。 5. **SPI扩展**:ShardingSphere的SPI(Service Provider Interface)机制允许开发者自定义扩展,比如分片策略、事务管理器等,以适应特定...
2. **Project Tango** (也称作Tango)—— 实现了可靠性、安全性和事务处理相关的WS-*规范,并支持与.NET 3.0的互操作性。 **Java API for XML Web Services (JAX-WS) RI** 提供了核心Web服务平台,包括所有SOAP...
Seam 提供了一套强大的安全机制,包括认证、授权和加密等功能,以确保应用程序的安全性。 - **Ajax 和 JavaScript 远程调用**:Seam 支持 AJAX 和 JavaScript 远程调用,这意味着开发者可以构建响应迅速且用户体验...
9. **安全性考虑**:开发Web服务时,安全性是一个重要的方面,包括认证、授权、加密等,需要了解如何在PB9和EAServer中实现这些安全机制。 10. **性能优化**:理解如何优化Web服务的性能,包括服务响应时间、并发...
- 在右侧找到“Java 认证和授权服务”>“J2C 认证数据”。 - 进入“全局安全性”>“JAAS-J2C认证数据”。 - 点击“新建”按钮进行新认证的创建。 - 输入必要的用户名和密码信息,并点击“应用”及“保存”按钮...
- **安全认证**:设置身份验证和授权机制保障数据安全。 #### 十、总结 通过本文档的学习,读者可以了解到Elasticsearch的基本概念、部署流程以及相关的运维知识。在实际操作过程中,还需要结合具体的业务场景进行...
- **安全性:** 实施端到端的安全策略,包括身份验证、授权和加密。 #### 五、Oracle SOA Suite 支持与资源 - **官方文档:** 参阅 Oracle 官方文档获取详细的技术指南和支持信息。 - **社区论坛:** 加入 Oracle ...
### BusinessObjects Integration Kit for SAP – 安装与配置详解 #### 概述 BusinessObjects Integration Kit for SAP 是一套专门设计用于集成 SAP 和 BusinessObjects 平台的工具包。该工具包使得用户能够在 SAP...
总的来说,Spring框架的众多组件和相关技术为构建现代化的Java应用提供了强大的支持,从反应式编程到微服务架构,再到安全性和分布式系统的其他方面,Spring的生态系统不断地扩展着Java开发者的能力范围。...
由国内著名技术社区联合推荐的2012年IT技术力作:《高性能Linux服务器构建实战:运维监控、性能调优与集群应用》,即将上架发行,此书从Web应用、数据备份与恢复、网络存储应用、运维监控与性能优化、集群高级应用等...
Apache Shiro是Java的安全框架,负责身份认证、授权(权限控制)、会话管理和安全加密等功能。在AuthManager中,Shiro扮演着核心角色,它处理用户的登录验证,提供基于角色的访问控制(RBAC),并能实现记住我、密码...
- 多因素认证:支持多种MFA(多因素认证)机制,增加安全性。 - 开放标准支持:遵循OAuth 2.0、OpenID Connect等开放标准,易于与其他系统集成。 2. **Keycloak工作原理**: - Keycloak服务器作为身份服务,处理...
2. **配置安全**:根据企业的安全策略,设置MQ的用户认证、权限和SSL/TLS加密。 3. **创建队列管理器**:使用MQ的命令行工具创建队列管理器,定义队列和通道,以支持消息传输。 4. **远程队列管理**:在Windows...
- **基于JAAS的验证**: 利用Java Authentication and Authorization Service(JAAS)提供的API来进行用户的认证和授权。 - **基于JAAS的授权**: 根据用户的角色和权限来决定其访问权限。 - **配置**: 配置文件中...
总结来说,Filter 在 JavaWeb 开发中扮演着至关重要的角色,它们帮助开发者实现诸如认证、授权、数据校验、性能优化等多种功能,提高了应用程序的安全性和可维护性。理解并熟练运用 Filter,能显著提升 JavaWeb 应用...