JAAS 程序化登录

程序化登录是一种表单登录类型,为了认证而支持特定于应用程序显示站点的登录形式。

当企业 Bean 客户机应用程序要求用户提供标识信息时,应用程序的写程序必须收集该信息并认证该用户。 可以根据实际执行用户认证所在的位置来将程序员的工作粗略划分为:

  • 在客户机程序中
  • 在服务器程序中

Web 应用程序的用户可使用许多方法来接收认证数据的提示。 Web 应用程序部署描述符文件中的 <login-config> 元素定义用于收集此信息的机制。 要定制登录过程而不是依赖于通用的设备(如浏览器中的 401 对话窗口)的程序员,可以使用基于表单的登录,以提供用于搜集登录信息的特定于应用程序的 HTML 表单。

除非启用 管理安全性 ,否则不会进行认证。 如果要将基于表单的登录用于 Web 应用程序,那么必须在每个 Web 应用程序的部署描述符中的 <login-config> 元素的 auth-method 标记中指定 表格

应用程序可以使用 WebSphere® Application Server 表单登录类型来提供特定于站点的登录表单。 Java™ Platform, Enterprise Edition (Java EE) 规范将表单登录定义为 Web 应用程序的认证方法之一。 WebSphere Application Server 提供了表单注销机制。

Java 认证和授权服务程序化登录

Java 认证和授权服务 (JAAS) 是 WebSphere Application Server中的新功能。 它也由 Java EE 1.4 规范规定。 JAAS 是一组策略认证应用程序编程接口 (API),它们取代了公共对象请求代理体系结构 (CORBA) 程序化登录 API。 WebSphere Application Server 提供了 JAAS的一些扩展:

