图片 1

Java OAuth 2.0 客户端编程: 资源所有者密码凭据授权

Java OAuth 2.0 客商端编制程序(后生可畏):
能源全部者密码凭据授权

Java OAuth 2.0 客商端编制程序(二):
客商端凭据授权

Java OAuth 2.0
客户端编制程序(三):认证码授权

概述

OAuth
是三个盛放的授权规范,允许客商端代表三个财富全部者得到访谈受保险服务器财富的访问权。能源全部者能够是另三个客商端或最后客商。OAuth
还足以支持最后顾客将对其服务器财富的探访权限授权给第三方,而没有必要分享其证据,比如顾客名和密码。本体系文章固守奥迪Q5FC 6749 中所列出的 OAuth 2.0 授权框架。能够在 Internet Engineering Task
Force 的网址上找到 科雷傲FC 6749 中列出的全体 OAuth 2.0
授权框架(请参阅 参照他事他说加以考查资料)。

授权批准

授权批准是风姿浪漫种凭据,可代表能源全数者用来访问受保险财富的权能。客商端选拔此凭据获取访谈令牌。访谈令牌最后与央求一齐发送,以便访谈受保障财富。OAuth
2.0 定义了多样授权类型:

  1. 授权码
  2. 隐式
  3. 能源全数者密码凭据
  4. 顾客端凭据

本文是由四片段组成的多元中的第 1
片段,将引导你使用方面列出的每个授权类型在 Java™ 编制程序中得以达成 OAuth 2.0
顾客端。在第 1
有的中,作者会告诉我们怎么着落到实处能源全数者密码凭据授权。本文详细介绍各样授权,并分解示例客商端代码,此代码可用于兼容OAuth 2.0
的任何服务器接口,以扶植此授权。在本文的终极,您应该对顾客端完结存周详的摸底,并希图好下载示例客户端代码,本身开展测量检验。

财富全部者密码凭据授权

当财富全部者对顾客端有可观信赖时,财富全数者密码凭据授权类型是行之有效的。此授权类型相符于能够赢得财富全体者的客户名和密码的客商端。对于使用
HTTP 基本功的现存企业客商端,也许想迁移到 OAuth
的摘要式身份验证,该授权最有用。然后,通过使用现存证据来生成二个做客令牌,然后就足以兑现迁移。

比方,Salesforce.com 增多了 OAuth 2.0
作为对其现存底子布局的多个授权机制。对于现成的客商端转移为这种授权方案,能源全数者密码凭据授权将是最有益的,因为她俩只需接纳现存的帐户详细音信(譬喻客户名和密码)来获取访谈令牌。

图 1. 财富全数者密码凭据流

图片 1

在 图 1 中所示的流水线包罗以下步骤:

  1. 财富全数者提供二个可相信的 OAuth 2.0 顾客端,并提供其顾客名和密码。
  2. OAuth 2.0
    顾客端对授权服务器的令牌端点发出国访问谈令牌央求,此中囊括从能源全部者这里收到的凭证。在发出央浼时,OAuth
    2.0 客户端使用由授权服务器提供的凭据和授权服务器进行身份验证。
  3. 授权服务器对 OAuth 2.0
    客商端进行身份验证,并表明能源全体者凭据,假使该证据是行之有效的,那么授权服务器会公布三个访谈令牌。

访问令牌乞请

对应于第一个步骤的会见令牌央浼如 图 1 所示。

顾客端对令牌端点(授权服务器)发出央浼,采纳application/x-www-form-urlencoded 格式发送以下参数。

  • grant_type:必选项。必需将其值设置为 “password”
  • username:必选项。财富全部者的顾客名。
  • password:必选项。财富全部者密码。
  • scope:可选项。访谈须求的约束

举例客商端类型是地下的,或客商端获得了客商端凭据(只怕被分配了别的身份验证必要),那么顾客端必得向授权服务器进行身份验证。举例,顾客端选用传输层安全性发生下列
HTTP 央求。

项目清单 1. 向授权服务器举行身份验证
POST /token HTTP/1.1
Host: server.example.com
Authorization:Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=varun&password=ab32vr

做客令牌响应

对应于上述手续 C 的拜望令牌响应如 图
1 所示。假如访谈令牌诉求是有效的,而且获得了授权,那么授权服务器将回到访谈令牌和三个可选的底蕴代谢令牌。清单2 呈现了二个打响响应的亲自去做。

清单 2. 成功的拜谒令牌响应
    HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}

要是必要无效,或然是未经授权的,那么授权服务器将会接受代码重回三个应和的错误音信。

设置

