我使用基于JDBC表单的安全领域,我想实现注销,但是当我点击链接时,我看到了这个例外:
java.lang.RuntimeException:java.security.AccessControlException: 访问被拒绝(java.lang.reflect.ReflectPermission suppressAccessChecks)...由以下原因引起: java.security.AccessControlException:访问被拒绝 (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();
}
}
}
这里我从支持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上使用ejbs安全注释来允许访问?(使用安全领域时)
我应该用servlet而不是EJB吗?
这种做法是否错误,我应该尝试注销其他内容吗?
答案 0 :(得分:5)
首先,我的建议是你不要在EJB中调用FacesContext,因为FacesContext是“视图层”的一个元素。 EJB的目的是代表“Bussines Logic Layer”,最佳实践是将商务逻辑与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);
}
}
因此,您可以在html / xhtml页面中添加以下链接以进行注销:
<a href="/logout">Logout</a>
如果您使用的是JSF,要获取应用程序的上下文路径,您可以使用:
<a href="${request.contextPath}/logout">Logout</a>
免责声明:我假设您正在使用Java EE 6.此外,我没有测试代码(但我知道它有效)如果您有一些编译问题请告诉我