如何在JSF中添加cookie?

时间:2014-01-05 13:19:24

标签: cookies jsf-2

当我添加如下cookie时:

FacesContext.getCurrentInstance().getExternalContext().addResponseCookie("Test", "Test", null);

然后它运行良好,但cookie成为会话cookie,其最大年龄为-1

当我尝试如下:

Map<String, Object> properties = new HashMap<>();
properties.put("domain", "test");
properties.put("maxAge", 31536000);
properties.put("secure", false); 
properties.put("path","/");
FacesContext.getCurrentInstance().getExternalContext().addResponseCookie("Test", "Test", properties);

然后我在任何地方都看不到cookie。我不明白为什么。

我正在使用Tomcat 7。

2 个答案:

答案 0 :(得分:26)

您的具体案例失败,因为域名设置错误。 Cookie是特定于域的。您无法在其他域上设置Cookie。如果您未指定域,则它将默认为当前请求URI的域。仅当您打算在常见或不同的域上设置Cookie时,Cookie#setDomain()才有用。例如。如果您有foo.example.combar.example.com,那么您可以通过该方法为其他域设置Cookie,或将域设置为.example.com(带有前导期!)以在之间共享Cookie这两个子域名。

所以,这应该在你的特定情况下做到:

String name = "cookiename";
String value = "cookievalue";
Map<String, Object> properties = new HashMap<>();
properties.put("maxAge", 31536000);
properties.put("path", "/");
externalContext.addResponseCookie(name, URLEncoder.encode(value, "UTF-8"), properties);

请注意,显式设置路径非常重要,以防您打算在webapp-wide范围内使用cookie,否则默认为当前路径,当在第一次在子文件夹中设置时,该路径当然会失败。任何父文件夹都无法访问此类cookie。上面的另一个答案没有正确考虑到这一点,因为它不必要地错误地重用现有的cookie而不是全新的。另见a.o. In Java servlet, cookie.getMaxAge() always returns -1

关于在JSF中检索cookie,请使用ExternalContext#getRequestCookieMap()

Cookie cookie = (Cookie) externalContext.getRequestCookieMap().get(name);
String value = URLDecoder.decode(cookie.getValue(), "UTF-8");
// ...

请注意,我在设置/检索之前对cookie值进行了网址编码/解码,否则您会遇到以下相关问题中提到的问题:Why do cookie values with whitespace arrive at the client side with quotes?java.lang.IllegalArgumentException: Control character in cookie value or attribute

尽管如此,我确实同意JSF API在检索和设置cookie方面有些不透明。出于此目的,JSF实用程序库OmniFacesseveral useful utility methods中有Faces utility class,隐式将默认值设置为cookie属性并对值进行URL编码/解码。

// Getting a cookie value.
String value = Faces.getRequestCookie(name);

// Setting a session cookie in current path.
Faces.addResponseCookie(name, value, -1);

// Setting a session cookie in current domain.
Faces.addResponseCookie(name, value, "/", -1);

// Setting a (sub)domain-wide session cookie.
Faces.addResponseCookie(name, value, ".example.com", "/", -1);

// Setting a cookie with max age of 1 year in current domain.
Faces.addResponseCookie(name, value, "/", (int) TimeUnit.DAYS.toSeconds(365));

// Removing a cookie from current domain.
Faces.removeResponseCookie(name, "/");

答案 1 :(得分:22)

试试这个:

public class CookieHelper {

  public void setCookie(String name, String value, int expiry) {

    FacesContext facesContext = FacesContext.getCurrentInstance();

    HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
    Cookie cookie = null;

    Cookie[] userCookies = request.getCookies();
    if (userCookies != null && userCookies.length > 0 ) {
        for (int i = 0; i < userCookies.length; i++) {
            if (userCookies[i].getName().equals(name)) {
                cookie = userCookies[i];
                break;
            }
        }
    }

    if (cookie != null) {
        cookie.setValue(value);
    } else {
        cookie = new Cookie(name, value);
        cookie.setPath(request.getContextPath());
    }

    cookie.setMaxAge(expiry);

    HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
    response.addCookie(cookie);
  }

  public Cookie getCookie(String name) {

    FacesContext facesContext = FacesContext.getCurrentInstance();

    HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
    Cookie cookie = null;

    Cookie[] userCookies = request.getCookies();
    if (userCookies != null && userCookies.length > 0 ) {
        for (int i = 0; i < userCookies.length; i++) {
            if (userCookies[i].getName().equals(name)) {
                cookie = userCookies[i];
                return cookie;
            }
        }
    }
    return null;
  }
}