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

如何用Java(Jersey)调用StreamSets Control Hub API获取认证令牌?

解决Jersey客户端获取Auth Token并调用API的问题

嘿,我看你现在卡在用Jersey实现curl里的认证令牌获取步骤了,导致后续调用API时一直碰到"User not authenticated"错误。咱们照着curl的逻辑一步步来拆解实现,很快就能搞定~

1. 先搞懂curl登录命令的核心操作

你的第一条curl命令其实做了这几件关键的事:

  • 给登录接口https://host:18641/security/public-rest/v1/authentication/login发一个POST请求
  • 请求体是JSON格式的用户名密码:{"userName":"NAME", "password": "xxxxx"}
  • 带着两个必填请求头:Content-Type:application/json和X-Requested-By:SDC
  • 从响应的Cookie里抠出带SSO标识的令牌值,存到sessionToken里给后续接口用

2. 用Jersey写个获取Token的方法

我们单独写一个方法来完成登录并提取令牌,代码直接能用:

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig;

public static String getAuthToken(String loginUrl, String username, String password) throws Exception {
    ClientConfig cc = new ClientConfig();
    // 这里用你已经写好的JerseywithSSL来处理HTTPS证书,避免SSL报错
    Client client = new JerseywithSSL().initClient(cc);
    
    // 构造登录用的JSON请求体
    String loginJson = String.format("{\"userName\":\"%s\", \"password\": \"%s\"}", username, password);
    
    // 发送登录请求
    Response loginResponse = client.target(loginUrl)
            .request(MediaType.APPLICATION_JSON)
            .header("X-Requested-By", "SDC")
            .post(Entity.entity(loginJson, MediaType.APPLICATION_JSON));
    
    // 先检查登录是否成功
    if (loginResponse.getStatus() != 200) {
        throw new RuntimeException("登录失败啦,HTTP状态码:" + loginResponse.getStatus());
    }
    
    // 从响应Cookie里捞SSO令牌(对应curl里的grep SSO操作)
    String sessionToken = null;
    for (NewCookie cookie : loginResponse.getCookies().values()) {
        // 这里要注意:如果curl里的SSO对应的Cookie名是具体的(比如SSO_TOKEN),就把contains改成equals
        if (cookie.getName().contains("SSO")) {
            sessionToken = cookie.getValue();
            break;
        }
    }
    
    if (sessionToken == null) {
        throw new RuntimeException("没从响应Cookie里找到SSO令牌,检查下接口返回的Cookie名对不对");
    }
    
    // 别忘了关闭资源,避免内存泄漏
    loginResponse.close();
    client.close();
    
    return sessionToken;
}

3. 把Token集成到你现有的上传代码里

现在你只需要在testUploadService方法开头先调用上面的getAuthToken拿到令牌,然后把令牌加到请求头里(对应curl里的X-SS-User-Auth-Token:$sessionToken和X-SS-REST-CALL:true)。

修改点如下:

  1. 先获取令牌:
// 第一步:调用登录接口拿令牌
String loginUrl = "https://host:18641/security/public-rest/v1/authentication/login";
String sessionToken = getAuthToken(loginUrl, User, Pass);
  1. 在构建请求头时添加令牌相关的字段,同时可以去掉原来的Basic Auth头(因为API要求用token认证,不是Basic Auth):
invocationBuilder = webTarget.request();
// 注释掉原来的Basic Auth,改用token
// invocationBuilder.header("Authorization", "Basic " + USER_PASS);
invocationBuilder.header("X-Requested-By","SDC");
invocationBuilder.header("X-SS-REST-CALL", "true"); // 这个头curl里有,必须加
invocationBuilder.header("X-SS-User-Auth-Token", sessionToken); // 核心的令牌头
invocationBuilder.header("Content-type", "multipart/form-data; boundary=" + boundary);

