使用tomcat基本身份验证从Web应用程序注销

时间:2012-05-28 15:09:34

标签: apache tomcat jsf-2 basic-authentication

我正在为我的网络应用程序使用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");
}

现在,当调用logout时,它会重定向到另一个应该要求身份验证的页面。但是它会在用户登录时呈现.PS:当用户第一次在地址栏中键入同一页面的URL时,会向他显示身份验证质询(这意味着在保护页面密码时没有问题)

3 个答案:

答案 0 :(得分:16)

您正在使用HTTP BASIC身份验证,而不是使用FORM进行HTTP j_security_check身份验证。 BASIC身份验证由来自浏览器端的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身份验证。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

public void logout() throws IOException {
    HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
    try {
        request.logout();
    } catch (ServletException ex) {
        throw new IOException(ex);
    }
}