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

sfr*_*frj 5 java security java-ee ejb-3.0 java-ee-6

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

java.lang.RuntimeException:java.security.AccessControlException:access denied(java.lang.reflect.ReflectPermission suppressAccessChecks)...由以下引起:java.security.AccessControlException:access denied(java.lang.reflect.ReflectPermission suppressAccessChecks)

这是我为执行loggout而创建的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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里我从一个支持bean调用它:

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

    @EJB
    private SessionSupportEJB sessionSupportEJB;

    public String logout() {
        sessionSupportEJB.releaseUserState();
        return "index.xhtml?faces-redirect=true";
    }
}
Run Code Online (Sandbox Code Playgroud)

这里应该触发它的标记:

<h:form>
        <h:commandLink value="LOGOUT" action="#{logoutBB.releaseUserState}"/>
    </h:form>
Run Code Online (Sandbox Code Playgroud)

我的怀疑是:

  • 如何使注销功能起作用?

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

  • 我应该用servlet代替EJB吗?

  • 这种方法是错误的,我应该尝试其他注销吗?

Ern*_*oso 5

首先,我的建议是你不要在EJB中调用FacesContext,因为FacesContext是"视图层"的一个元素.EJB的目的是代表"Bussines逻辑层",最佳实践是将商务逻辑与de View隔离,因为您可以从许多类型的视图中访问bussines逻辑.

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

创建一个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);
  }
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以在html/xhtml页面中添加以下链接以进行注销:

<a href="/logout">Logout</a>
Run Code Online (Sandbox Code Playgroud)

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

<a href="${request.contextPath}/logout">Logout</a>
Run Code Online (Sandbox Code Playgroud)

免责声明:我假设您正在使用Java EE 6.此外,我没有测试代码(但我知道它有效)如果您有一些编译问题请告诉我