Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用基于表单的安全性时如何实现注销_Java_Security_Jakarta Ee_Ejb 3.0_Java Ee 6 - Fatal编程技术网

Java 使用基于表单的安全性时如何实现注销

Java 使用基于表单的安全性时如何实现注销,java,security,jakarta-ee,ejb-3.0,java-ee-6,Java,Security,Jakarta Ee,Ejb 3.0,Java Ee 6,我使用基于JDBC表单的安全域,我想实现注销,但当我单击链接时,我看到了以下异常: java.lang.RuntimeException:java.security.AccessControlException: 拒绝访问(java.lang.reflect.ReflectPermission) 取消访问检查)。。。原因: java.security.AccessControlException:拒绝访问 (java.lang.reflect.reflect权限检查) 这是我创建的用于执行日志的

我使用基于JDBC表单的安全域,我想实现注销,但当我单击链接时,我看到了以下异常:

java.lang.RuntimeException:java.security.AccessControlException: 拒绝访问(java.lang.reflect.ReflectPermission) 取消访问检查)。。。原因: java.security.AccessControlException:拒绝访问 (java.lang.reflect.reflect权限检查)

这是我创建的用于执行日志的EJB:

@Stateless(name = "ejbs/SessionSupportEJBImpl")
@DeclareRoles({"administrators","users"})
public class SessionSupportEJBImpl implements SessionSupportEJB {

    @PermitAll
    public void releaseUserState() {
        HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
                .getExternalContext().getSession(false);
        if (session != null) {
            session.invalidate();
        }
    }
}
这里我从一个支持bean中调用它:

@Named("logoutBB")
@RequestScoped
public class LogoutBean {

    @EJB
    private SessionSupportEJB sessionSupportEJB;

    public String logout() {
        sessionSupportEJB.releaseUserState();
        return "index.xhtml?faces-redirect=true";
    }
}
这里是触发它的标记:

<h:form>
        <h:commandLink value="LOGOUT" action="#{logoutBB.releaseUserState}"/>
    </h:form>

我的疑问是:

  • 如何使注销功能正常工作

  • 是否必须始终在我的EJB上使用EJB安全注释以允许访问?(当使用安全域时)

  • 我应该用servlet而不是EJB来实现这一点吗

  • 这种方法错了吗?我应该尝试其他方法注销吗


首先,我的建议是不要在EJB中调用FacesContext,因为FacesContext是“视图层”的一个元素。EJB的目的是表示“业务逻辑层”,最佳实践是将业务逻辑与de视图隔离,因为您可以从多种类型的视图访问业务逻辑

关于如何结束会话,我建议执行以下操作:

创建一个servlet并实现doGet方法,以关闭会话,如下所示:

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
        HttpSession session= req.getSession();
        session.invalidate();
        RequestDispatcher rd = req.getRequestDispatcher("/login.xhtml"); //The url where go after logout
        rd.forward(req,res);
  }
}
因此,您可以在html/xhtml页面中添加以下链接以进行注销:

<a href="/logout">Logout</a>

如果您使用的是JSF,要获取应用程序的上下文路径,可以使用:

<a href="${request.contextPath}/logout">Logout</a>


免责声明:我假设您使用的是JavaEE6。此外,我没有测试代码(但我知道它是有效的)。如果您在编译过程中遇到一些问题,请告诉我

这可能与您的问题有关,但我不确定。EJB如何访问
FacesContext
实例?我个人不认为像
HttPSession
这样的HTTP协议特定对象应该在EJB容器中访问。这是一种关注点没有分开的情况。最好在托管bean中实现注销机制。@Vinet Reynolds我不知道,也许这不正确。我将注销机制移到托管bean而不是EJB,但我得到了相同的错误(我将粘贴上面的完整堆栈跟踪)。您认为注销的最佳做法是什么?也许我不应该这样做?在LogoutBean类中,为什么要注入sessionSupportEJB而不是SessionSupportJBImpl?@perissf,因为我编程到的是接口而不是实现。CDI将在场景后面为我实例化,我会尝试一下,我会让你知道的。我只是有点怀疑。因为我使用jsf,所以我需要使用
h:commandLink
而不是
,当链接返回的值是
/logout
时,servlet会知道需要处理该请求,对吗?servlet是否可以通过检测触发该操作的组件的id来实现这一点?(因此/logout不会出现在url中),因为实现是在servlet中的,您不需要使用h:commandLink,这样就可以正常工作。当应用程序请求/注销时,servlet会使会话无效,并将用户重定向到“/login.xhtml”,您可以将所需的URI放在这里。关于最后一点,您可以向Servlet发送额外的参数,更改URL映射,并在doPost中进行处理。我想我很接近了,但我被重定向到
http://localhost:8080/logout
我得到一个错误404(找不到资源),我认为错误在这里:
req.getRequestDispatcher(“/login.xhtml”)问题在于我设法做到了这一点。这条路比我要做的要简单得多。谢谢