1

我想使用 Ruby gem RestClient 通过 REST URL 从 Rational Team Concert (RTC) 访问记录。我已经用其他服务器成功地做到了这一点。当我直接在 Chrome 中使用 REST URL 时,我可以得到一条记录。但是,当我使用我的 Ruby 代码时,我会返回一些包含一行的页面:

net.jazz.ajax._appPath = "/ccm0001001/auth/authrequired";

我尝试了各种方法来传递凭据,但似乎没有任何效果。这就是我想要使用的:

response = RestClient::Request.new(
    :method => :get,
    :url => uri,
    :user => "username",
    :password => "password",
    :verify_ssl => OpenSSL::SSL::VERIFY_NONE
).execute

任何人曾经使用 Ruby(或 Python?)通过 REST URL 访问 RTC,或者知道我做错了什么?

谢谢!

4

2 回答 2

3

不确定您是否仍然被困在这里,但对其他人来说这可能会有所帮助。

First Rational Team Concert(RTC) 和其他基于 Jazz 的产品默认默认为基于表单的身份验证,这可以由 Jazz 管理员更改以支持标准的基本身份验证或更复杂的方法,例如针对普通访问卡的基于证书的身份验证等TN0013:Jazz Team 服务器身份验证说明。很容易判断您是否具有表单或基本身份验证,当您尝试通过浏览器登录时,您是被定向到登录 servlet 页面还是提示输入操作系统/浏览器对话框

表单身份验证重定向到登录页面,如下所示: 在此处输入图像描述

通过浏览器的基本身份验证提示: 在此处输入图像描述

我将展示一些使用 Python 和 Requests 模块来简化代码的示例,这里是下面代码片段的主要样板。

import requests
# quiet warnings for self-signed certificates
requests.packages.urllib3.disable_warnings()

base_url = "https://jazzserver.demo.com/ccm"
auth_uri = "/authenticated/identity"

jazz_user = "user"
jazz_pass = "secretpassword"

session = requests.Session()
session.verify = False
session.allow_redirects = True
session.headers = {'accept':'application/xml'}

如果您的管理员已激活基本身份验证,那么您提供的示例就足够了,因为所需的身份验证已经在您的会话中,并且当您请求安全资源时,将提供凭据并且您的请求将成功。

session.auth = (jazz_user, jazz_pass)

# Request a protected resource, auth creds are stored in session
response = session.get(base_url + auth_uri)

由于您上面的代码段不起作用,我假设您正在使用表单身份验证。在这种情况下,我们需要执行请求受保护资源的标准表单身份验证握手,遵循重定向到表单,使用提供的会话 ID 将凭据发布到表单,验证我们是否已登录,然后遵循重定向或重试受保护资源。

print "Request for authenticated resource"
response = session.get(base_url + auth_uri)

#print response.text
print response.headers

if 'x-com-ibm-team-repository-web-auth-msg' in response.headers and response.headers['x-com-ibm-team-repository-web-auth-msg'] == 'authrequired':
    print "Not currently authenticated"

    # Form response
    print "Sending login POST"
    login_response = session.post(base_url + '/j_security_check', data={ 'j_username': jazz_user, 'j_password': jazz_pass } )
    print login_response.headers

    if 'x-com-ibm-team-repository-web-auth-msg' in login_response.headers and login_response.headers['x-com-ibm-team-repository-web-auth-msg'] == 'authrequired':
        print "Failed to authenticate"
        print login_response.status_code
        print login_response.text
        raise Exception( "Failed to login: ", login_response.text )

    print "Getting authenticated resource again now that we should be logged in:"
    response = session.get( base_url + auth_uri )

print response.headers
print response.text

我还没有访问基于证书的身份验证服务器或拥有一套,所以我还没有任何使用 API 的经验。

发布了一个完整的示例,该示例适用于 Basic 或 Form auth 作为 GitHub gist

要点 - rtc_request_example.py

