【问题标题】:Basic Auth Authorization header and base 64 encodingBasic Auth Authorization 标头和 base 64 编码
【发布时间】:2020-12-04 12:37:22
【问题描述】:

我有一个希望与之交换数据的供应商。他们希望我获取他们提供给我的用户名和密码,并将其用于获取请求的 Authorization 标头。

现在是我肮脏的小秘密。我以前从未创建过授权标头。

所以我做了一堆研究并找出以下代码。

public static final String          AUTH_SEPARATOR = ":";
private static final String         AUTH_TYPE = "Basic ";
public static final String          HEADER_AUTHORIZATION = "Authorization";

public static void addAuthHeader(Map<String, String> headers, String user, String password) {
    String secretKey = user
            + AUTH_SEPARATOR
            + password;
    byte[] tokenBytes = secretKey.getBytes();
    String token64 = Base64.getEncoder().encodeToString(tokenBytes);
    String auth = AUTH_TYPE + token64;
    headers.put(HEADER_AUTHORIZATION, auth);
}

我运行它,但我没有得到任何回应。嗯。所以我去向他们提出支持请求,我想创建一个示例,所以我打开邮递员并使用他们为邮递员提供的 API。首先,我为我正在复制的 API 运行一个,它可以工作。嗯。

然后我修改该 API 并使用我的用户名和密码而不是示例中包含的用户名和密码,它工作正常。呲牙咧嘴!

所以我敲了一下,发现 postman 创建的 auth 中的 Base64 字符串与我创建的略有不同。

所以,回到研究中,我发现的所有代码看起来都很像我的,尽管由于版本差异我不得不对其进行一些更新。字符串仍然不同,现在我正在寻求帮助。肯定有人解决了这个问题。

来自邮递员的字符串 "Basic THVKZ...FvTg==" 上面代码中的字符串 "Basic THVKZ...FvTiA="

我怎么做错了,结果只有三个字节的差异?

【问题讨论】:

  • 可能来自编码,特别是如果您的密码中有特殊字符。您是否尝试在 getBytes(encoding) 方法中指定编码?

标签: java http-headers base64


【解决方案1】:

Tg==N 的 base64。

TiA=N 的 base64(如 N,然后是空格)。

Sooo,听起来邮递员在上面贴了一个空格,而你没有。希望,如果你在 base64 编码的最后添加一个空格,你应该得到与邮递员给你的字符串完全相同的字符串,并且希望到那时一切都会解决:)

【讨论】:

  • 我想我最终会考虑解码字符串并查看它的样子。我尝试添加一个空间,它现在更近了,但仍然不同。我按照另一个答案的建议在base64encode.org 输入了相同的字符串,它给了我与邮递员相同的答案。这里发生了一些奇怪的事情。
【解决方案2】:

Postman 使用 UTF-8 进行基本身份验证编码,请查看 https://github.com/postmanlabs/postman-app-support/issues/4070

像这样改变你的代码

secretKey.getBytes(StandardCharsets.UTF_8);

https://www.base64encode.org/ 用于测试

【讨论】:

  • 显然默认使用的是UTF 8。加密字符串没有变化。
【解决方案3】:

问题是由填充引起的。我仍然不明白为什么,但我正在编码的字符串是 49 字节长,不能被 3 整除,这意味着填充开始发挥作用。

当我将代码更改为以下内容时:

    String token64 = Base64.getEncoder().withoutPadding().encodeToString(tokenBytes);

然后运行它,我得到相同的字符串减去 base64 用作填充字符的末尾的两个 ==。将其发送到服务器得到了我正在寻找的答案。

既然软件这么难,为什么还要叫它软件?

【讨论】:

    【解决方案4】:

    尊敬的开发人员,他们不是在 OAuth2 上运行吗?如果是这样,请使用下面的代码块并杀死它

     public HttpHeaders getHeaders() {
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
            headers.add("Authorization", "Bearer " + token you are either generating or getting from Eureka discovery service);
            return headers;
        }
    
    
        AuthResponseObjectType getAuthorization() {
            HttpHeaders headers = new HttpHeaders();
            headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
            String auth = basicAuthUsername + ":" + basicAuthPassword;
            byte[] encodedAuth = org.apache.commons.net.util.Base64.encodeBase64(auth.getBytes(StandardCharsets.US_ASCII));
            headers.add("Authorization", "Basic " + new String(encodedAuth));
    
            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
            map.add("grant_type", grantType);
            map.add("username", username);
            map.add("password", password);
            map.add("scope", scope);
    
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
            return restTemplate.exchange(authUrl, HttpMethod.POST, request, AuthResponseObjectType.class).getBody();
    
        }
    

    如果您面临任何挑战,请告诉我,我们可以一起解决

    【讨论】:

    • 这是承载认证,不是基本认证。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 2011-04-03
    • 2015-06-05
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多