You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java调用Duo Admin API添加Authorization和Date头后401错误如何解决

错误根因
  • 认证方式不符合Duo规范:Duo Admin API不使用普通的账号密码Basic认证,要求基于HMAC-SHA1的签名认证,你直接对用户名密码做Base64生成的Authorization头不被识别
  • 请求路径缺失:创建用户的接口路径为/admin/v1/users,你当前只请求了API根域名,没有指定接口路径
  • 请求体格式错误:Duo Admin API接收application/x-www-form-urlencoded格式的参数,你传递的JSON格式参数无法被解析
修复后可运行代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class DuoAdminAPI {
    // 替换为你自己Duo后台的对应值
    private static final String IKEY = "你的Integration Key";
    private static final String SKEY = "你的Secret Key";
    private static final String API_HOST = "api-e9770554.duosecurity.com";
    private static final String HMAC_ALGORITHM = "HmacSHA1";

    // 字节数组转十六进制字符串工具
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    // 生成Duo要求的签名
    private static String generateDuoSignature(String date, String method, String path, String params) throws Exception {
        String canonicalString = String.join("\n",
                date,
                method.toUpperCase(),
                API_HOST.toLowerCase(),
                path,
                params
        );
        Mac mac = Mac.getInstance(HMAC_ALGORITHM);
        mac.init(new SecretKeySpec(SKEY.getBytes(), HMAC_ALGORITHM));
        return bytesToHex(mac.doFinal(canonicalString.getBytes()));
    }

    public static void POSTRequest() throws Exception {
        String dateTime = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME);
        String path = "/admin/v1/users";
        // 表单格式参数,创建用户必填参数可根据需求调整
        String postParams = "username=testuser&email=test@example.com&realname=测试用户";
        String signature = generateDuoSignature(dateTime, "POST", path, postParams);
        // 生成符合要求的Authorization头
        String authString = IKEY + ":" + signature;
        String basicAuth = "Basic " + Base64.getEncoder().encodeToString(authString.getBytes());

        URL obj = new URL("https://" + API_HOST + path);
        HttpURLConnection postConnection = (HttpURLConnection) obj.openConnection();
        postConnection.setRequestMethod("POST");
        postConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        postConnection.setRequestProperty("Authorization", basicAuth);
        postConnection.setRequestProperty("Date", dateTime);

        postConnection.setDoOutput(true);
        OutputStream os = postConnection.getOutputStream();
        os.write(postParams.getBytes());
        os.flush();
        os.close();

        int responseCode = postConnection.getResponseCode();
        System.out.println("POST响应码: " + responseCode);
        System.out.println("POST响应消息: " + postConnection.getResponseMessage());

        BufferedReader in = new BufferedReader(new InputStreamReader(
                responseCode >= 200 && responseCode <300 ? postConnection.getInputStream() : postConnection.getErrorStream()
        ));
        String inputLine;
        StringBuffer response = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        System.out.println("响应内容: " + response.toString());
    }

    public static void main(String[] args) throws Exception {
        POSTRequest();
    }
}
注意事项
  • 运行前务必替换IKEY、SKEY为你在Duo Admin后台创建集成时拿到的实际密钥,不要直接使用示例值
  • 确认你的Duo Admin集成已经开启了用户写入权限,否则依然会报权限错误
  • 确保运行代码的服务器本地时间和标准时间误差不超过5分钟,否则会出现签名验证失败的问题
  • 如果需要传递更多用户参数,可以调整postParams里的键值对,参数名要和接口要求完全一致

内容的提问来源于stack exchange,提问作者Jhonnysins

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 08:39:03