应该给你这样的输出:

    (rtc_client)sgwilbur@gura:~/workspaces/rtc_helper$ ./test_ccm.py
    Request for authenticated resource
    {'x-com-ibm-team-repository-web-auth-msg': 'authrequired', 'content-length': '1985', 'set-cookie': 'JSESSIONID=CEF68A74B1A8005EB91A90BA42F3F86A; Path=/ccm/; Secure; HttpOnly, JazzFormAuth=Form; Path=/ccm; Secure', 'expires': 'Wed, 31 Dec 1969 18:00:00 CST', 'server': 'Apache-Coyote/1.1', 'cache-control': 'private', 'date': 'Thu, 15 Jan 2015 18:43:35 GMT', 'content-type': 'text/html;charset=UTF-8'}
    Not currently authenticated
    Sending login POST
    {'content-length': '55', 'set-cookie': 'JSESSIONID=1FE94776634391C83E47210113D1A4D4; Path=/ccm/; Secure; HttpOnly, JSESSIONIDSSO=D91E3A4E3376D567AF93DD031ED48E72; Path=/; Secure; HttpOnly, X-com-ibm-team-foundation-auth-loop-avoidance=false; Secure', 'expires': 'Wed, 31 Dec 1969 18:00:00 CST', 'server': 'Apache-Coyote/1.1', 'cache-control': 'private', 'date': 'Thu, 15 Jan 2015 18:43:36 GMT', 'content-type': 'text/json;charset=utf-8'}
    Getting authenticated resource again now that we should be logged in:
    {'content-length': '55', 'set-cookie': 'X-com-ibm-team-foundation-auth-loop-avoidance=false; Secure', 'expires': 'Wed, 31 Dec 1969 18:00:00 CST', 'server': 'Apache-Coyote/1.1', 'cache-control': 'private', 'date': 'Thu, 15 Jan 2015 18:43:36 GMT', 'content-type': 'text/json;charset=utf-8'}
    {
        "userId": "sgwilbur",
        "roles": [
            "JazzAdmins"]
    }

-肖恩

于 2015-01-15T18:53:27.727 回答
1

差不多 6 年后,我记得发布了一些我开始工作的代码……这是我糟糕的 Ruby 实现。

#!/usr/bin/ruby

require 'HTTParty'
require 'Nokogiri'
require 'pp'

###########################################################################

class Jazz
include HTTParty

def self.jazzSetup(authuri,proxyaddr,proxyport,username,password)
    @authuri=authuri
    @proxyaddr=proxyaddr
    @proxyport=proxyport
    @username=username
    @password=password

    @httparty_options={:verify=>false}
    if(not @proxyaddr.nil?)then
        @httparty_options[:http_proxyaddr]=@proxyaddr
    end
    if(not @proxyport.nil?)then
        @httparty_options[:http_proxyport]=@proxyport
    end
end

def self.jazzGet(inputuri)

    $stderr.puts "\n" + inputuri
    $stderr.puts 'First attempt to get'
    response=get(inputuri,@httparty_options)
    @httparty_options[:headers]={'Cookie'=>response.headers['set-cookie']}
    $stderr.puts "CODE: #{response.code}"
    $stderr.puts "MESG: #{response.message}"

    if(response.headers['x-com-ibm-team-repository-web-auth-msg']=='authrequired')then

        $stderr.puts 'Attempt to authenticate'
        @httparty_options[:query]={'j_username'=>@username,'j_password'=>@password}
        response=post(@authuri,@httparty_options)
        @httparty_options[:headers]={'Cookie'=>response.headers['set-cookie']}
        @httparty_options.delete(:query)
        $stderr.puts "CODE: #{response.code}"
        $stderr.puts "MESG: #{response.message}"

        if(response.headers['x-com-ibm-team-repository-web-auth-msg']=='authfailed')then
            # this might be a decprecated condition, have only see code 401
            $stderr.puts 'Authentication FAILED! (authfailed)'
            exit
        elsif(response.code==401)then
            $stderr.puts 'Authentication FAILED! (401)'
            exit
        else
            $stderr.puts 'Authentication success!'
        end

        $stderr.puts 'Second attempt to get'
        response=get(inputuri,@httparty_options)
        @httparty_options[:headers]={'Cookie'=>response.headers['set-cookie']}
        $stderr.puts "CODE: #{response.code}"
        $stderr.puts "MESG: #{response.message}"
    end

    response
end

end

def getNext(doc)
    rel=doc.xpath('//ds:dataSource').attr('rel')
    if((not rel.nil?) and ("next"==rel.value))then
        doc.xpath('//ds:dataSource').attr('href').value
    else nil end
end

###########################################################################

Jazz.jazzSetup(
    'https://blah.clm.ibmcloud.com/rm/j_security_check',
    '111.111.111.111',80, # proxy settings
    # nil,nil,          # no proxy used
    ENV['j_username'],ENV['j_password']
)
于 2020-11-13T09:59:13.670 回答