在开始使用程序化登录 API 进行开发之前,请考虑以下要点:
  • 对于纯 Java 客户机应用程序或客户机容器应用程序,请在执行 JAAS 登录之前初始化客户机对象请求代理 (ORB) 安全性。 在进行 JAAS 登录之前通过执行以下代码来完成此操作:
    ...
    import java.util.Hashtable;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    ...
    // Perform an InitialContext and default lookup prior to logging 
    // in to initialize ORB security and for the bootstrap host/port 
    // to be determined for SecurityServer lookup. If you do not want 
    // to validate the userid/password during the JAAS login, disable 
    // the com.ibm.CORBA.validateBasicAuth property in the 
    // sas.client.props file.
    
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, 
        "com.ibm.websphere.naming.WsnInitialContextFactory");
    env.put(Context.PROVIDER_URL, 
         "corbaloc:iiop:myhost.mycompany.com:2809");
    Context initialContext = new InitialContext(env);
    Object obj = initialContext.lookup("");
    
    [z/OS]注: 每当连接到 z/OS® 服务器时设置 com.ibm.CORBA.validateBasicAuth=false 。 此功能当前无法从分布式客户机工作到 z/OS 服务器,因为 SecurityServer 是使用 z/OS 系统上不接受的 "UNAUTHENTICATED" 主体来定位的。
  • 对于纯 Java 客户机应用程序或客户机容器应用程序,请确保正确指定目标 Java 命名和目录接口 (JNDI) 引导属性的主机名和端口号。 请参阅 开发使用 CosNaming (CORBA 命名接口) 的应用程序 部分以获取详细信息。
  • 如果应用程序使用定制 JAAS 登录配置,请确保正确定义了 定制 JAAS 登录配置
  • 某些 JAAS API 受 Java 2 安全许可权保护。 如果这些 API 由应用程序代码使用,请确保这些许可权添加到应用程序 was.policy 文件。 请参阅 向应用程序添加 was.policy 文件以获取 Java 2 安全性使用 PolicyTool 编辑策略文件以获取 Java 2 安全性配置 was.policy 文件以获取 Java 2 安全性 部分以获取详细信息。 有关哪些 API 受 Java 2 安全性许可权保护的更多详细信息,请查看 IBM® Developer Kit , Java Technology Edition; JAAS 和 WebSphere Application Server 公共 API 文档以获取更多详细信息。 以下列表包含在此文档中提供的样本代码中所使用的 API。
    • 受 javax.security.auth.AuthPermission "createLoginContext" 保护的 javax.security.auth.login.LoginContext 构造函数。
    • 受 javax.security.auth.AuthPermission "doAs" 保护的 javax.security.auth.Subject.doAs 和 com.ibm.websphere.security.auth.WSSubject.doAs。
    • 受 javax.security.auth.AuthPermission "doAsPrivileged" 保护的 javax.security.auth.Subject.doAsPrivileged 和 com.ibm.websphere.security.auth.WSSubject.doAsPrivileged。
  • com.ibm.websphere.security.auth.WSSubject:由于 JAAS 1.0 中的设计疏忽,javax.security.auth.Subject.getSubject 不返回与 java.security.AccessController.doPrivileged 代码块中正在运行的线程相关联的主体集。 这会产生有问题的不一致行为,并且要花费额外的精力来解决问题。 com.ibm.websphere.security.auth.WSSubject API 提供了使主体集与正在运行的线程相关联的变通方法。 com.ibm.websphere.security.auth.WSSubject API 将 JAAS 模型扩展至 Java EE 资源以进行授权检查。 与 com.ibm.websphere.security.auth.WSSubject.doAs 或 com.ibm.websphere.security.auth.WSSubject.doAsPrivileged 代码块中正在运行的线程相关联的主体集用于 Java EE 资源授权检查。
  • 管理控制台支持定义新的 JAAS 登录配置: 您可以在管理控制台中配置 JAAS 登录配置,并将其存储在 WebSphere Application Server 配置 API 中。 应用程序可以在管理控制台中定义新的 JAAS 登录配置,并且数据将持久存储在使用 WebSphere Application Server 配置 API 存储的配置库中。 但是, WebSphere Application Server 仍然支持 JAAS 缺省实现提供的缺省 JAAS 登录配置格式。 如果在 WebSphere Application Server 配置 API 和纯文本文件格式中都定义了重复登录配置,那么 WebSphere Application Server 配置 API 中的登录配置优先。 在 WebSphere Application Server 配置 API 中定义登录配置的优点包括:
    • 使用管理控制台定义 JAAS 登录配置。
    • 可以集中管理 JAAS 登录配置。
    • WebSphere Application Server Network Deployment 安装中分发 JAAS 登录配置。
  • WebSphere Application Server的 JAAS 登录配置: WebSphere Application Server 提供了 JAAS 登录配置 用于对 WebSphere Application Server 安全性运行时执行程序化认证的应用程序。 WebSphere Application Server 的这些 JAAS 登录配置根据提供的认证数据对配置的认证机制,简单 WebSphere 认证机制 (SWAM) 或轻量级第三方认证 (LTPA) 以及用户注册表 (本地操作系统, LDAP 或定制) 执行认证。 这些 JAAS 登录配置中的已认证主体集包含 WebSphere Application Server 安全运行时可用于对基于 Java EE 角色的受保护资源执行授权检查的必需主体和凭证。
    注:WebSphere Application Server V 9.0 中不推荐使用 SWAM ,将在将来的发行版中除去。
    以下是 WebSphere Application Server提供的 JAAS 登录配置:
    • WSLogin JAAS 登录配置: 一个通用 JAAS 登录配置, Java 客户机,客户机容器应用程序, servlet , JSP 文件,企业 Bean 等可以使用此配置来执行基于用户标识和密码的认证,或者执行 WebSphere Application Server 安全性的令牌 运行时。 但是,此配置不支持在客户机容器部署描述符中指定的 CallbackHandler 处理程序。
    • ClientContainer JAAS 登录配置:此 JAAS 登录配置识别在客户机容器部署描述符中指定的 CallbackHandler 处理程序。 此登录配置的登录模块将使用客户机容器部署描述符中的 CallbackHandler 处理程序(如果指定了一个的话),即使应用程序代码在登录上下文中指定了一个 CallbackHandler 处理程序。 这适用于客户机容器应用程序。
    • 使用先前提到的 JAAS 登录配置认证的主体集包含 com.ibm.websphere.security.auth.WSPrincipal 主体和 com.ibm.websphere.security.auth.WSCredential 凭证。 如果将已认证的主体集传递到 com.ibm.websphere.security.auth.WSSubject.doAs 方法或其他 doAs 方法,那么 WebSphere Application Server 安全性运行时可以根据主体集 com.ibm.websphere.security.auth.WSCredential 凭证对 Java EE 资源执行授权检查。
  • 客户定义的 JAAS 登录配置: 您可以 定义其他 JAAS 登录配置。 使用这些登录配置来对定制认证机制执行程序化认证。 但是,如果这些客户定义的 JAAS 登录配置中的主体集不包含必需的主体集和凭证,那么 WebSphere Application Server 安全性运行时可能不会使用这些主体集来执行授权检查。

