jakarta-ee - Java EE 6 应用程序中的 Shiro

标签 jakarta-ee jsf-2 jboss7.x java-ee-6 shiro

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

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

问题是当我尝试在来自另一个容器(甚至是同一 EAR 中的 ejb jar)的注入(inject) EJB 上执行此操作时。

我得到的错误是:

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 A,注入(inject)了无状态 session bean BA 类驻留在 myApp.war 中,B 类驻留在 myApp.ejb 中,两者都在 myApp.ear 中。我正在从 B 类调用 SecurityUtils

你有解决这个问题的线索吗?

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

最佳答案

我自己在回答这个问题。

我使用 Filter 和 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>

关于jakarta-ee - Java EE 6 应用程序中的 Shiro,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18326128/

相关文章:

linux - 在 Linux 上将 JBoss 7 作为服务启动

java - 出于 "sequentially"要求输入的目的部分提交表单

jsf - 如何访问 Composite 的父命名容器?

java - 如何解决 Jboss EAP 7.1.4 java.util.concurrent.TimeoutException : No invocation response received in 30000 milliseconds

java - 改变继承依赖的依赖

html - &lt;!DOCTYPE> 部分在 JSF 中应该如何显示? HTML5 还是 XHTML?

java - Java EE 包有什么不同? (SDK/正常与 Web 配置文件)

java - jqgrid java服务器端分页

java - Log4j configureAndWatch() 产生数千个线程

java - 将 setter 方法中组件的 id 传递给 ManagedBean