Apache代理后Jira REST API调用异常:Python报401但curl正常
解决Apache反向代理后Jira REST API双认证401问题
我完全理解你的困惑——curl能正常返回结果,但Python代码却一直报401,核心原因是curl允许发送多个相同的HTTP头字段,而Python的requests库(包括依赖它的python-jira)默认会覆盖重复的头字段。
你的curl命令同时发送了两个Authorization头:一个来自-u jirauser:jirapass(给Jira的认证),另一个是你手动添加的(给Apache代理的认证)。但在Python代码中,auth参数(或python-jira的basic_auth)会自动生成并覆盖你手动添加的Authorization头,导致请求只携带了Jira的认证信息,缺少Apache代理要求的认证,从而返回401 Unauthorized。
下面是两种可行的解决方案:
方案1:使用requests库手动构造双认证头
因为requests的字典式headers会覆盖重复键,所以我们需要用元组列表来定义headers,这样就能发送多个相同的Authorization头,和curl的行为一致:
import requests import base64 # 配置代理(Apache)和Jira的认证信息 proxy_user = "proxyuser" proxy_pass = "proxypass" jira_user = "jirauser" jira_pass = "jirapass" # 生成Base64编码的认证字符串 proxy_auth = base64.b64encode(f"{proxy_user}:{proxy_pass}".encode('utf-8')).decode('utf-8') jira_auth = base64.b64encode(f"{jira_user}:{jira_pass}".encode('utf-8')).decode('utf-8') # 用元组列表定义headers,支持重复的Authorization字段 headers = [ ('Content-Type', 'application/json'), ('Authorization', f'Basic {proxy_auth}'), # Apache代理认证 ('Authorization', f'Basic {jira_auth}') # Jira认证 ] # 发送请求 url = "http://127.0.0.1/jira/rest/api/2/search?jql=key=DEV4" response = requests.get(url, headers=headers) # 验证结果 print(f"响应状态码:{response.status_code}") if response.ok: print("返回数据:", response.json()) else: print("错误信息:", response.text)
方案2:适配python-jira库发送双认证头
python-jira内部依赖requests,我们可以通过自定义requests Session来注入双认证头,避免basic_auth参数覆盖我们的头配置:
from jira import JIRA, JIRAError import requests import base64 import sys # 配置认证信息 proxy_user = "proxyuser" proxy_pass = "proxypass" jira_user = "Jira_username" jira_pass = "Jira_password" # 生成Base64编码的认证字符串 proxy_auth = base64.b64encode(f"{proxy_user}:{proxy_pass}".encode('utf-8')).decode('utf-8') jira_auth = base64.b64encode(f"{jira_user}:{jira_pass}".encode('utf-8')).decode('utf-8') # 创建自定义的requests Session,注入双认证头 session = requests.Session() session.headers.update([ ('X-Atlassian-Token', 'no-check'), ('Cache-Control', 'no-cache'), ('Content-Type', 'application/json'), ('Authorization', f'Basic {proxy_auth}'), ('Authorization', f'Basic {jira_auth}') ]) # 初始化JIRA客户端,使用自定义Session jira_options = { 'server': 'http://127.0.0.1/jira', 'verify': True } try: jira = JIRA( options=jira_options, session=session, # 传入自定义Session validate=True ) # 测试连接:获取项目列表 projects = jira.projects() print(f"成功连接Jira!共获取到{len(projects)}个项目") except JIRAError as e: print(f"初始化Jira连接失败,错误信息:[{e}]") sys.exit()
额外建议:更规范的代理认证方式
如果可以修改Apache配置,建议将代理的认证改为使用Proxy-Authorization头(而非和Jira共用Authorization),这样就不会出现头字段冲突的问题。此时Python代码可以更清晰地分离两种认证:
- 用
auth参数设置Jira的Authorization头 - 在headers中添加
Proxy-Authorization: Basic ...用于Apache代理认证
这种方式更符合HTTP标准,也能避免后续的头字段覆盖问题。
内容的提问来源于stack exchange,提问作者A. Lein
相关产品推荐
相关产品推荐