查找来自 JAAS 登录的根本原因登录异常

如果在发出 LoginContext.login API 之后产生 LoginException 异常,那么可从已配置的用户注册表中找到根本原因异常。 在登录模块中,注册表异常包括在 com.ibm.websphere.security.auth.WSLoginFailedException 类中。 此异常具有 getCause 方法,可以通过此方法拉出在发出上述命令后包括的异常。

您并不是总会获得 WSLoginFailedException 异常,但是,用户注册表中生成的大多数异常都显示在此处。 以下示例说明了 LoginContext.login API 以及相关联的 catch 块。 如果想要发出 getCause API,那么将 WSLoginFailedException 异常强制类型转换为 com.ibm.websphere.security.auth.WSLoginFailedException 类。

下面的 determineCause 示例可用于处理 CustomUserRegistry 异常类型。
try 
    {
         lc.login(); 
    } 
    catch (LoginException le)
    {
	// drill down through the exceptions as they might cascade through the runtime
	Throwable root_exception = determineCause(le);
	
	// now you can use "root_exception" to compare to a particular exception type
	// for example, if you have implemented a CustomUserRegistry type, you would 
  //  know what to look for here.
    }


/* Method used to drill down into the WSLoginFailedException to find the 
"root cause" exception */

    public Throwable determineCause(Throwable e) 
      {
				Throwable root_exception = e, temp_exception = null;

				// keep looping until there are no more embedded WSLoginFailedException or 
				// WSSecurityException exceptions 
         while (true) 
				{
						if (e instanceof com.ibm.websphere.security.auth.WSLoginFailedException)
						{
							temp_exception = ((com.ibm.websphere.security.auth.WSLoginFailedException)
							e).getCause();
						}
						else if (e instanceof com.ibm.websphere.security.WSSecurityException)
						{
							temp_exception = ((com.ibm.websphere.security.WSSecurityException)
							e).getCause();
						}
						else if (e instanceof javax.naming.NamingException)
								// check for Ldap embedded exception
								{
										temp_exception = ((javax.naming.NamingException)e).getRootCause();
								}
						else if (e instanceof your_custom_exception_here)
						{
								// your custom processing here, if necessary
						}
						else
						{
								// this exception is not one of the types we are looking for,
								// lets return now, this is the root from the WebSphere 
								//  Application Server perspective
								return root_exception;
						}
						if (temp_exception != null)
						{
								// we have an exception; go back and see if this has another
								// one embedded within it.
								root_exception = temp_exception;
								e = temp_exception;
								continue;
						}
						else
						{
								// we finally have the root exception from this call path, this
								// has to occur at some point
								return root_exception;
						}
				}
		}

查找来自 Servlet 过滤器的根本原因登录异常

您还会在处理 post-form 登录处理时接收到来自 Servlet 过滤器的根本原因异常。 此异常很有用,这是因为它会告诉用户发生的情况。 可以发出以下 API 以获取根本原因异常:
Throwable t = com.ibm.websphere.security.auth.WSSubject.getRootLoginException();  
if (t != null)  	
         t = determineCause(t);

发生异常之后,可以通过前面的 determineCause 示例运行它,以获得本机注册表根本原因。

启用到纯 Java 客户机的根本原因登录异常传播

当前,为安全起见,根本原因不会传播到纯客户机。 但是,可能要在可信环境中将根本原因传播到纯客户机。 如果要对纯客户机启用根本原因登录异常传播,请在 WebSphere Application Server 管理控制台上单击 安全 > 全局安全性 > 定制属性 并设置以下属性:

com.ibm.websphere.security.registry.propagateExceptionsToClient=true

不提示程序化登录

WebSphere Application Server 提供 javax.security.auth.callback.CallbackHandler 接口 (称为 com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl) 的非提示实现。 使用此接口,应用程序可将认证数据推入 WebSphere LoginModule 实例以执行认证。 此功能对于服务器端应用程序代码认证身份以及使用该身份来调用下游 Java EE 资源很有用。
javax.security.auth.login.LoginContext lc = null;