4. 几个要注意的坑

  • SSL证书问题:确保你的JerseywithSSL类能正确处理HTTPS的证书,不然登录请求直接就失败了
  • Cookie名称匹配:如果curl里的grep是找具体的Cookie名(比如SSO_SESSION),记得把代码里的contains("SSO")改成equals("具体Cookie名")
  • 资源关闭:finally块里的资源关闭最好加个非空判断,避免空指针
  • 请求体格式:登录请求必须是JSON,不能用表单或multipart,这点别搞错了

最后,整合后的完整testUploadService方法大概是这样:

public static String testUploadService(String httpURL, File filePath,String User,String Pass,Processing processing) throws Exception { 
    // 第一步:获取认证令牌
    String loginUrl = "https://host:18641/security/public-rest/v1/authentication/login";
    String sessionToken = getAuthToken(loginUrl, User, Pass);

    // 原有变量定义
    ClientConfig clientConfig = null; 
    Client client = null; 
    WebTarget webTarget = null; 
    Invocation.Builder invocationBuilder = null; 
    Response response = null; 
    FileDataBodyPart fileDataBodyPart = null; 
    FormDataMultiPart formDataMultiPart = null; 
    int responseCode; 
    String responseMessageFromServer = null; 
    String responseString = null; 
    String boundary = "=-=" + System.currentTimeMillis() + "=-="; 

    try{ 
        ClientConfig cc = new ClientConfig(); 
        cc.register(MultiPartFeature.class); 
        try { 
            client = new JerseywithSSL().initClient(cc); 
        } catch (KeyManagementException e) { 
            e.printStackTrace(); 
        } catch (NoSuchAlgorithmException e) { 
            e.printStackTrace(); 
        } 
        webTarget = client.target(httpURL); 

        // 构造文件上传的multipart内容
        fileDataBodyPart = new FileDataBodyPart("file", filePath, MediaType.APPLICATION_OCTET_STREAM_TYPE); 
        formDataMultiPart = new FormDataMultiPart(); 
        formDataMultiPart.bodyPart(fileDataBodyPart); 

        // 构建请求头,添加令牌
        invocationBuilder = webTarget.request();
        invocationBuilder.header("X-Requested-By","SDC");
        invocationBuilder.header("X-SS-REST-CALL", "true");
        invocationBuilder.header("X-SS-User-Auth-Token", sessionToken);
        invocationBuilder.header("Content-type", "multipart/form-data; boundary=" + boundary); 

        try{
            response = invocationBuilder.post(Entity.entity(formDataMultiPart, MediaType.MULTIPART_FORM_DATA));
        } catch(Exception ex){ 
            ex.printStackTrace(); 
        } 

        responseCode = response.getStatus(); 
        System.out.println("Response code: " + responseCode); 
        if (response.getStatus() != 200) { 
            // 这里可以根据实际情况抛出异常或者处理错误
        } 
        System.out.println("Check 6"); 

        responseMessageFromServer = response.getStatusInfo().getReasonPhrase(); 
        System.out.println("ResponseMessageFromServer: " + responseMessageFromServer); 
        System.out.println("Check 7"); 

        processing.setlabel("Finished"); 
        processing.setprogress(100); 

        responseString = response.readEntity(String.class); 
        processing.finished("Server Response Code - "+responseCode + "\n ResponseMessageFromServer: " + responseString); 

    } catch(Exception ex) { 
        ex.printStackTrace(); 
        JOptionPane.showMessageDialog(null, "Error!! \n Make sure you are connected to Dell Internal Network"); 
        processing.dispose(); 
    } finally{ 
        // 安全关闭资源,加非空判断
        if (fileDataBodyPart != null) fileDataBodyPart.cleanup(); 
        if (formDataMultiPart != null) {
            formDataMultiPart.cleanup(); 
            formDataMultiPart.close(); 
        }
        if (response != null) response.close(); 
        if (client != null) client.close(); 
    } 
    return responseString; 
}

这样应该就能顺利拿到令牌,然后正常调用API了,不会再报认证错误啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:04:06