Java 为什么Subject.doAs基于登录用户而不是切换的Subject返回主体?
我正在尝试从以前部署在bea weblogic中的web应用程序转换现有api。我现在需要在JBoss EAP 7中部署这个应用程序 在我的用户登录代码中,我执行servlet身份验证,如下所示:Java 为什么Subject.doAs基于登录用户而不是切换的Subject返回主体?,java,subject,principal,jboss-eap-7,sessioncontext,Java,Subject,Principal,Jboss Eap 7,Sessioncontext,我正在尝试从以前部署在bea weblogic中的web应用程序转换现有api。我现在需要在JBoss EAP 7中部署这个应用程序 在我的用户登录代码中,我执行servlet身份验证,如下所示: HttpServletRequest request = ServletActionContext.getRequest(); request.login("user1", "password"); testEJB= (TestEJB) LookupUtil.lookup("TestEJB"); S
HttpServletRequest request = ServletActionContext.getRequest();
request.login("user1", "password");
testEJB= (TestEJB) LookupUtil.lookup("TestEJB");
System.out.println("logged in user: " + testEJB.getName()); //returns user1
LoginContext loginContext = new LoginContext("TestLoginContext", new UsernamePasswordHandler("user2", "password"));
loginContext.login();
String newUser = (String) Subject.doAs(loginContext.getSubject(), new TestPrivilegedAction());
System.out.println("privileged User: " + newUser); //still returns user1
现在,容器查找的每个EJB中的sessionContext都会返回登录的用户,这非常完美,只是有些应用程序功能需要切换用户并执行一些特权操作,例如上载文档
我正在切换用户并执行特权操作,如下所示:
HttpServletRequest request = ServletActionContext.getRequest();
request.login("user1", "password");
testEJB= (TestEJB) LookupUtil.lookup("TestEJB");
System.out.println("logged in user: " + testEJB.getName()); //returns user1
LoginContext loginContext = new LoginContext("TestLoginContext", new UsernamePasswordHandler("user2", "password"));
loginContext.login();
String newUser = (String) Subject.doAs(loginContext.getSubject(), new TestPrivilegedAction());
System.out.println("privileged User: " + newUser); //still returns user1
在实现PrivilegedAction的TestPrivilegedAction中,我有以下代码:
@Override
public Object run() {
return this.getSwitchedUser();
}
private Object getSwitchedUser() {
testEJB= (TestEJB) LookupUtil.lookup("TestEJB");
System.out.println("logged in user: " + testEJB.getName());
}
基本上,在weblogic中部署应用程序时使用的原始api是:
Authenticate.authenticate
Security.runAs
…然后我将其替换为以下内容以使其在JBoss中工作:
LoginContext.login
Subject.doAs
那么,为什么现在它仍然返回登录用户(user1),即使身份验证成功并且主题已设置为user2?我一直在网上搜索,试图看看我是否只是错过了一些配置,但我现在真的被困在这个问题上了。非常感谢您的反馈或建议。在对可用的API进行了一段时间的实验后,我终于能够解决我的问题。我只想把它放在这里,以防其他人遇到同样的问题 基本上,我重新发明了用于weblogic server的现有api:
Authenticate.authenticate
Security.runAs
这是我的身份验证类:
public class Authenticate {
private static Subject originalSubject = null;
public static void authenticate(Hashtable env, Subject subject) throws LoginException {
try {
//retrieve the security context that contains the current subject (logged in user)
SecurityContext securityContext = SecurityContextAssociation.getSecurityContext();
SubjectInfo subjectInfo = securityContext.getSubjectInfo();
//set the current subject as the original subject
originalSubject = subjectInfo.getAuthenticatedSubject();
//start authentication of the new subject
CallbackHandler callbackHandler = new UsernamePasswordHandler((String) env.get(Context.SECURITY_PRINCIPAL), env.get(Context.SECURITY_CREDENTIALS));
LoginContext loginContext = new LoginContext("JbossLoginContext", callbackHandler);
loginContext.login();
//set the new subject information to perform the privileged action
subject.getPrincipals().addAll(loginContext.getSubject().getPrincipals());
subjectInfo.setAuthenticatedSubject(loginContext.getSubject());
} catch (LoginException e) {
throw new LoginException();
} catch (Exception e) {
throw new Exception();
}
}
public static void setOriginalSubject() {
try {
//if the login method is already invoked, replace the current subject with the original subject
if(originalSubject != null) {
SecurityContextAssociation.getSecurityContext().getSubjectInfo().setAuthenticatedSubject(originalSubject);
}
} catch (Exception e) {
throw new Exception();
}
}
}
我为Subject.doAs创建了一个包装器类,它没有切换回原始主题的功能。我是这样做的:
public class Security {
public static Object runAs(Subject subject, PrivilegedAction privilegedAction) {
try {
Object object = Subject.doAs(subject, privilegedAction);
Authenticate.setOriginalSubject();
return object;
} catch (Exception e) {
throw new Exception();
}
}
}
现在,请注意,我仍然使用Subject.doAs方法,然后调用Authenticate.setOriginalSubject将原始主题设置回原处
一切正常,我几乎只需要更新使用它的类文件中的包导入