Java EE 6应用中的Shiro

3

我正在按照BalusC的代码来管理Java EE 6中的用户身份验证(http://balusc.blogspot.com/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html),如果我留在同一个Web容器中,这很好用。

我遇到了一个问题,也许有人可以帮助我。 当注入Web容器中驻留的EJB时,SecurityUtils.getSubject()从该EJB的任何方法中都可以正常工作。

但问题是,当我尝试在来自另一个容器的注入EJB上执行此操作时(即使是在同一EAR中的ejb jar中),会出现以下错误:

Caused by: org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.

使用注入的无状态会话bean B 管理bean A。类 A 存在于 myApp.war,类 B 存在于 myApp.ejb,两者都在 myApp.ear 中。我正在从类 B 调用 SecurityUtils

你有任何解决方法吗?

我正在运行 JSF 2、Java EE 6 和 JBoss 7.1。

2个回答

1

我将回答这个问题。

我使用了一个过滤器和一个自定义的JBoss LoginModule来解决集成问题:

该过滤器(必须在调用shiro过滤器之后应用):

public class ShiroJAASIntegrationFilter implements Filter{

    static Logger logger = Logger.getLogger(ShiroJAASIntegrationFilter.class);
    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain arg2) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)arg0;
        Principal userPrincipal = httpServletRequest.getUserPrincipal();
        HttpSession session = httpServletRequest.getSession(false);
        if(userPrincipal!=null){
            if(session!= null && session.getAttribute("shiroAuthenticated")==null){
                String name = userPrincipal.getName();
                try {
                    httpServletRequest.login(name,"");
                    session.setAttribute("shiroAuthenticated",true);
                } catch (ServletException e) {
                    logger.debug("Unable to authenticate user" + e.getMessage());
                }
            }

        }
        arg2.doFilter(arg0, arg1);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }
}

登录模块仅将用户标记为已验证:

public class ShiroJAASLoginModule extends UsernamePasswordLoginModule {

    /**
     * Always return true. 
     */
    protected boolean validatePassword(String inputPassword,
            String expectedPassword) {
        return true;
    }

    protected Group[] getRoleSets() throws LoginException {
        //TODO: if needed, add roles
        Group[] roleSets = { new SimpleGroup("Roles") };
        roleSets[0].addMember(new SimplePrincipal(getUsername()));
        return roleSets;
    }


    @Override
    protected String getUsersPassword() throws LoginException {
        return null;
    }

}

该模块必须在 standalone.xml 中定义:
<security-domain name="shiro" cache-type="default">
 <authentication>
  <login-module code="web.security.shiroJaasIntegration.ShiroJAASLoginModule" flag="required"/>
 </authentication>
</security-domain>

最后,在您的应用程序 jboss-web.xml 中定义安全域:
<jboss-web>
    <security-domain>shiro</security-domain>

</jboss-web>

我也遇到了同样的异常。你还记得是什么具体原因导致了这个问题,以及这段代码是如何解决它的吗? - Jens Piegsa

0

嗯,Shiro通过ShiroFilterSecurityManager绑定为ThreadLocal。看一下doFilterInternal方法。 Subject仅在subject.execute方法内部绑定到ThreadContext,这意味着每次在subject.execute之外调用SecurityUtils.getSubject()时将返回null,这意味着在ShiroFilter之外,也就是请求线程之外,这就是我认为的问题。

AbstractShiroFilter.java

protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)
            throws ServletException, IOException {
...

            final Subject subject = createSubject(request, response);

            //noinspection unchecked
            subject.execute(new Callable() {
                public Object call() throws Exception {
                    updateSessionLastAccessTime(request, response);
                    executeChain(request, response, chain);
                    return null;
                }
            });    
...
    } 

好的,你说你要注入无状态B,你用的是哪个依赖注入框架?Shiro可以很容易地与Guice和Spring集成。


你好,感谢您的输入。我正在使用EJB3.1与JSF2,目前无法转换到Guice或Spring。实际上,ejb在shirofilter的相同线程中被调用,但我不知道为什么当它涉及到EJB3.1项目的堆栈时,Shiro ThreadLocal会消失..也许我可以使用第二个过滤器手动添加它,但可能是EJB堆栈的问题。 - Rafael Sisto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接