You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Java调用带SSO的Jira Rest API遇数据获取失败及400错误问题

Jira REST API 调用问题(SSO认证场景)

我目前在通过Jira REST API获取数据时遇到了认证相关的异常,系统采用Windows账号自动登录的SSO认证,已经通过JKS文件解决了初始SSL问题,但仍存在以下两种异常情况,希望能得到分析和解决方案:

场景1:不带参数调用搜索接口

调用地址:https://jira.f.bbg/rest/api/2/search?jql

  • Java代码返回结果:{"startAt":0,"maxResults":50,"total":0,"issues":[]}
  • 浏览器隐私窗口返回结果:{"startAt":0,"maxResults":50,"total":0,"issues":[]}
  • 正常登录状态的浏览器:可以正常获取目标数据

场景2:带project参数调用搜索接口

调用地址:https://jira.f.bbg/rest/api/2/search?jql=project=PARE2

  • Java代码抛出异常:java.io.IOException: Server returned HTTP response code: 400
  • 浏览器隐私窗口返回结果:{"errorMessages":["La valeur 'PARE2' n'existe pas pour le champ 'project'."],"errors":{}}(法语翻译:“PARE2”值在project字段中不存在)
  • 正常登录状态的浏览器:可以正常获取目标数据

相关Java代码

public String recuperer(String adresse) throws Exception {
    URL url = new URL(adresse);
    HttpsURLConnection.setDefaultSSLSocketFactory(SecuriteHelper.getSslContext().getSocketFactory());
    HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
    con.setRequestMethod("GET");
    con.setRequestProperty("Accept-Charset", "UTF-8");
    con.setRequestProperty("Accept", "application/json");
    StringBuilder sb = new StringBuilder();
    BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
    for (String line; (line = reader.readLine()) != null;) {
        sb.append(line);
    }
    return sb.toString();
}

问题分析

从现象来看,核心问题是SSO认证未通过

  1. 正常浏览器能获取数据,是因为已经通过Windows账号完成了SSO登录,请求携带了有效的认证信息;而Java代码和隐私窗口都没有携带认证凭证,处于未授权状态。
  2. 场景1返回空结果:Jira对未授权请求的处理是返回“无权限查看的结果”,而非直接返回401,所以显示total:0
  3. 场景2的400错误:未授权状态下,Jira的权限系统会限制你能访问的项目列表,此时PARE2不在你的“可见项目”范围内(甚至你没有权限查看任何项目),因此Jira返回“项目不存在”的错误,本质还是认证缺失导致的权限问题。

解决方案

1. 在Java请求中实现SSO认证

因为是Windows账号自动登录,大概率是NTLM或Kerberos认证,这里提供两种常见实现方式:

方式A:NTLM认证

利用Java的Authenticator自动处理NTLM认证流程:

public String recuperer(String adresse) throws Exception {
    // 设置NTLM认证信息(当前Windows用户,格式可能需要是 DOMAIN\username)
    String domainUser = System.getProperty("user.name");
    String password = ""; // 部分NTLM环境无需密码,或需填写域密码
    Authenticator.setDefault(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(domainUser, password.toCharArray());
        }
    });

    URL url = new URL(adresse);
    HttpsURLConnection.setDefaultSSLSocketFactory(SecuriteHelper.getSslContext().getSocketFactory());
    HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
    con.setRequestMethod("GET");
    con.setRequestProperty("Accept-Charset", "UTF-8");
    con.setRequestProperty("Accept", "application/json");
    
    // 处理响应(注意:如果认证失败,con.getInputStream()会抛出401异常,需要捕获处理)
    StringBuilder sb = new StringBuilder();
    BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
    for (String line; (line = reader.readLine()) != null;) {
        sb.append(line);
    }
    return sb.toString();
}

方式B:Kerberos认证

如果是Kerberos协议的SSO,需要配置Java的Kerberos环境:

  • 配置krb5.conf文件,指定域控制器等信息
  • 使用LoginContext获取Kerberos票据,然后在请求头中添加Authorization: Negotiate <票据>

2. 确保URL参数正确编码

虽然不是核心问题,但为了避免参数解析错误,建议对JQL参数进行URL编码:

String jql = "project=PARE2";
String encodedJql = URLEncoder.encode(jql, StandardCharsets.UTF_8.toString());
String adresse = "https://jira.f.bbg/rest/api/2/search?jql=" + encodedJql;

3. 临时测试方案:复用浏览器认证Cookie

可以先从正常登录的浏览器中复制Jira的会话Cookie(比如JSESSIONID、SSO相关Cookie),在Java请求中添加Cookie头,验证是否能获取数据:

con.setRequestProperty("Cookie", "JSESSIONID=your_session_id; SSO_COOKIE=your_sso_cookie");

如果此方法有效,说明认证问题确实是核心原因,需要进一步实现自动认证逻辑。


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

火山引擎 最新活动