Java 为什么Subject.doAs基于登录用户而不是切换的Subject返回主体?

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

我正在尝试从以前部署在bea weblogic中的web应用程序转换现有api。我现在需要在JBoss EAP 7中部署这个应用程序

在我的用户登录代码中,我执行servlet身份验证,如下所示:

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将原始主题设置回原处

一切正常,我几乎只需要更新使用它的类文件中的包导入