3

我的应用程序需要将用户电子邮件地址存储在 cookie 中,以便我可以预先填充登录表单(username == email address)。我在 JavaScript 中设置了 cookie 值。如果我从 JavaScript 读取它,我会得到foo@bar.com. 如果我在 Firefox 的 cookie 查看器中查看它,我会得到foo@bar.com.

但是,当我尝试在 Java 的服务器端读取它时,我只得到foo.

我需要在这里进行某种编码/解码吗?如果是这样,我该如何以一种可以被 JavaScript 和 Java 解码的方式来做到这一点?

提前致谢!-迈克尔

4

4 回答 4

4

来自setValue(String)的javax.servlet.http.Cookie文档:

创建 cookie 后为 cookie 分配一个新值。如果您使用二进制值,您可能需要使用 BASE64 编码。

对于版本 0 cookie,值不应包含空格、方括号、圆括号、等号、逗号、双引号、斜杠、问号、at 符号、冒号和分号。空值在所有浏览器上的行为方式可能不同。

我猜你需要在输入(通过 JavaScript)和输出(通过 Java)的途中对其进行 BASE64 编码

于 2008-11-07T03:12:44.263 回答
0

我找到了两种解决方案。这是第一个。

添加回填充到 Base64 编码的字符串。灵感来自http://fi.am/entry/urlsafe-base64-encodingdecoding-in-two-lines/

在这个解决方案中,JavaScript 保持不变(base64 对所有内容进行编码),服务器端如下所示:

public class CookieDecoder {

private static final Log log = LogFactory.getLog(CookieDecoder.class);

/**
 * @param cookieValue The value of the cookie to decode
 * @return Returns the decoded string
 */
public String decode(String cookieValue) {
    if (cookieValue == null || "".equals(cookieValue)) {
        return null;
    }
    if (!cookieValue.endsWith("=")) {
        cookieValue = padString(cookieValue);
    }
    if (log.isDebugEnabled()) {
        log.debug("Decoding string: " + cookieValue);
    }
    Base64 base64 = new Base64();
    byte[] encodedBytes = cookieValue.getBytes();
    byte[] decodedBytes = base64.decode(encodedBytes);
    String result = new String(decodedBytes);
    if (log.isDebugEnabled()) {
        log.debug("Decoded string to: " + result);
    }
    return result;
}

private String padString(String value) {
    int mod = value.length() % 4;
    if (mod <= 0) {
        return value;
    }
    int numEqs = 4 - mod;
    if (log.isDebugEnabled()) {
        log.debug("Padding value with " + numEqs + " = signs");
    }
    for (int i = 0; i < numEqs; i++) {
        value += "=";
    }
    return value;
}
}

在 JavaScript 方面,您只需要确保对值进行 base64 编码:

var encodedValue = this.base64.encode(value);
document.cookie = name + "=" + encodedValue + 
                  "; expires=" + this.expires.toGMTString() + 
                  "; path=" + this.path;
于 2008-11-07T20:40:48.627 回答
0

第二种解决方案只是对 Base64 编码的字符串进行 URLEncode。我在这里使用公共编解码器进行编码。Java 代码:

public class CookieDecoder {

    private static final Log log = LogFactory.getLog(CookieDecoder.class);

    /**
     * @param cookieValue The value of the cookie to decode
     * @return Returns the decoded string
     */
    public String decode(String cookieValue) {
        if (cookieValue == null || "".equals(cookieValue)) {
            return null;
        }
        if (log.isDebugEnabled()) {
            log.debug("Decoding string: " + cookieValue);
        }
        URLCodec urlCodec = new URLCodec();
        String b64Str;
        try {
            b64Str = urlCodec.decode(cookieValue);
        }
        catch (DecoderException e) {
            log.error("Error decoding string: " + cookieValue);
            return null;
        }
        Base64 base64 = new Base64();
        byte[] encodedBytes = b64Str.getBytes();
        byte[] decodedBytes = base64.decode(encodedBytes);
        String result = new String(decodedBytes);
        if (log.isDebugEnabled()) {
            log.debug("Decoded string to: " + result);
        }
        return result;
    }
}

但现在我也必须在 JavaScript 端对其进行解码......编码:

var encodedValue = this.base64.encode(value);
document.cookie = name + "=" + escape(encodedValue) + 
                  "; expires=" + this.expires.toGMTString() + 
                  "; path=" + this.path;

解码:

var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0)==' ') {
        c = c.substring(1,c.length);
    }
    if (c.indexOf(nameEQ) == 0) {
        var encodedValue = c.substring(nameEQ.length,c.length);
        return this.base64.decode(unescape(encodedValue));
    }
}
return null;
于 2008-11-07T20:45:16.030 回答
0

您需要转义 cookie 的值部分。

document.cookie = name + "=" +escape( value ) 
    + ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" )
    + ( ( path ) ? ";path=" + path : "" ) 
    + ( ( domain ) ? ";domain=" + domain : "" ) 
    + ( ( secure ) ? ";secure" : "" );
于 2008-11-07T02:14:33.273 回答