我正在学习JAAS和我采取一个简单的例子,在使用Tomcat与JaasRealm web应用程序使用。
现在我的问题是,我不知道如何检索既然喜欢代码的主题Subject subject = Subject.getSubject(AccessController.getContext());
始终返回null。
我使用Tomcat 7.0.27。 是不是有什么我已经错过了? 在如何管理Java EE中与JAAS授权其他方面? 例如,我如何能实现JAAS的安全范围内的行动?
我正在学习JAAS和我采取一个简单的例子,在使用Tomcat与JaasRealm web应用程序使用。
现在我的问题是,我不知道如何检索既然喜欢代码的主题Subject subject = Subject.getSubject(AccessController.getContext());
始终返回null。
我使用Tomcat 7.0.27。 是不是有什么我已经错过了? 在如何管理Java EE中与JAAS授权其他方面? 例如,我如何能实现JAAS的安全范围内的行动?
我知道,和它的作品,但我需要检索主题得到也roleprincipal
不幸的是,这是行不通的一样,在Java EE的。 的JAAS主题只是一个“校长袋”,以及这些的代表用户/呼叫者主要和/或作用主要(S)简单地不规范。 每隔容器做不同的事情在这里。 在对Tomcat的JAASRealm的Javadoc描述了这一点,并解释了Tomcat的具体约定(重点煤矿):
的JAAS规范描述在成功登录作为javax.security.auth.Subject实例,它可包含在Subject.getPrincipals的返回值()方法零个或更多的java.security.Principal对象的结果。 但是, 它提供了有关如何区分描述单个用户(以及因此适当的恢复为request.getUserPrincipal()的Web应用程序的值)从描述授权角色这样做的主要(或多个)校长没有指导用户。 为了保持从JAAS执行底层LoginMethod实现尽可能多的独立越好,下面的政策是由该领域实现:[...]
除此之外,在Java EE环境中,你甚至很少有机会获得JAAS主体,往往不能甚至通过供应商的具体方法。 JAAS是远离你认为它是,特别是当它涉及Java EE的通用标准。
您可以在便携式的方式访问的唯一的事情是调用者主体和与之关联的角色,但即使是那些没有被你的JAAS登录模块构建的确切者主体。
JBoss AS中,例如,拷贝这主要使用其自己的类几次。 所以,如果你的JAAS模块存储在kaz.zak.FooPrincipal
为主题的用户/调用者主体,然后HttpServletRequest#getUserPrincipal()
可能会返回一个org.jboss.security.SimplePrincipal
。 保证的唯一的事情是getName()
在该实例将返回相同的字符串。
有关此主题的一些背景:
最后一个来源基本上是说同样的事情,不同的写法;
虽然有可能在Tomcat使用JAAS作为身份验证机制(JAASRealm),一旦用户被认证JAAS框架的柔软性丧失。 这是因为校长是用来表示“用户”和“角色”的概念,并且不再在其中执行的Web应用程序的安全上下文可用。 认证的结果是只能通过request.getRemoteUser()和request.isUserInRole()。
这减少了授权目的到失去其与Java安全策略连接一个简单的用户/角色系统JAAS框架。
要检索主题,我们可以使用的LoginModule和阀门的组合。 该阀认证踢之前在这里帮助我们调用的事实。 当阀门被调用它放入ThreadLocal的会话(类似于JBOSS如何在ThreadLocal中保存的请求),当LoginModule.commit()被调用它保存对象到会话后。
要配置这个插件类的编译代码下面一个罐子,并将其放置在$ CATALINA_BASE / lib目录/
package my.test;
import java.io.IOException;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.servlet.ServletException;
import org.apache.catalina.Session;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
/**
* Use following class to retrieve subject in your HTTPServlet when using Tomcat.
*/
public class ContainerServices extends ValveBase implements LoginModule {
// Key to revtieve subject from session.
public static final String SUBJECT_KEY =
"javax.security.auth.Subject.container";
/**
* Session for current thread.
*/
static InheritableThreadLocal<Session> sessionHolder =
new InheritableThreadLocal<Session>();
// JAAS Subject being authenticated.
private Subject subject;
// Invoke the value.
public void invoke(Request request, Response response) throws IOException,
ServletException {
sessionHolder.set(request.getSessionInternal(true));
try {
// Next in the invocation chain
getNext().invoke(request, response);
} finally {
sessionHolder.remove();
}
}
// Initialize the login module
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
this.subject = subject;
}
// Store subject to session.
public boolean commit() throws LoginException {
Session session = sessionHolder.get();
if (session != null) {
session.getSession().setAttribute(ContainerServices.SUBJECT_KEY, subject);
}
return true;
}
// not used
public boolean abort() throws LoginException {
return false;
}
// not used
public boolean login() throws LoginException {
return true;
}
// not used
public boolean logout() throws LoginException {
return true;
}
}
在$ CATALINA_BASE / conf目录/ server.xml中添加以下阀门的结构元素的孩子。
<Valve className="my.test.ContainerServices" />
在的jaas.config文件添加同一类的LoginModule。
DummyAppLogin { my.test.ContainerServices required debug=true; my.test.DummyAppLoginModule required debug=true; };
现在,在您登录后,认证主题可以使用以下检索。
session.getAttribute( ContainerServices.SUBJECT_KEY );