9

我正在为我的网络应用程序使用 tomcat 基本身份验证:

我在我的网络应用程序的 web.xml 中添加了以下几行:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>webpages</web-resource-name>
            <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>*</role-name>
    </auth-constraint>

    <user-data-constraint>
        <!-- transport-guarantee can be CONFIDENTIAL, INTEGRAL, or NONE -->
        <transport-guarantee>NONE</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
</login-config>
<security-role>
    <role-name>*</role-name>
</security-role>

我的注销链接:

<h:commandLink value="Logout" action="#{userBean.logout}" />

我的注销链接操作:

public void logout() throws IOException
{
    FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
    FacesContext.getCurrentInstance().getExternalContext().redirect("add_international_job.faces");
}

现在,当调用注销时,它会重定向到另一个需要身份验证的页面。但它是在用户登录时呈现的。 PS:当用户第一次在地址栏中输入同一页面的url时,会出现身份验证挑战(表示该页面密码保护没有问题) .

4

3 回答 3

17

您正在使用 HTTPBASIC身份验证而不是 HTTPFORM身份验证j_security_checkBASIC身份验证由浏览器端的Authorization请求标头完成,与会话无关。

要强制“注销”BASIC身份验证,服务器基本上需要返回 401 响应。

FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.invalidateSession();
externalContext.responseSendError(401, "You are logged out.");
facesContext.responseComplete();

这将显示一个 HTTP 401 错误页面,该页面可自定义<error-page>web.xml.

相反,您也可以返回带有元刷新的 HTML 页面,以便最终用户被重定向到元刷新标题内容中指定的所需目标页面。

FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
externalContext.invalidateSession();
externalContext.setResponseStatus(401);
externalContext.getResponseOutputWriter().write("<html><head><meta http-equiv='refresh' content='0;add_international_job.faces'></head></html>");
facesContext.responseComplete();

这看起来确实相当低级和hacky,但BASIC身份验证也相当低级。使用身份验证时,这不是必需的FORM。只是使会话无效并发送正常的重定向应该可以用于FORM身份验证。

于 2012-05-28T15:41:18.183 回答
1

这是完全不同的东西。您正在使用 BASIC 身份验证来验证用户。这会在第一次请求时提示浏览器输入用户名和密码。从那时起,浏览器将自动将所有后续请求的用户名和密码发送到同一台服务器,因此您的基于 Web 的身份验证只是重新登录它们。会话无效,您输入的任何内容都将消失,但您不能让服务器重新提示用户输入名称和密码。它将继续向同一主机发送相同的用户名和密码,直到您关闭浏览器。这是 BASIC 身份验证的一个缺点。

我通常使用我自己的身份验证,因为它允许更多的自由,但是您有责任确保您的所有资源都受到保护。一个简单的方法是使用 Struts 并覆盖 action servlet perform 方法来进行身份验证。您创建自己的登录页面,而不是让浏览器显示登录对话框。您可以通过将变量保存到他们的会话并在他们发出请求时检查该变量来检查以确保某人已登录。如果设置了 var,它们就可以了。如果没有,您将它们重定向到登录页面。使会话无效将某人注销。

于 2017-05-16T13:29:05.923 回答
0
public void logout() throws IOException {
    HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    try {
        request.logout();
    } catch (ServletException ex) {
        throw new IOException(ex);
    }
}
于 2012-05-31T12:01:17.980 回答