问题
I want to use the Ruby gem RestClient to access records from Rational Team Concert (RTC) over REST URLs. I have done this successfully with other servers. When I use the REST URL in Chrome directly, I can get a record. However, when I use my Ruby code, I get back some page that includes a line:
net.jazz.ajax._appPath = "/ccm0001001/auth/authrequired";
I've tried all sorts of ways to pass the credentials, but nothing seems to work. This is what I want to use:
response = RestClient::Request.new(
:method => :get,
:url => uri,
:user => "username",
:password => "password",
:verify_ssl => OpenSSL::SSL::VERIFY_NONE
).execute
Anyone ever use Ruby (or Python?) to access RTC over REST URLs, or have any ideas what I'm doing wrong?
Thanks!
回答1:
Not sure you are still stuck here, but for anyone else this might help.
First Rational Team Concert(RTC) and the other Jazz based products default to Form based authentication by default, this can be changed by the Jazz Administrators to support the standard Basic authentication or more complex methods like certificate based authentication for common access cards and the like TN0013: Jazz Team Server Authentication Explained. It is easy to tell if you have Form or Basic authentication, when you try and login via the browser are you directed to a login servlet page or prompted for an operating system/browser dialog
Form Auth redirects to login page like this:
Basic Auth prompts via browser:
I'll show some examples using Python and the Requests module to simplify the code, here is the leading boiler plate that proceeds the below snippets.
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'}
If your administrator has activated Basic auth, then the example you provided would be sufficient as the authentication needed would already be in your session and when you requested a secured resource the credentials will be provided and your request will succeed.
session.auth = (jazz_user, jazz_pass)
# Request a protected resource, auth creds are stored in session
response = session.get(base_url + auth_uri)
Since your snippet above is not working, I would assume you are using Form authentication. In this case we need to do the standard form auth handshake of request a protected resource, follow redirect to form, post credentials to form with provided session id, verify we are logged in, and either follow redirect or retry protected resource.
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
I have not accessed a certificate based authentication server or have one set so I don't have any experience using the API against that yet.
Posted a full example that should work for either Basic or Form auth as a GitHub gist
Gist - rtc_request_example.py
Should give you an output like this:
(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"]
}
-Sean
回答2:
Almost 6 years later, I remember to post some code I got working... This is my shitty Ruby implementation.
#!/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']
)
来源:https://stackoverflow.com/questions/26252991/ruby-restclient-to-access-rational-team-concert-rtc-rest