1

我正在尝试从以前部署在 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

现在容器查找到的每个 EJB 中的 sessionContext 都会返回登录的用户,这很完美,只是一些应用程序功能需要切换用户并执行一些特权操作,例如上传文档。

我正在切换用户并执行特权操作,如下所示:

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?我一直在网上搜索并试图看看我是否只是缺少一些配置,但我现在真的坚持下去了。我感谢任何反馈或建议。

4

1 回答 1

1

在对可用的 API 进行了一段时间的试验后,我终于能够解决我的问题。我只是想把它放在这里,以防其他人遇到同样的问题。

基本上,我重新发明了用于 weblogic 服务器的现有 api:

Authenticate.authenticate
Security.runAs

这是我的 Authenticate 类:

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 来设置原始主题。

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

于 2017-11-14T08:45:38.600 回答