try {
lc = new javax.security.auth.login.LoginContext("WSLogin",
new com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl("user", 
      "securityrealm", "securedpassword"));

// create a LoginContext and specify a CallbackHandler implementation
// CallbackHandler implementation determine how authentication data is collected
// in this case, the authentication data is "push" to the authentication mechanism
//   implemented by the LoginModule.
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " 
+ e.getMessage());
e.printStackTrace();

// maybe javax.security.auth.AuthPermission "createLoginContext" is not granted
//   to the application, or the JAAS login configuration is not defined.
}

if (lc != null)
try {
lc.login();  // perform login
javax.security.auth.Subject s = lc.getSubject();
// get the authenticated subject

// Invoke a Java EE resource using the authenticated subject
com.ibm.websphere.security.auth.WSSubject.doAs(s,
new java.security.PrivilegedAction() {
public Object run() {
try {
bankAccount.deposit(100.00);  // where bankAccount is a protected EJB
} catch (Exception e) {
System.out.println("ERROR: error while accessing EJB resource, exception: " 
+ e.getMessage());
e.printStackTrace();
}
return null;
}
}
);
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: login failed with exception: " + e.getMessage());
e.printStackTrace();

// login failed, might want to provide relogin logic
}

可以将 com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl 回调处理程序与纯 Java 客户机,客户机应用程序容器,企业 Bean , JavaServer Pages (JSP) 文件, Servlet 或其他 Java 2 Platform , Enterprise Edition (Java EE) 资源配合使用。

注意: WSCallbackHandlerImpl 回调处理程序因您使用的是 WebSphere Application Server 安全还是 Web 服务安全,回调处理程序也不同。 如果使用 WebSphere Application Server 安全性,那么该回调处理程序将位于 sas.jar 文件中;如果使用 Web Service 安全性,那么位于 was-wssecurity.jar 文件中。

用户界面提示程序化登录

WebSphere Application Server 还提供了 javax.security.auth.callback.CallbackHandler 实现的用户界面实现,以通过用户界面登录提示从用户收集认证数据。 com.ibm.websphere.security.auth.callback.WSGUICallbackHandlerImpl 回调处理程序会提供一个用户界面登录面板,以提示用户输入认证数据。
[AIX HP-UX Solaris][z/OS]注: 此行为需要由 DISPLAY 环境调用 X11 服务器。
javax.security.auth.login.LoginContext lc = null;

try {
lc = new javax.security.auth.login.LoginContext("WSLogin",
new com.ibm.websphere.security.auth.callback.WSGUICallbackHandlerImpl());

// create a LoginContext and specify a CallbackHandler implementation
// CallbackHandler implementation determine how authentication data is collected
// in this case, the authentication date is collected by GUI login prompt
//   and pass to the authentication mechanism implemented by the LoginModule.
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: failed to instantiate a LoginContext and the exception: " 
+ e.getMessage());
e.printStackTrace();

// maybe javax.security.auth.AuthPermission "createLoginContext" is not granted
//   to the application, or the JAAS login configuration is not defined.
}

if (lc != null)
try {
lc.login();  // perform login
javax.security.auth.Subject s = lc.getSubject();
// get the authenticated subject

// Invoke a Java EE resources using the authenticated subject
com.ibm.websphere.security.auth.WSSubject.doAs(s,
new java.security.PrivilegedAction() {
public Object run() {
try {
bankAccount.deposit(100.00);  // where bankAccount is a protected enterprise bean
} catch (Exception e) {
System.out.println("ERROR: error while accessing EJB resource, exception: " 
+ e.getMessage());
e.printStackTrace();
}
return null;
}
}
);
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: login failed with exception: " + e.getMessage());
e.printStackTrace();

// login failed, might want to provide relogin logic
}
注意: 请勿将 com.ibm.websphere.security.auth.callback.WSGUICallbackHandlerImpl 回调处理程序用于服务器端资源 (例如,企业 bean , servlet 和 JSP 文件等)。 用户界面登录提示阻拦服务器的用户输入。 此行为对于服务器进程不利。

