1

我使用 JavaEE、JSF 和一个 Servlet 构建了 Web 应用程序。

我通过 Glassfish 和 web.xml 使用安全性。当我登录时,我可以做任何我被允许做的事情,但是一旦我退出,问题就会发生。

正是我注销,我被重定向到主页,在其他(不安全的)页面中会话不再可见,但是一旦我进入安全页面 - 这里它被命名为secured.xhtml - 我得到我的会话回来我可以再次看到我的信息并做我之前被允许做的任何事情。

Imo 问题始于web.xml 中的用户数据约束和传输保证设置为CONFIDENTIAL。如果我没有设置它,我的信息在其他页面上不可见,但注销仍然不起作用,如果设置它只是在所有页面上显示它,如前所述。

这是我的 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app
    id="WebApp_ID" version="3.1"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <display-name>IssueTrack</display-name>

    <!-- Change to "Production" when you are ready to deploy -->
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>

    <!-- Welcome page -->
    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>

    <!-- JSF mapping -->
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map these files with JSF -->
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.faces</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>issuetrack-realm</realm-name>
    </login-config>

    <security-role>
        <role-name>User</role-name>
    </security-role>
    <security-role>
        <role-name>Admin</role-name>
    </security-role>

    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/index.xhtml</location>
    </error-page>

    <session-config>
        <tracking-mode>COOKIE</tracking-mode>
        <cookie-config>
            <secure>true</secure>
            <http-only>true</http-only>
        </cookie-config>
        <session-timeout>5</session-timeout>
    </session-config>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Secured pages</web-resource-name>
            <description/>
            <url-pattern>secured.xhtml</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <description/>
            <role-name>*</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
</web-app>

LogoutServlet (应该)注销登录的用户。

public class LogoutServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // Destroys the session for this user.
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
            request.logout();
        }

        response.sendRedirect("/");
    }
}

编辑

context.xml 看起来像这样

<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/" />

glassfish-web.xml 看起来像

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC 
    "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" 
    "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="/">
    <context-root>/</context-root>
    <security-role-mapping>
        <role-name>Admin</role-name>
        <principal-name>Admin</principal-name> 
        <group-name>Admin</group-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>User</role-name>
        <principal-name>User</principal-name> 
        <group-name>User</group-name>
    </security-role-mapping>
</glassfish-web-app>

我的豆子都是这样的。。

@Named
@RequestScoped
public class IssueBean extends BasicBean {

    private long id;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    @Inject
    private IssueService gServ;

    private Issue issue = new Issue();

    public List<Issue> getIssues() {
        try {
            return gServ.viewAll();
        } catch (ValidationException ex) {
            showException(ex);
            return null;
        }
    }

    public Issue getIssueById() {
        if (id < 1) {
            navigate("/issues.xhtml");
        }
        try {
            issue = gServ.view(id);
        } catch (ValidationException ex) {
            showException(ex);
        }
        if (issue == null || issue.getPriority()== null) {
            navigate("/issues.xhtml");
        }
        return issue;
    }

    public Issue getIssue() {
        return issue;
    }

    public void setIssue(Issue issue) {
        this.issue = issue;
    }

    public String saveIssue() {
        try {
            gServ.add(issue);
            return "/issues.xhtml?faces-redirect=true";
        } catch (ValidationException ex) {
            showException(ex);
            return "";
        }
    }

    public String updateIssue() {
        try {
            gServ.edit(issue);
            return "/issues.xhtml?faces-redirect=true";
        } catch (ValidationException ex) {
            showException(ex);
            return "";
        }
    }

    public void init() {
        if (id < 1) {
            navigate("/issues.xhtml");
        }
        try {
            issue = gServ.view(id);
        } catch (ValidationException ex) {
            showException(ex);
        }
        if (issue == null || issue.getPriority()== null) {
            navigate("/issues.xhtml");
        }
    }

}

Basic Bean 看起来像这样的地方

public class BasicBean {
    protected void navigate(String where) {
        ConfigurableNavigationHandler nav
                = (ConfigurableNavigationHandler) FacesContext.getCurrentInstance().getApplication().getNavigationHandler();

        nav.performNavigation(where);
    }

    protected void showException(Exception ex){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Validation Error - " + ex.getMessage(), ex.toString()));    
    }
}
4

2 回答 2

2

我猜这是因为您在应用程序中使用BASIC auth 方法,它不需要 cookie、会话标识符和登录页面,而是使用标准 HTTP 标头。这意味着一旦用户通过身份验证,每个请求都包含登录信息,因此用户在下次访问该站点时会自动登录。

所以处理它的一种方法是实现基于表单的身份验证。或者,如果您希望坚持使用此线程中给出的BASIC 使用建议。

有关身份验证机制的更多信息,请参阅Java EE 教程

于 2015-05-01T19:51:44.790 回答
1

我认为您可以使用以前的安全页面,因为会话正在被您的浏览器缓存。包括以下内容作为注销的一部分,以便不缓存响应。这也应该适用于所有浏览器。

response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
于 2015-04-30T11:29:51.350 回答