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认证未通过:
- 正常浏览器能获取数据,是因为已经通过Windows账号完成了SSO登录,请求携带了有效的认证信息;而Java代码和隐私窗口都没有携带认证凭证,处于未授权状态。
- 场景1返回空结果:Jira对未授权请求的处理是返回“无权限查看的结果”,而非直接返回401,所以显示
total:0。 - 场景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




