jira支持通过api进行一系列的操作,对于java客户端,jira提供了JiraRestClient客户端。但官方的Client仅支持使用用户名密码认证,没有对OAuth的支持。本文在JiraRestClient基础上提供一种支持OAuth认证的方式。
1、用户名密码认证方式
使用JiraRestClient客户端,我们只需要添加如下maven依赖:
<dependency>
<groupId>com.atlassian.jira</groupId>
<artifactId>jira-rest-java-client-core</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>io.atlassian.fugue</groupId>
<artifactId>fugue</artifactId>
<version>4.7.2</version>
</dependency>
使用用户名密码的认证操作示例如下:
public class JiraDemo {
public static void main(String[] args) {
JiraRestClient client = loginJira("http://localhost:8080","username","pwassword");
//根据key查询issue
Issue issue =client.getIssueClient().getIssue("key-1").claim();
}
private static JiraRestClient loginJira(String url,String userName,String pwd){
AsynchronousJiraRestClientFactory asynchronousJiraRestClientFactory = new AsynchronousJiraRestClientFactory();
JiraRestClient jiraRestClient = asynchronousJiraRestClientFactory.createWithBasicHttpAuthentication(
URI.create(url), userName,pwd);
return jiraRestClient;
}
}
2、OAuth认证流程
通过OAuth进行权限认证,官网有支持OAuth的操作步骤,这里不细述,可参考官网文档,简单来说就是需要配置一个Application link。配置完之后,我们需要拿到2个配置参数,一个是Consumer key,一个是生成的私钥。
然后需要调用api拿到一个access token,认证流程如下:
这里主要有2步操作,1是根据Consumer key和私钥调用api获取一个临时的request token和一个认证链接(具体操作下面第3步),用户点击认证链接之后拿到页面上的一个secret,2是根据这个secret和request token调用api获取一个access token(具体操作下面第4步),拿到access token之后,后续的对jira的相关操作只需要使用这个token即可(具体操作下面第5步)。
因为涉及到OAuth的操作,需要导入2个包:
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client</artifactId>
<version>1.22.0</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>1.11.0-beta</version>
</dependency>
3、获取request token
根据Consumer key和私钥调用api获取一个临时的request token代码如下:
private static void getRequestToken(String jiraBaseUrl, String consumerKey, String privateKey)throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
//request-token获取路径
String authorizationUrl = jiraBaseUrl + "/plugins/servlet/oauth/request-token";;
JiraOAuthGetTemporaryToken oAuthGetTemporaryToken = new JiraOAuthGetTemporaryToken(authorizationUrl);
oAuthGetTemporaryToken.consumerKey = consumerKey;
oAuthGetTemporaryToken.signer = getOAuthRsaSigner(privateKey);
oAuthGetTemporaryToken.transport = new ApacheHttpTransport();
oAuthGetTemporaryToken.callback = "oob";
OAuthCredentialsResponse response = oAuthGetTemporaryToken.execute();
OAuthAuthorizeTemporaryTokenUrl authorizationURL = new OAuthAuthorizeTemporaryTokenUrl(authorizationUrl);
authorizationURL.temporaryToken = response.token;
System.out.println("request token="+response.token);//request token
System.out.println("authorizationURL="+authorizationURL.toString());//认证链接
}
/**
执行结果
request token=oSqRQQGrByucmpQSrsGtVlMtE2A0UJYs
authorizationURL=http://localhost:8080/plugins/servlet/oauth/request-token?oauth_token=oSqRQQGrByucmpQSrsGtVlMtE2A0UJYs
**/
其中JiraOAuthGetTemporaryToken代码如下:
public class JiraOAuthGetTemporaryToken extends OAuthGetTemporaryToken {
/**
* @param authorizationServerUrl encoded authorization server URL
*/
public JiraOAuthGetTemporaryToken(String authorizationServerUrl) {
super(authorizationServerUrl);
this.usePost = true;
}
}
执行之后获取到request token和认证链接,点击认证链接之后,点击 允许 获取权限,页面会出现一个secret字符串,记录下这个字符串。
4、获取access token
拿到secret和request token之后,就可以申请一个access token令牌了,申请代码如下:
private static void getAccessToken(String jiraBaseUrl, String consumerKey, String privateKey,String secret,String requestToken)throws Exception{
//access token获取路径
String accessTokenUrl = jiraBaseUrl + "/plugins/servlet/oauth/access-token";
JiraOAuthGetAccessToken accessToken = new JiraOAuthGetAccessToken(accessTokenUrl);
accessToken.consumerKey = consumerKey;
accessToken.signer = getOAuthRsaSigner(privateKey);
accessToken.transport = new ApacheHttpTransport();
accessToken.verifier = secret;
accessToken.temporaryToken = requestToken;
OAuthCredentialsResponse response = accessToken.execute();
System.out.println("AccessToken"+response.token);
}
其中JiraOAuthGetAccessToken代码如下:
public class JiraOAuthGetAccessToken extends OAuthGetAccessToken {
/**
* @param authorizationServerUrl encoded authorization server URL
*/
public JiraOAuthGetAccessToken(String authorizationServerUrl) {
super(authorizationServerUrl);
this.usePost = true;
}
}
5、JiraRestClient支持OAuth令牌认证
第一步中我们通过用户名密码的方式构建客户端JiraRestClient,JiraRestClient本质上是对http请求的封装,便于我们方便操作,既然是http请求,那么通过用户名密码方式认证应该也是添加了相应的请求头(header)。首先看一下构造JiraRestClient的方法createWithBasicHttpAuthentication:
public JiraRestClient createWithBasicHttpAuthentication(URI serverUri, String username, String password) {
return this.create(serverUri, (AuthenticationHandler)(new BasicHttpAuthenticationHandler(username, password)));
}
这里创建了一个BasicHttpAuthenticationHandler实例,进入这个实例主要做了一件事,就是实现AuthenticationHandler接口的configure方法,这个configure方法主要是在http请求设置一个key为Authorization的请求头,并将用户名密码编码后作为value。通过这一个操作,JiraRestClient调用jira的所有接口都会添加这一请求头,从而进行身份验证。
public class BasicHttpAuthenticationHandler implements AuthenticationHandler {
...
public void configure(Builder builder) {
builder.setHeader("Authorization", "Basic " + this.encodeCredentials());
}
private String encodeCredentials() {
byte[] credentials = (this.username + ':' + this.password).getBytes();
return new String(Base64.encodeBase64(credentials));
}
}
那么如果使用OAuth进行认证呢?上面提高对jira的api调用是通过http请求发起的,那么OAuth认证应该也不例外,需要添加相关的OAuth认证的请求头。
也就是说我们只需实现AuthenticationHandler接口,并在configure方法中添加OAuth认证的请求头即可。
构建一个OauthAuthenticationHandler类实现AuthenticationHandler接口,configure方法中添加相关的OAuth请求头,代码如下:
public class OauthAuthenticationHandler implements AuthenticationHandler {
private OAuthParameters parameters;
public OauthAuthenticationHandler(OAuthParameters parameters){
this.parameters = parameters;
}
@Override
public void configure(Builder builder) {
//获取需要构建的request
Request request = builder.build();
String uri = request.getUri().toString();
parameters.computeNonce();
parameters.computeTimestamp();
try {
parameters.computeSignature(request.getMethod().toString(), new GenericUrl(uri));
} catch (GeneralSecurityException var4) {
log.error("jira request computeSignature error",var4);
}
//生成OAuth认证需要的请求头
String authHeader = parameters.getAuthorizationHeader();
//设置http请求头
builder.setHeader("Authorization",authHeader);
}
}
这里用到了guava oauth包中OAuthParameters,这个类用于构建OAuth请求的参数。
OAuthParameters的构建就用到了上面步骤中获取到的access token,构造OAuthParameters方法如下:
private OAuthParameters generate(String jiraBaseUrl,String acessToken, String secret, String consumerKey, String privateKey)throws Exception{
String accessTokenUrl = jiraBaseUrl + "/plugins/servlet/oauth/access-token";
JiraOAuthGetAccessToken accessToken = new JiraOAuthGetAccessToken(accessTokenUrl);
accessToken.consumerKey = consumerKey;
accessToken.signer = getOAuthRsaSigner(privateKey);
accessToken.transport = new ApacheHttpTransport();
accessToken.verifier = secret;
accessToken.temporaryToken = acessToken;
accessToken.verifier = secret;
OAuthParameters result= accessToken.createParameters();
return result;
}
有了OAuthParameters和OauthAuthenticationHandler之后,我们就可以构建支持OAuth认证的JiraRestClient了。
private static JiraRestClient getClientWithOauth() throws Exception{
AsynchronousJiraRestClientFactory asynchronousJiraRestClientFactory = new AsynchronousJiraRestClientFactory();
OAuthParameters parameters = generateOAuthParameters("http://localhost:8080","accesstoken","secret","consumerKey","PrivateKey");
OauthAuthenticationHandler oauthAuthenticationHandler= new OauthAuthenticationHandler(parameters);
JiraRestClient jiraRestClient = asynchronousJiraRestClientFactory.create(
URI.create("http://localhost:8080"), oauthAuthenticationHandler);
return jiraRestClient;
}
ref:
1、oauth配置步骤OAuth