首页 > 解决方案 > Spring OAuth2 - 令牌端点的基本身份验证标头中用户名的 URL 编码

问题描述

令牌端点的基本身份验证似乎不符合 OAuth2.0 规范,该规范指定用户名和密码在加入冒号和 base 64 编码之前应进行 URL 编码。见rfc6749

标头的创建应该是:

auth_header = 'Basic' + base64 (urlEncode (client_id) + ':' + urlEncode (client_secret))

因此,在将用户名与密码分开后,需要一个 URL 解码步骤。

Spring 只是使用 BasicAuthenticationFilter 来提取凭据,似乎没有办法扩展它以添加 URL 解码步骤。

那么,这是 Spring security OAuth2 的遗漏吗?如果是这样,猜测应该提出一个错误。我可以将 BasicAuthenticationFilter 替换为具有 URL 解码步骤的过滤器,但有没有更简单的方法?

我目前正在使用 Spring Security 5.0.5

标签: spring-security-oauth2

解决方案


Spring 安全性确实符合 OAuth 2.0 规范。您要问的内容已经包含在BasicAuthenticationFilter. 这是代码的摘录:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        boolean debug = this.logger.isDebugEnabled();
        String header = request.getHeader("Authorization");
        if (header != null && header.startsWith("Basic ")) {
            try {
                String[] tokens = this.extractAndDecodeHeader(header, request);

                assert tokens.length == 2;

过滤器读取具有基本身份验证的标头,然后提取并解码凭据。
在下面的代码中,请注意冒号的索引用作字符串分隔符。

private String[] extractAndDecodeHeader(String header, HttpServletRequest request) throws IOException {
        byte[] base64Token = header.substring(6).getBytes("UTF-8");

        byte[] decoded;
        try {
            decoded = Base64.getDecoder().decode(base64Token);
        } catch (IllegalArgumentException var7) {
            throw new BadCredentialsException("Failed to decode basic authentication token");
        }

        String token = new String(decoded, this.getCredentialsCharset(request));
        int delim = token.indexOf(":");
        if (delim == -1) {
            throw new BadCredentialsException("Invalid basic authentication token");
        } else {
            return new String[]{token.substring(0, delim), token.substring(delim + 1)};
        }
    }

推荐阅读