演示 OAuth 2.0 顾客端被增大为可导入 Eclipse 情形中的 Java
项目。您需求将第三方信赖关系 JAMurano 文件下载到 Java 项目中的 lib 文件夹中。

借助于关系 JA昂Cora 文件

该项目利用以下 JAHaval 文件:

  • commons-codec-1.6.jar
  • commons-logging-1.1.1.jar
  • httpclient-4.2.5.jar
  • httpclient-cache-4.2.5.jar
  • httpcore-4.2.4.jar
  • httpmime-4.2.5.jar
  • json-simple-1.1.1.jar

在前六项中关系的 JA陆风X8 文件能够在 Http Components JA奇骏文件中找到。下载这几个文件和 json-simple-1.1.1.jar
文件的链接,请参见 更加多下载。确认保障已将下面这个可供下载的
JAGL450 文件复制到 Java 项目标 lib 文件夹。

先决条件

下载 Eclipse IDE for Java EEdevelopers,以便设置开采情状,并导入附加项目。相关的链接请参见 更加多下载。

OAuth 2.0 客户端

此间钻探的 OAuth 2.0
顾客端完毕了财富全部者密码凭据授权。本类别文章的接轨部分将叙述其他授权类型,并三番五次改善客商端代码。

输入参数

接纳在演示顾客端代码下载(请参阅 Download)中提供的
Oauth2Client.config 属性文件向顾客端提供所需的输入参数。

  • scope:这是三个可选参数。它代表做客诉求的界定。由服务器再次来到的会见令牌只可以够访谈scope 中涉及的服务。
  • grant_type:供给将以此参数设置为 "password",表示能源全体者密码凭据授权。
  • username:用于登入到能源服务器的客户名。
  • password:用于登陆到能源服务器的密码。
  • client_id:注册应用程序时由能源服务器提供的顾客端或使用者 ID。
  • client_secret:注册应用程序时由能源服务器提供的客商端或使用者的密码。
  • access_token:授权服务器响应有效的和经过授权的拜访令牌须要时重返的拜访令牌。作为该诉求的黄金时代局地,您的客户名和密码将用来交换访谈令牌。
  • refresh_token:这是二个可选参数,由授权服务器在响应访谈令牌乞请时再次来到。可是,大比超级多端点(举个例子Salesforce、IBMWebSphere® Application Server 和 IBM
    DataPower)对能源全体者密码凭据授权不回来刷新令牌。因而,笔者的客商端达成不策画思量刷新令牌。
  • authenticatation_server_url:这代表令牌端点。批准和另行生成访谈令牌的持有供给都一定要发送到这个UTucsonL。
  • resource_server_url:那代表必要沟通的财富服务器的
    UCRUISERL,通过将授权标头中的采访令牌传递给它来访谈受有限接济的能源。
