Java 中使用 Apache OAuth 客户端 2.0 库生成授权码和用户令牌的问题

Issues with Generating Authorization code and User Token using Apache OAuth client 2.0 library in Java

我尝试使用 Java 中的 Apache OAuth 客户端 2.0 库来自动化用户级别令牌 Creation/Generation 过程(REST/Authorization 授权代码)。 下面是我从 https://cwiki.apache.org/confluence/display/OLTU/OAuth+2.0+Client+Quickstart

获得的正在使用的代码
`/*Previous Codes & starting the below with Try/Catch*/
OAuthClientRequest request = OAuthClientRequest
   .authorizationLocation("Authorization URL")
   .setClientId("ClientID")
   .setRedirectURI("Redirect URL")
   .buildQueryMessage();
request.getLocationUri();
OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(request);
String code = oar.getCode();
/*Other Codes and starting the below with Try/Catch*/
OAuthClientRequest request = OAuthClientRequest
                .tokenLocation("TokenEndPointURL")
                .setGrantType(GrantType.AUTHORIZATION_CODE)
                .setClientId("ClientID")
                .setClientSecret("ClientSecret")
                .setRedirectURI("REdirectURL")
                .setCode(code)//Authorization Code from above
                .buildQueryMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(request, GitHubTokenResponse.class);
String accessToken = oAuthResponse.getAccessToken();
String expiresIn = oAuthResponse.getExpiresIn();`

但是,我在以下行中收到(从 Eclipse 中的错误推断)编译错误,

oauthCodeAuthzResponse方法接受httpservlet对象,不支持OAuthAuthzReponse类型

OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(request);

任何人都可以告诉我是否有解决此问题的方法吗? 要么 如何将 oauthCodeAuthzResponse 请求转换为 httpservlet 请求? 要么 我做错了什么或遗漏了什么吗?

OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(request);
String code = oar.getCode();

我认为上面的代码应该写在重定向URI端点的实现中,而不是在客户端代码中。

正确理解Authorization Code Flow会有所帮助。 授权码从授权服务器的授权端点发出,并被传送到重定向URI指向的位置。也就是说,授权代码不会直接传递给客户端应用程序。

当授权服务器发出授权代码时,它会将如下所示的 HTTP 响应发送回客户端的 Web 浏览器。

HTTP/1.1 302 Found
Location: {Redirect URI}
  ?code={Authorization Code}  // - Always included
  &state={Arbitrary String}   // - Included if the authorization
                              //   request included 'state'.

302 Found 触发网络浏览器转到 Location header 指向的位置。因此,您必须实现接收授权代码的位置,并且实现必须以某种方式将授权代码传递给客户端应用程序。

另请注意,授权页面 (HTML) 显示在 (a) 授权请求(= 对授权端点的请求)和 (b) 令牌请求(= 对令牌的请求)之间端点)并且该页面需要 end-user 交互。详见“Diagrams And Movies Of All The OAuth 2.0 Flows”中的“1.授权码流程”

我终于能够使用 httpclient 生成令牌 - 请参阅下面的逻辑。

获取授权码:

public String getAuthCode(String authUrl, String userName, String password, String scope, String clientId, 
        String redirectUrl) throws ClientProtocolException, IOException, URISyntaxException
{
    DefaultHttpClient httpclient = new DefaultHttpClient();

    System.out.println("Adding Paramters to a Array List as NameValuePair");
    List<NameValuePair> params = new ArrayList<NameValuePair>();
    params.add(new BasicNameValuePair("scope", scope));
    params.add(new BasicNameValuePair("response_type", "code"));
    params.add(new BasicNameValuePair("client_id", clientId));
    params.add(new BasicNameValuePair("redirect_uri", redirectUrl));

    System.out.println("Parameters List:" + params);

    System.out.println("Building the URI with Authorization Endpoint by adding the Parameters create in Array List");
    URI uri = new URIBuilder(authUrl)
            .addParameters(params)
            .build();
    System.out.println("Built URI:" + uri);

    System.out.println("Creating HTTPGET with the Created URI");
    HttpGet get = new HttpGet(uri);
    System.out.println("HttpGet:" + get);

    System.out.println("Creating Client Context");
    HttpClientContext context = HttpClientContext.create();
    System.out.println("Created Client Context:" + context);


    System.out.println("Executing the GET Method with the created Client Context");
    HttpResponse response = httpclient.execute(get, context);
    System.out.println("HttpResponse:" + response);

    System.out.println("Getting the Final URI from the Submitted Get Method");
    URI finalUrl = get.getURI();
    System.out.println("Final URL:" + finalUrl);

    System.out.println("Creating a List of URI from the Redirection Locations using Client Context");
    List<URI> locations = context.getRedirectLocations();
    System.out.println("List of URI:" + locations);

    if (locations != null) {
        finalUrl = locations.get(locations.size() - 1);
    }
    System.out.println("Taking the last URL as Final:" + finalUrl);

    System.out.println("Creating Entity");
    EntityUtils.consume(response.getEntity());
    System.out.println("Consume the Entity:" + response.getEntity());

    String userid = "username=".concat(userName);
    System.out.println("UserID:" + userid);
    String userPassword = "Password=".concat(password);
    System.out.println("User Password:" + userPassword);
    String cred = userid+"&"+userPassword;
    System.out.println("User Credentials:" + cred);
    HttpPost postReq = new HttpPost(finalUrl);
    StringEntity entity = new StringEntity(cred);
    postReq.setEntity(entity);
    postReq.addHeader("Content-Type", "application/x-www-form-urlencoded"); 
    postReq.addHeader("User-Agent", "MSIE 8.0");


    HttpResponse responsePost = httpclient.execute(postReq,context);
    List<Header> location = Arrays.asList(responsePost.getHeaders("Location"));
    String locationUrl = location.get(0).getValue().toString();
    String[] locationArray = locationUrl.split("=");
    String authCode = locationArray[1].trim().toString();
    //System.out.println(authCode);

    EntityUtils.consume(responsePost.getEntity());
    System.out.println("Response Post Entity:"+responsePost);
    System.out.println("Authorization Code:" +authCode);
    return authCode;
}