WebSphere Application Server 还提供了 javax.security.auth.callback.CallbackHandler 接口的 Kerberos 凭证高速缓存实现。 回调处理程序 com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl。 使用此接口,应用程序可将认证数据推入 WebSphere LoginModule 实例以执行认证。

此功能仅用于客户机端应用程序代码使用 Kerberos 凭证高速缓存向 WebSphere Application Server 进行认证。

如果 wsjaas_client.conf 文件中存在下列选项,请将它们设置为 false:
useDefaultKeytab=false
useDefaultCcache=false
tryFirstPass=false
useFirstPass=false
forwardable=false
renewable=false
renewable=false
noaddress=false
javax.security.auth.login.LoginContext lc = null;

String krb5Ccache = /etc/krb5/krb5cc_utle;

try {
lc = new javax.security.auth.login.LoginContext("WSKRB5Login",
new com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl(user, krb5Realm, krb5Ccache, false));
// create a LoginContext and specify a CallbackHandler implementation
// CallbackHandler implementation determines how authentication data is collected
// in this case, the authentication date is collected by stdin prompt
// and passed to the authentication mechanism implemented by the LoginModule.
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: failed to instantiate a LoginContext and the exception: 
          " + e.getMessage());
e.printStackTrace();

// maybe javax.security.auth.AuthPermission "createLoginContext" is not granted
//   to the application, or the JAAS login configuration is not defined.
}

if (lc != null)
try {
lc.login();  // perform login
javax.security.auth.Subject s = lc.getSubject();
// get the authenticated subject

// Invoke a Java EE resource using the authenticated subject
com.ibm.websphere.security.auth.WSSubject.doAs(s,
new java.security.PrivilegedAction() {
public Object run() {
try {
bankAccount.deposit(100.00);  
// where bankAccount is a protected enterprise bean
} catch (Exception e) {
System.out.println("ERROR: error while accessing EJB resource, exception: " 
       + e.getMessage());
e.printStackTrace();
}
return null;
}
}
);
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: login failed with exception: " + e.getMessage());
e.printStackTrace();

// login failed, might want to provide relogin logic
}

Application Server with the default Kerberos credential cache.

javax.security.auth.login.LoginContext lc = null;

try {
lc = new javax.security.auth.login.LoginContext("WSKRB5Login",
new com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl(user, krb5Realm, null, true));
// create a LoginContext and specify a CallbackHandler implementation
// CallbackHandler implementation determines how authentication data is collected
// in this case, the authentication date is collected by stdin prompt
// and passed to the authentication mechanism implemented by the LoginModule.
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: failed to instantiate a LoginContext and the exception: 
          " + e.getMessage());
e.printStackTrace();

// maybe javax.security.auth.AuthPermission "createLoginContext" is not granted
//   to the application, or the JAAS login configuration is not defined.
}

if (lc != null)
try {
lc.login();  // perform login
javax.security.auth.Subject s = lc.getSubject();
// get the authenticated subject

// Invoke a Java EE resource using the authenticated subject
com.ibm.websphere.security.auth.WSSubject.doAs(s,
new java.security.PrivilegedAction() {
public Object run() {
try {
bankAccount.deposit(100.00);  
// where bankAccount is a protected enterprise bean
} catch (Exception e) {
System.out.println("ERROR: error while accessing EJB resource, exception: " 
       + e.getMessage());
e.printStackTrace();
}
return null;
}
}
);
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: login failed with exception: " + e.getMessage());
e.printStackTrace();

// login failed, might want to provide relogin logic
}

Application Server with the Microsoft native Kerberos credential cache. The client must
login to the Microsoft Domain Controller.

javax.security.auth.login.LoginContext lc = null;

try {
lc = new javax.security.auth.login.LoginContext("WSKRB5Login",
new com.ibm.websphere.security.auth.callback.WSCcacheCallBackHandlerImpl(null, null, null, true));
// create a LoginContext and specify a CallbackHandler implementation
// CallbackHandler implementation determines how authentication data is collected
// in this case, the authentication date is collected by stdin prompt
// and passed to the authentication mechanism implemented by the LoginModule.
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: failed to instantiate a LoginContext and the exception: 
          " + e.getMessage());
e.printStackTrace();

// maybe javax.security.auth.AuthPermission "createLoginContext" is not granted
//   to the application, or the JAAS login configuration is not defined.
}