清单 3. Oauth2Client 代码
 Properties config = OAuthUtils.getClientConfigProps   (OAuthConstants.CONFIG_FILE_PATH);
 String resourceServerUrl = config.getProperty(OAuthConstants.RESOURCE_SERVER_URL);      
 String username = config.getProperty(OAuthConstants.USERNAME);
 String password = config.getProperty(OAuthConstants.PASSWORD);
 String grantType = config.getProperty(OAuthConstants.GRANT_TYPE);
 String authenticationServerUrl = config
         .getProperty(OAuthConstants.AUTHENTICATION_SERVER_URL);

  if (!OAuthUtils.isValid(username)
    || !OAuthUtils.isValid(password)
    || !OAuthUtils.isValid(authenticationServerUrl)
    || !OAuthUtils.isValid(grantType)) {
  System.out
        .println("Please provide valid values for username, password,
                        authentication server url and grant type");
  System.exit(0);

   }

 if (!OAuthUtils.isValid(resourceServerUrl)) {
 // Resource server url is not valid.
 //Only retrieve the access token
 System.out.println("Retrieving Access Token");
 OAuth2Details oauthDetails = OAuthUtils.createOAuthDetails(config);
 String accessToken = OAuthUtils.getAccessToken(oauthDetails);
 System.out
 .println("Successfully retrieved Access token
  for Password Grant:" + accessToken);
 }
 else {
 // Response from the resource server must be in Json or
 //Urlencoded or xml
 System.out.println("Resource endpoint url:" + resourceServerUrl);
 System.out.println("Attempting to retrieve protected resource");
 OAuthUtils.getProtectedResource(config);
      }

在 清单 3 中的客商端代码读取 Oauth2Client.config
文件中所提供的输入参数。usernamepassword、 authentication server url 和 grant type 的有效值是免强性的。要是布署文件中所提供的能源服务器
U福特ExplorerL 是行得通的,那么顾客端会尝试搜索该 U中华VL
中提供的受有限支撑能源。不然,客户端只对授权服务器发出国访问问令牌乞请,并收复访谈令牌。以下一些表明了担负寻找受保证财富和会见令牌的代码。

拜望受保险能源

项目清单 4 中的代码演示了哪些利用访问令牌来访谈受敬爱的能源。

清单 4. 做客受保险资源
String resourceURL =
config.getProperty(OAuthConstants.RESOURCE_SERVER_URL);
OAuth2Details oauthDetails = createOAuthDetails(config);
HttpGet get = new HttpGet(resourceURL);
get.addHeader(OAuthConstants.AUTHORIZATION,
getAuthorizationHeaderForAccessToken(oauthDetails
.getAccessToken()));
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = null;
int code = -1;
  try {
    response = client.execute(get);
    code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
      // Access token is invalid or expired.
      // Regenerate the access token
      System.out.println("Access token is invalid
      or expired.Regenerating access token....");
      String accessToken = getAccessToken(oauthDetails);
      if (isValid(accessToken)) {
    // update the access token
      // System.out.println("New access token:" + accessToken);
      oauthDetails.setAccessToken(accessToken);
      get.removeHeaders(OAuthConstants.AUTHORIZATION);
      get.addHeader(OAuthConstants.AUTHORIZATION,
      getAuthorizationHeaderForAccessToken(oauthDetails
    .getAccessToken()));
      get.releaseConnection();
      response = client.execute(get);
      code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    throw new RuntimeException("Could not
  access protected resource.
  Server returned http code:"+ code);

     }

   } else {
    throw new RuntimeException("Could not
       regenerate access token");
    }

 }

   handleResponse(response);

注意

  • 此方法应用从结构文件检索到的值来填充 OauthDetails bean。
  • 看名就能够知道意思,这种办法将尝试从财富服务器检索受保证的财富,由此,您需求创制多个简练的 HttpGet 方法。
  • 为了向财富服务器举行身份验证,供给将拜访令牌作为 Authorization
    标头的生机勃勃有的发送。示例:Authorization:Bearer accessTokenValue
  • 创办三个 DefaultHttpClient 对能源服务器发出三个 get 请求。
  • 假如从财富服务器收到的响应代码是 403 或 401,则用于身份验证的拜谒令牌可能已过期或无效。
  • 下一步是再度创建访谈令牌(清单 5)。
  • 成功地重新生成访问令牌之后,更新 OauthDetails bean
    中的访谈令牌值。用新的拜谒令牌值替换 get 方法中存活的
    Authorization 标头。
  • 当今时有发生对受保护能源的另五个拜候恳求。
  • 假若访谈令牌有效,并且能源服务器的 U奔驰G级L
    也是对的的,那么你应该能够在调整桃园看出响应内容。

再也生成过期的拜望令牌

清单 5 中的代码将会管理已过期访问令牌的双重生成。

清单 5. 再度生成过期的拜谒令牌
 HttpPost post = new HttpPost(
 oauthDetails.getAuthenticationServerUrl());
 String clientId = oauthDetails.getClientId();
 String clientSecret = oauthDetails.getClientSecret();
 String scope = oauthDetails.getScope();

 List<BasicNameValuePair> parametersBody =
 new ArrayList<BasicNameValuePair>();
 parametersBody.add(new BasicNameValuePair(OAuthConstants.GRANT_TYPE,
 oauthDetails.getGrantType()));
 parametersBody.add(new BasicNameValuePair(OAuthConstants.USERNAME,
 oauthDetails.getUsername()));
 parametersBody.add(new BasicNameValuePair(OAuthConstants.PASSWORD,
 oauthDetails.getPassword()));

 if (isValid(clientId)) {
    parametersBody.add(new BasicNameValuePair
      (OAuthConstants.CLIENT_ID,clientId));
  }
 if (isValid(clientSecret)) {
    parametersBody.add(new BasicNameValuePair(
    OAuthConstants.CLIENT_SECRET, clientSecret));
  }
 if (isValid(scope)) {
    parametersBody.add(new BasicNameValuePair
      (OAuthConstants.SCOPE,scope));
  }

 DefaultHttpClient client = new DefaultHttpClient();
 HttpResponse response = null;
 String accessToken = null;
   try {
    post.setEntity(new UrlEncodedFormEntity(parametersBody,
       HTTP.UTF_8));

    response = client.execute(post);
    int code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    System.out.println("Authorization
       server expects Basic authentication");
    // Add Basic Authorization header
    post.addHeader(
    OAuthConstants.AUTHORIZATION,
    getBasicAuthorizationHeader(oauthDetails.getUsername(),
    oauthDetails.getPassword()));
    System.out.println("Retry with login credentials");
    post.releaseConnection();
    response = client.execute(post);
    code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    System.out.println("Retry with client credentials");
    post.removeHeaders(OAuthConstants.AUTHORIZATION);
    post.addHeader(
    OAuthConstants.AUTHORIZATION,
       getBasicAuthorizationHeader(
     oauthDetails.getClientId(),
    oauthDetails.getClientSecret()));
    post.releaseConnection();
    response = client.execute(post);
    code = response.getStatusLine().getStatusCode();
    if (code >= 400) {
    throw new RuntimeException(
    "Could not retrieve access token for user:"
    oauthDetails.getUsername());
       }
        }
      }
    Map<String, String> map = handleResponse(response);
    accessToken = map.get(OAuthConstants.ACCESS_TOKEN);
    } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
    }

    return accessToken;

注意

  • 这种情势生成二个 HttpPost 诉求,并获得身份验证服务器的 ULacrosseL。
  • Post 乞求以 UXC90L
    编码参数的款型发送 usernamepassword,以致可选的 scope,将它们作为有效载荷的风度翩翩局部。
  • 稍加授权服务器还有大概会必要你发送 client_id 和 client_secret 作为此恳请有效载荷的一片段。
  • 如果 client_idclient_secret 和 scope 的值不为空,那么它们也将作为有效载荷的后生可畏有的被发送。
  • 据守 OAuth 2.0
    授权框架,顾客端应该利用客商端凭据,或选拔在发生访谈令牌要求时由服务器所提供的任何任何凭据来设置
    Authorization
    标头。不过,那受制于授权服务器达成。顾客端代码发出开始诉求时不需求加上基本人份验证标头。若是服务器重回一个未经授权的响应,客商端随后试图透过登入和客商端凭据实行身份验证。
  • OAuth 2.0 规定,供给运用 JSON
    格式来发送访谈令牌响应。但为了灵活性,小编还增加了实用程序方法来管理来自服务器的
    XML 编码或 U福睿斯L 编码的响应。

测量试验客商端

在本节中,笔者将研商怎么着营造三个 OAuth 2.0 兼容的端点并用它来测量试验客商端。

在 Salesforce.com 注册

Salesforce.com
对于能源全部者密码凭据授权是贰个很好的用例。纵然客户有记名
Salesforce.com 的凭证,并期望团结的顾客端转移为 OAuth 2.0
身份验证,那么他索要做的便是在 Salesforce
注册本人的应用程序,以得到顾客端凭据。今后得以用这个客商端凭据以至他共处的报到凭据从授权服务器中得到访谈令牌。

  1. 假如您在此之前并未有在 Salesforce.com
    注册过,请立即登记。请参阅 参谋资料 。
  2. 单击 Login,然后单击 Sign up for free
  3. 姣好注册,得到你的证据。
  4. 除了那些之外顾客名和密码之外,您还将获取叁个安然照旧令牌。您提供的用来发生访谈令牌乞请的密码必得是你的密码和安全令牌的串联。(示例:password12312123)。
  5. 有关怎么样在 salesforce.com
    中创设应用程序,请参阅 仿照效法资料 中有效的稿子链接。

运营顾客端

近些日子,您曾经完毕了 Salesforce.com
中的注册,您能够测验顾客端并从服务器检索受保险的音讯。

  • 将本文中探讨的 Java 项目导入到 Eclipse
    专业区(请参阅 仿效资料)。
  • 下载信任关系 JA奥迪Q5 文件,并将其复制到项目标 lib
    文件夹中(请参阅 更加多下载 )。
  • 导航到 resources/com/ibm/oauth/Oauth2Client.config
    文件,并填写 usernamepassword(追加安全令牌)、client_idclient_secret 和 authorization server URL 的值。
  • 开采 Oauth2Client.java 并运营它。

做客令牌输出

你应该在调整台窗口看看上面包车型大巴出口。

Retrieving Access Token
encodedBytes dmVybi5vamhhQGdtYWlsL.......

********** Response Received **********
  instance_url = https://ap1.salesforce.com
  issued_at = 1380106995639
  signature = LtMjTrmoBbvVfZ6+qT5Un1UioHaV9KIOK7ayQTmJzCg=
  id = https://login.salesforce.com/id/00D90000000mQaYEAU/00590000001HCB7AAO
  access_token = 00D90000000mQaY!AQ8AQEn0rLDMvxrP9WgY3Blc.......
Successfully retrieved Access token for Password Grant:00D90000000mQaY!AQ8AQEn0rLDMvxrP9WgY3Bl......

从 Salesforce.com 检索客户新闻

当今,您曾经有了拜访令牌和 ID,能够向 Salesforce.com 发出诉求,通过利用
OAuth 2.0 进行身份验证来采访您的帐户消息。

  • 用拜候令牌更新 Oauth2Client.confg
    文件,并接纳作为响应的豆蔻梢头有的重临的 id 值来填充能源服务器 UTiggoL
    属性。
  • 双重运维 Oauth2Client.java。

输出

您应该在决定台窗口看六柱预测近于上面包车型地铁输出。

清单 6. 输出
Resource endpoint URL: https://login.salesforce.com/id/00D90000000mQaYEAU/00590000001HCB7AAO
Attempting to retrieve protected resource
********** Response Received **********
photos = {"thumbnail":"https:////c.ap1.content.force.com//profilephoto//005//T","picture":"https:///
/c.ap1.content.force.com//profilephoto//005//F"}
urls =
{"enterprise":"https:////ap1.salesforce.com//services//Soap//c//{version}//00D90000000mQaY","sobjects":
"https:////ap1.salesforce.com//services//data//v{version}//sobjects//","partner":"https:///
/ap1.salesforce.com//services//Soap//u//{version}//00D90000000mQaY","search":"https:///
/ap1.salesforce.com//services//data//v{version}//search//","query":"https:////ap1.salesforce.com/
/services//data//v{version}//query//","users":"https:////ap1.salesforce.com//services//data//v{version}/
/chatter//users","profile":"https:////ap1.salesforce.com//00590000001HCB7AAO","metadata":"https:///
/ap1.salesforce.com//services//Soap//m//{version}//00D90000000mQaY","rest":"https:////ap1.salesforce.com/
/services//data//v{version}//","groups":"https:////ap1.salesforce.com//services//data//v{version}/
/chatter//groups","feeds":"https:////ap1.salesforce.com//services//data//v{version}//chatter//feeds",
"recent":"https:////ap1.salesforce.com//services//data//v{version}//recent//","feed_items":"https://
//ap1.salesforce.com//services//data//v{version}//chatter//feed-items"}
  asserted_user = true
  active = true
  organization_id = 00D90000000mQaYEAU
  nick_name = vern.ojha1....
  display_name = varun ojha
  user_type = STANDARD
  user_id = ***********
  status = {"body":null,"created_date":null}
  last_name = ojha
  username = vern.ojha.....
  utcOffset = -28800000
  language = en_US
  locale = en_US
  first_name = varun
  last_modified_date = 2013-06-04T07:43:42.000+0000
  id = https://login.salesforce.com/id/00D90000000mQaYEAU/00590000001HCB7AAO
  email = vern.ojha@gmail.com

如你所见,您可以经过行使 OAuth 2.0
进行身份验证,成功赢得客户音讯。在安插文件中提供的拜候令牌过期后,顾客端将会自动重新生成访谈令牌,并使用它来搜求在财富服务器
UEscortL 中提供的受保险财富。

用 IBM 端点测量试验顾客端

客户端也曾经成功通过 OAuth 2.0 包容的 IBM 端点的测验,即 IBM WebSphere
Application Server 和 IBM
DataPower。请参阅 参谋资料 的链接,“使用
OAuth:在 WebSphere Application Server 中启用 OAuth
服务提供程序”,那是一个十一分好的财富,介绍了什么在 WebSphere Application
Server 上设置 OAuth 2.0。

在您的应用服务器上设置了 OAuth 2.0 后,客商端所需的输入与 Salesforce.com
演示中的相符。

结束语

本文是该种类文章的第生龙活虎部分,解说了能源全部者密码凭据授权的底子知识。本文演示了怎样在
Java 编制程序中编辑一个通用的 OAuth 2.0 客商端,以接二连三到 OAuth 2.0
宽容的八个端点,并从当中获得受保险的能源。示例顾客端被增大为二个 Java
项目,以使您能够神速导入项目到 Eclipse
工作区,并起首测验。在本体系文章的继续部分中,我将介绍在 OAuth 2.0
授权框架中列出的别的二种授权类型。在持续小说中,客商端代码将会拿到立异,以反映这么些授权类型及特点,举个例子公布到某个能源服务器和管理SSL。

下载

描述 名字 大小
示例客户端代码 OAuth20.zip 19KB

发表评论

电子邮件地址不会被公开。 必填项已用*标注