获得代币:

public List<String> getJwtToken(String clientId,String clientSecret, String authUrl,String tokenUrl,
            String redirectUrl,String accessTokenScope, String LDAPuserName,String LDAPpassword) throws Exception
    {

        List<String> tokens = new ArrayList<String>();
        //Generate the User Level Token & JWT Token using the Get/Post Method
        DefaultHttpClient httpclient = new DefaultHttpClient();


        System.out.println("Calling the get Auth Code Method");
        String authCode = getAuthCode(authUrl, LDAPuserName, LDAPpassword, accessTokenScope, clientId, redirectUrl);
        System.out.println("Authorization Code:" + authCode);

        HttpPost tokenPost = new HttpPost(tokenUrl);
        System.out.println("Token HttpPost:" + tokenPost);

        System.out.println("Adding the Parameters in an ArrayList as NameValuePair");
        List<NameValuePair> tokenParams = new ArrayList<NameValuePair>();
        tokenParams.add(new BasicNameValuePair("client_id", clientId));
        tokenParams.add(new BasicNameValuePair("client_secret", clientSecret));
        tokenParams.add(new BasicNameValuePair("code", authCode));
        tokenParams.add(new BasicNameValuePair("grant_type", "authorization_code"));
        System.out.println("Token Call Parameter:" + tokenParams);

        System.out.println("Setting the Parameters as URL Encoded Entity");
        tokenPost.setEntity(new UrlEncodedFormEntity(tokenParams));
        System.out.println("URL Encoded Entity" + tokenPost);

        System.out.println("Executing the Token Post Method");
        HttpResponse responseJWT = httpclient.execute(tokenPost);
        System.out.println("Setting the Parameters as URL Encoded Entity" + responseJWT);

        System.out.println("Parsing the ResponseJWT using JsonParser & JsonObjet");
        JsonParser parser = new JsonParser();   
        System.out.println("Json Parser:" + parser);
        JsonObject data = (JsonObject) parser.parse(new InputStreamReader(responseJWT.getEntity().getContent()));
        System.out.println("Json Object" + data);

        String token = data.get("access_token").toString();
        System.out.println("Access Token:" + token);

        String jwt="";
        try
        {
            jwt = data.get("jwt_token").toString();
            System.out.println("JWT Token:" + jwt);
        }
        catch(Exception ejwt)
        {
            System.out.println("Exception occured converting Jwt Token to String");
            ejwt.printStackTrace();
        }

        String refresh = data.get("refresh_token").toString();
        System.out.println("Refresh Token:" + refresh);

        String accessToken = token.substring(1, token.length()-1);
        tokens.add(0, accessToken);
        System.out.println("Real Access Token:" + accessToken);

        String jwtToken ="";
        try
        {
        jwtToken = jwt.substring(1, jwt.length()-1);
        tokens.add(1, jwtToken);
        System.out.println("Real JWT Token:" + jwtToken);
        }

        catch(Exception ejwt)
        {
            System.out.println("Exception occured adding Jwt Token to String List");
            ejwt.printStackTrace();
        }

        String refreshToken = refresh.substring(1, refresh.length()-1);
        System.out.println("Real Refresh Token:" + refreshToken);

        return tokens;

    }

我用过这种验证码方式。我在制作授权码时遇到了这个错误

> location->[] 
[ERROR] 2018-10-12 14:16:59.414 [http-nio-8080-exec-3]
> [dispatcherServlet] - Servlet.service() for servlet
> [dispatcherServlet] in context with path [] threw exception [Request
> processing failed; nested exception is
> java.lang.ArrayIndexOutOfBoundsException: 0] with root cause
> java.lang.ArrayIndexOutOfBoundsException: 0