if (lc != null)
try {
lc.login();  // perform login
javax.security.auth.Subject s = lc.getSubject();
// get the authenticated subject

// Invoke a Java EE resource using the authenticated subject
com.ibm.websphere.security.auth.WSSubject.doAs(s,
new java.security.PrivilegedAction() {
public Object run() {
try {
bankAccount.deposit(100.00);  
// where bankAccount is a protected enterprise bean
} catch (Exception e) {
System.out.println("ERROR: error while accessing EJB resource, exception: " 
       + e.getMessage());
e.printStackTrace();
}
return null;
}
}
);
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: login failed with exception: " + e.getMessage());
e.printStackTrace();

// login failed, might want to provide relogin logic
}

WSKRB5Login 模块

WSKRB5Login JAAS 登录配置: 是通用 JAAS 登录配置, Java 客户机,客户机容器应用程序, Servlet , JSP 文件或企业 Bean 可以使用此配置来执行基于 Kerberos 主体名称密码或 Kerberos 凭证高速缓存到 WebSphere Application Server 安全运行时的认证。 但是,此配置不支持在客户机容器部署描述符中指定的 CallbackHandler 处理程序。

将您所创建的 krb5.inikrb5.conf 文件放入缺省位置。 如果其中任一文件不在缺省位置,那么必须使用正确的路径和 Kerberos 配置文件名称来设置 java.security.krb5.conf JVM 系统属性。

在 Windows® 平台上,缺省位置为 c:\winnt\krb5.ini。

在 Linux® 平台上,缺省位置为 /etc/krb5.conf。

在其他 Unix 平台上,缺省位置为 /etc/krb5/krb5.conf。

在 z/OS 平台上,缺省位置为 /etc/krb5/krb5.conf。

Kerberos 配置设置、Kerberos 密钥分发中心 (KDC) 名称和领域设置将在 Kerberos 配置文件中提供,或者通过 java.security.krb5.kdc 和 java.security.krb5.realm 系统属性文件提供。

Stdin 提示程序化登录

WebSphere Application Server 还提供了 javax.security.auth.callback.CallbackHandler 接口的 stdin 实现。 回调处理程序 com.ibm.websphere.security.auth.callback.WSStdinCallbackHandlerImpl 通过 stdin 提示来提示用户输入认证数据和搜集认证数据。
javax.security.auth.login.LoginContext lc = null;

try {
lc = new javax.security.auth.login.LoginContext("WSLogin",
new com.ibm.websphere.security.auth.callback.WSStdinCallbackHandlerImpl());

// create a LoginContext and specify a CallbackHandler implementation
// CallbackHandler implementation determines how authentication data is collected
// in this case, the authentication date is collected by stdin prompt
// and passed to the authentication mechanism implemented by the LoginModule.
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: failed to instantiate a LoginContext and the exception: 
          " + e.getMessage());
e.printStackTrace();

// maybe javax.security.auth.AuthPermission "createLoginContext" is not granted
//   to the application, or the JAAS login configuration is not defined.
}

if (lc != null)
try {
lc.login();  // perform login
javax.security.auth.Subject s = lc.getSubject();
// get the authenticated subject

// Invoke a Java EE resource using the authenticated subject
com.ibm.websphere.security.auth.WSSubject.doAs(s,
new java.security.PrivilegedAction() {
public Object run() {
try {
bankAccount.deposit(100.00);  
// where bankAccount is a protected enterprise bean
} catch (Exception e) {
System.out.println("ERROR: error while accessing EJB resource, exception: " 
       + e.getMessage());
e.printStackTrace();
}
return null;
}
}
);
} catch (javax.security.auth.login.LoginException e) {
System.err.println("ERROR: login failed with exception: " + e.getMessage());
e.printStackTrace();

// login failed, might want to provide relogin logic
}
注意: 请勿将 com.ibm.websphere.security.auth.callback.WSStdinCallbackHandlerImpl 回调处理程序用于服务器端资源,例如企业 Bean , Servlet 和 JSP 文件等。 来自 stdin 提示的输入未发送到服务器环境。 多数服务器在后台运行,并且没有控制台。 但是,如果服务器具有控制台,那么 stdin 提示阻拦服务器的用户输入。 此行为对于服务器进程不利。