ایجاد کنترل کننده پاسخ به تماس مجوز

این سند نحوه پیاده‌سازی یک کنترل‌کننده بازخوانی مجوز OAuth 2.0 را با استفاده از سرورهای جاوا از طریق یک برنامه وب نمونه توضیح می‌دهد که وظایف کاربر را با استفاده از Google Tasks API نمایش می‌دهد. برنامه نمونه ابتدا مجوز دسترسی به Google Tasks کاربر را درخواست می کند و سپس وظایف کاربر را در لیست وظایف پیش فرض نمایش می دهد.

حضار

این سند برای افرادی که با معماری برنامه های وب جاوا و J2EE آشنا هستند طراحی شده است. مقداری آگاهی از جریان مجوز OAuth 2.0 توصیه می شود.

فهرست

برای داشتن چنین نمونه کاملاً کارآمد چندین مرحله لازم است، شما باید:

نگاشت servlet را در فایل web.xml اعلام کنید

ما از 2 سرولت در برنامه خود استفاده خواهیم کرد:

  • PrintTasksTitlesServlet (نگاشت به / ): نقطه ورود برنامه است که احراز هویت کاربر را مدیریت می کند و وظایف کاربر را نمایش می دهد.
  • OAuthCodeCallbackHandlerServlet (نگاشت به /oauth2callback ): پاسخ تماس OAuth 2.0 که پاسخ از نقطه پایانی مجوز OAuth را کنترل می کند

در زیر فایل web.xml است که این 2 سرولت را به URL های موجود در برنامه ما نگاشت می کند:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

 <servlet>
   <servlet-name>PrintTasksTitles</servlet-name>
   <servlet-class>com.google.oauthsample.PrintTasksTitlesServlet</servlet-class>
 </servlet>

 <servlet-mapping>
   <servlet-name>PrintTasksTitles</servlet-name>
   <url-pattern>/</url-pattern>
 </servlet-mapping>

 <servlet>
   <servlet-name>OAuthCodeCallbackHandlerServlet</servlet-name>
   <servlet-class>com.google.oauthsample.OAuthCodeCallbackHandlerServlet</servlet-class>
 </servlet>

 <servlet-mapping>
   <servlet-name>OAuthCodeCallbackHandlerServlet</servlet-name>
   <url-pattern>/oauth2callback</url-pattern>
 </servlet-mapping>

</web-app>
فایل /WEB-INF/web.xml

کاربران سیستم خود را احراز هویت کنید و برای دسترسی به وظایف آن مجوز درخواست کنید

کاربر از طریق URL ریشه '/' وارد برنامه می شود که به سرور PrintTaskListsTitlesServlet نگاشت شده است. در آن servlet وظایف زیر انجام می شود:

  • بررسی می کند که آیا کاربر در سیستم احراز هویت شده است یا خیر
  • اگر کاربر احراز هویت نشده باشد، به صفحه احراز هویت هدایت می شود
  • اگر کاربر احراز هویت شده باشد، بررسی می‌کنیم که آیا نشانه‌ی تازه‌سازی از قبل در ذخیره‌سازی داده‌هایمان وجود دارد - که توسط OAuthTokenDao زیر مدیریت می‌شود. اگر نشانه‌های تازه‌سازی برای کاربر وجود نداشته باشد، به این معنی است که کاربر هنوز مجوز برنامه را برای دسترسی به وظایف خود اعطا نکرده است. در این صورت کاربر به نقطه پایانی OAuth 2.0 Google's Authorization هدایت می شود.
در زیر روشی برای پیاده سازی این موضوع وجود دارد:

package com.google.oauthsample;

import ...

/**
 * Simple sample Servlet which will display the tasks in the default task list of the user.
 */
@SuppressWarnings("serial")
public class PrintTasksTitlesServlet extends HttpServlet {

  /**
   * The OAuth Token DAO implementation, used to persist the OAuth refresh token.
   * Consider injecting it instead of using a static initialization. Also we are
   * using a simple memory implementation as a mock. Change the implementation to
   * using your database system.
   */
  public static OAuthTokenDao oauthTokenDao = new OAuthTokenDaoMemoryImpl();

  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the current user
    // This is using App Engine's User Service but you should replace this to
    // your own user/login implementation
    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();

    // If the user is not logged-in it is redirected to the login service, then back to this page
    if (user == null) {
      resp.sendRedirect(userService.createLoginURL(getFullRequestUrl(req)));
      return;
    }

    // Checking if we already have tokens for this user in store
    AccessTokenResponse accessTokenResponse = oauthTokenDao.getKeys(user.getEmail());

    // If we don't have tokens for this user
    if (accessTokenResponse == null) {
      OAuthProperties oauthProperties = new OAuthProperties();
      // Redirect to the Google OAuth 2.0 authorization endpoint
      resp.sendRedirect(new GoogleAuthorizationRequestUrl(oauthProperties.getClientId(),
          OAuthCodeCallbackHandlerServlet.getOAuthCodeCallbackHandlerUrl(req), oauthProperties
              .getScopesAsString()).build());
      return;
    }
  }

  /**
   * Construct the request's URL without the parameter part.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getFullRequestUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = req.getServletPath();
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    String queryString = (req.getQueryString() == null) ? "" : "?" + req.getQueryString();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo + queryString;
  }
}
فایل PrintTasksTitlesServlet.java

توجه: پیاده سازی فوق از برخی کتابخانه های App Engine استفاده می کند که به عنوان یک موضوع ساده استفاده می شود. اگر در حال توسعه برای پلتفرم دیگری هستید، با خیال راحت رابط کاربری UserService را که احراز هویت کاربر را کنترل می کند، دوباره پیاده سازی کنید.

این برنامه از یک DAO برای تداوم و دسترسی به توکن های مجوز کاربر استفاده می کند. در زیر رابط - OAuthTokenDao - و اجرای ساختگی (در حافظه) - OAuthTokenDaoMemoryImpl - است که در این نمونه استفاده شده است:

package com.google.oauthsample;

import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;

/**
 * Allows easy storage and access of authorization tokens.
 */
public interface OAuthTokenDao {

  /**
   * Stores the given AccessTokenResponse using the {@code username}, the OAuth
   * {@code clientID} and the tokens scopes as keys.
   *
   * @param tokens The AccessTokenResponse to store
   * @param userName The userName associated wit the token
   */
  public void saveKeys(AccessTokenResponse tokens, String userName);

  /**
   * Returns the AccessTokenResponse stored for the given username, clientId and
   * scopes. Returns {@code null} if there is no AccessTokenResponse for this
   * user and scopes.
   *
   * @param userName The username of which to get the stored AccessTokenResponse
   * @return The AccessTokenResponse of the given username
   */
  public AccessTokenResponse getKeys(String userName);
}
فایل OAuthTokenDao.java
package com.google.oauthsample;

import com.google.api.client.auth.oauth2.draft10.AccessTokenResponse;
...

/**
 * Quick and Dirty memory implementation of {@link OAuthTokenDao} based on
 * HashMaps.
 */
public class OAuthTokenDaoMemoryImpl implements OAuthTokenDao {

  /** Object where all the Tokens will be stored */
  private static Map tokenPersistance = new HashMap();

  public void saveKeys(AccessTokenResponse tokens, String userName) {
    tokenPersistance.put(userName, tokens);
  }

  public AccessTokenResponse getKeys(String userName) {
    return tokenPersistance.get(userName);
  }
}
فایل OAuthTokenDaoMemoryImpl.java

همچنین اعتبارنامه OAuth 2.0 برای برنامه در یک فایل خواص ذخیره می شود. از طرف دیگر، می توانید آنها را به عنوان یک ثابت در جایی در یکی از کلاس های جاوا خود داشته باشید، اگرچه در اینجا کلاس OAuthProperties و فایل oauth.properties است که در نمونه استفاده می شود:

package com.google.oauthsample;

import ...

/**
 * Object representation of an OAuth properties file.
 */
public class OAuthProperties {

  public static final String DEFAULT_OAUTH_PROPERTIES_FILE_NAME = "oauth.properties";

  /** The OAuth 2.0 Client ID */
  private String clientId;

  /** The OAuth 2.0 Client Secret */
  private String clientSecret;

  /** The Google APIs scopes to access */
  private String scopes;

  /**
   * Instantiates a new OauthProperties object reading its values from the
   * {@code OAUTH_PROPERTIES_FILE_NAME} properties file.
   *
   * @throws IOException IF there is an issue reading the {@code propertiesFile}
   * @throws OauthPropertiesFormatException If the given {@code propertiesFile}
   *           is not of the right format (does not contains the keys {@code
   *           clientId}, {@code clientSecret} and {@code scopes})
   */
  public OAuthProperties() throws IOException {
    this(OAuthProperties.class.getResourceAsStream(DEFAULT_OAUTH_PROPERTIES_FILE_NAME));
  }

  /**
   * Instantiates a new OauthProperties object reading its values from the given
   * properties file.
   *
   * @param propertiesFile the InputStream to read an OAuth Properties file. The
   *          file should contain the keys {@code clientId}, {@code
   *          clientSecret} and {@code scopes}
   * @throws IOException IF there is an issue reading the {@code propertiesFile}
   * @throws OAuthPropertiesFormatException If the given {@code propertiesFile}
   *           is not of the right format (does not contains the keys {@code
   *           clientId}, {@code clientSecret} and {@code scopes})
   */
  public OAuthProperties(InputStream propertiesFile) throws IOException {
    Properties oauthProperties = new Properties();
    oauthProperties.load(propertiesFile);
    clientId = oauthProperties.getProperty("clientId");
    clientSecret = oauthProperties.getProperty("clientSecret");
    scopes = oauthProperties.getProperty("scopes");
    if ((clientId == null) || (clientSecret == null) || (scopes == null)) {
      throw new OAuthPropertiesFormatException();
    }
  }

  /**
   * @return the clientId
   */
  public String getClientId() {
    return clientId;
  }

  /**
   * @return the clientSecret
   */
  public String getClientSecret() {
    return clientSecret;
  }

  /**
   * @return the scopes
   */
  public String getScopesAsString() {
    return scopes;
  }

  /**
   * Thrown when the OAuth properties file was not at the right format, i.e not
   * having the right properties names.
   */
  @SuppressWarnings("serial")
  public class OAuthPropertiesFormatException extends RuntimeException {
  }
}
فایل OAuthProperties.java

در زیر فایل oauth.properties است که حاوی اطلاعات کاربری OAuth 2.0 برنامه شما است. شما باید مقادیر زیر را خودتان تغییر دهید.

# Client ID and secret. They can be found in the APIs console.
clientId=1234567890.apps.googleusercontent.com
clientSecret=aBcDeFgHiJkLmNoPqRsTuVwXyZ
# API scopes. Space separated.
scopes=https://www.googleapis.com/auth/tasks
فایل oauth.properties

OAuth 2.0 Client ID و Client راز برنامه شما را شناسایی می کند و به Tasks API اجازه می دهد فیلترها و قوانین سهمیه ای را که برای برنامه شما تعریف شده است اعمال کند. شناسه مشتری و راز را می توان در کنسول APIs Google پیدا کرد. هنگامی که روی کنسول قرار می گیرید باید:

  • ایجاد یا انتخاب یک پروژه
  • Tasks API را با تغییر وضعیت Tasks API روی ON در لیست خدمات فعال کنید.
  • اگر شناسه مشتری OAuth 2.0 هنوز ایجاد نشده باشد، تحت API Access ایجاد کنید.
  • اطمینان حاصل کنید که نشانی وب کنترل‌کننده پاسخ تماس کد OAuth 2.0 پروژه در URIهای تغییر مسیر ثبت/فهرست شده است. به عنوان مثال، در این پروژه نمونه، اگر برنامه وب شما از دامنه https://www.example.com ارائه می شود، باید https://www.example.com/oauth2callback را ثبت کنید.

تغییر مسیر URI در کنسول APIs
تغییر مسیر URI در کنسول APIs

به کد مجوز از نقطه پایانی مجوز Google گوش دهید

در مواردی که کاربر هنوز به برنامه اجازه دسترسی به وظایف خود را نداده است و بنابراین به نقطه پایانی مجوز OAuth 2.0 Google هدایت شده است، یک گفتگوی مجوز از Google به کاربر نمایش داده می شود که از کاربر می خواهد به برنامه شما اجازه دسترسی به وظایف خود را بدهد:

گفتگوی مجوز Google
گفتگوی مجوز Google

پس از اعطای یا رد دسترسی، کاربر به کنترل‌کننده پاسخ تماس کد OAuth 2.0 هدایت می‌شود که هنگام ساخت URL مجوز Google به‌عنوان تغییر مسیر/بازخوانی مشخص شده است:

new GoogleAuthorizationRequestUrl(oauthProperties.getClientId(),
      OAuthCodeCallbackHandlerServlet.getOAuthCodeCallbackHandlerUrl(req), oauthProperties
          .getScopesAsString()).build()

کنترل‌کننده پاسخ تماس کد OAuth 2.0 - OAuthCodeCallbackHandlerServlet - تغییر مسیر را از نقطه پایانی Google OAuth 2.0 مدیریت می‌کند. 2 مورد برای رسیدگی وجود دارد:

  • کاربر اجازه دسترسی داده است: درخواست دریافت کد OAuth 2.0 را از پارامترهای URL تجزیه می کند.
  • کاربر دسترسی را رد کرده است: پیامی را به کاربر نشان می دهد

package com.google.oauthsample;

import ...

/**
 * Servlet handling the OAuth callback from the authentication service. We are
 * retrieving the OAuth code, then exchanging it for a refresh and an access
 * token and saving it.
 */
@SuppressWarnings("serial")
public class OAuthCodeCallbackHandlerServlet extends HttpServlet {

  /** The name of the Oauth code URL parameter */
  public static final String CODE_URL_PARAM_NAME = "code";

  /** The name of the OAuth error URL parameter */
  public static final String ERROR_URL_PARAM_NAME = "error";

  /** The URL suffix of the servlet */
  public static final String URL_MAPPING = "/oauth2callback";

  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the "error" URL parameter
    String[] error = req.getParameterValues(ERROR_URL_PARAM_NAME);

    // Checking if there was an error such as the user denied access
    if (error != null && error.length > 0) {
      resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "There was an error: \""+error[0]+"\".");
      return;
    }
    // Getting the "code" URL parameter
    String[] code = req.getParameterValues(CODE_URL_PARAM_NAME);

    // Checking conditions on the "code" URL parameter
    if (code == null || code.length == 0) {
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "The \"code\" URL parameter is missing");
      return;
    }
  }

  /**
   * Construct the OAuth code callback handler URL.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getOAuthCodeCallbackHandlerUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = URL_MAPPING;
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo;
  }
}
فایل OAuthCodeCallbackHandlerServlet.java

کد مجوز را برای بازخوانی و رمز دسترسی مبادله کنید

سپس، OAuthCodeCallbackHandlerServlet کد Auth 2.0 را برای به‌روزرسانی و توکن‌های دسترسی مبادله می‌کند، آن را در دیتا استور نگه می‌دارد و کاربر را به URL PrintTaskListsTitlesServlet هدایت می‌کند:

کد اضافه شده به فایل زیر به صورت دستوری مشخص شده است، کد موجود به رنگ خاکستری است.

package com.google.oauthsample;

import ...

/**
 * Servlet handling the OAuth callback from the authentication service. We are
 * retrieving the OAuth code, then exchanging it for a refresh and an access
 * token and saving it.
 */
@SuppressWarnings("serial")
public class OAuthCodeCallbackHandlerServlet extends HttpServlet {

  /** The name of the Oauth code URL parameter */
  public static final String CODE_URL_PARAM_NAME = "code";

  /** The name of the OAuth error URL parameter */
  public static final String ERROR_URL_PARAM_NAME = "error";

  /** The URL suffix of the servlet */
  public static final String URL_MAPPING = "/oauth2callback";
/** نشانی اینترنتی جهت هدایت کاربر پس از رسیدگی به تماس. در نظر بگیرید * قبل از هدایت کاربران به URL مجوز Google * این را در یک کوکی ذخیره کنید اگر چندین URL ممکن برای هدایت افراد به آن دارید. */ رشته نهایی ثابت عمومی REDIRECT_URL = "/"; /** پیاده سازی OAuth Token DAO. به جای استفاده از * مقدار دهی اولیه استاتیک، آن را تزریق کنید. همچنین ما از یک پیاده سازی حافظه ساده * به عنوان ساختگی استفاده می کنیم. پیاده سازی را به استفاده از سیستم پایگاه داده خود تغییر دهید. */ عمومی static OAuthTokenDao oauthTokenDao = new OAuthTokenDaoMemoryImpl();
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the "error" URL parameter
    String[] error = req.getParameterValues(ERROR_URL_PARAM_NAME);

    // Checking if there was an error such as the user denied access
    if (error != null && error.length > 0) {
      resp.sendError(HttpServletResponse.SC_NOT_ACCEPTABLE, "There was an error: \""+error[0]+"\".");
      return;
    }

    // Getting the "code" URL parameter
    String[] code = req.getParameterValues(CODE_URL_PARAM_NAME);

    // Checking conditions on the "code" URL parameter
    if (code == null || code.length == 0) {
      resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "The \"code\" URL parameter is missing");
      return;
    }
// ساخت URL درخواست ورودی String requestUrl = getOAuthCodeCallbackHandlerUrl(req); // تبادل کد برای توکن های OAuth AccessTokenResponse accessTokenResponse = exchangeCodeForAccessAndRefreshTokens(code[0], requestUrl); // دریافت کاربر فعلی // این از سرویس کاربر App Engine استفاده می‌کند، اما شما باید آن را با // پیاده‌سازی کاربر/ورود به سیستم خود جایگزین کنید UserService userService = UserServiceFactory.getUserService(); ایمیل رشته = userService.getCurrentUser().getEmail(); // توکن ها را ذخیره کنید oauthTokenDao.saveKeys(accessTokenResponse, email); resp.sendRedirect(REDIRECT_URL); }
  /**
   * Construct the OAuth code callback handler URL.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getOAuthCodeCallbackHandlerUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = URL_MAPPING;
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo;
  }
/** * کد داده شده را با یک تبادل و یک توکن تازه سازی مبادله می کند. * * @param کد کد دریافت شده از سرویس مجوز * @param currentUrl نشانی اینترنتی پاسخ تماس * @param oauthProperties شی حاوی پیکربندی OAuth * @return شی حاوی هر دو نشانه دسترسی و بازخوانی * @throws IOException */ عمومی AccessTokenResponse exchangeCodeForAccessAndRefreshTokens (کد رشته، String currentUrl) IOException { HttpTransport httpTransport = new NetHttpTransport(); JacksonFactory jsonFactory = new JacksonFactory(); // بارگیری فایل پیکربندی oauth OAuthProperties oauthProperties = new OAuthProperties(); برگرداندن GoogleAuthorizationCodeGrant جدید (httpTransport، jsonFactory، oauthProperties .getClientId()، oauthProperties.getClientSecret()، کد، currentUrl).execute(); } }
فایل OAuthCodeCallbackHandlerServlet.java

توجه: پیاده سازی فوق از برخی کتابخانه های App Engine استفاده می کند که به عنوان یک موضوع ساده استفاده می شود. اگر در حال توسعه برای پلتفرم دیگری هستید، با خیال راحت رابط کاربری UserService را که احراز هویت کاربر را کنترل می کند، دوباره پیاده سازی کنید.

وظایف کاربر را بخوانید و نمایش دهید

کاربر به برنامه اجازه دسترسی به وظایف خود را داده است. این برنامه دارای یک نشانه به‌روزرسانی است که در ذخیره‌گاه داده ذخیره می‌شود که از طریق OAuthTokenDao قابل دسترسی است. سرور PrintTaskListsTitlesServlet اکنون می تواند از این نشانه ها برای دسترسی به وظایف کاربر و نمایش آنها استفاده کند:

کد اضافه شده به فایل زیر به صورت دستوری مشخص شده است، کد موجود به رنگ خاکستری است.

package com.google.oauthsample;

import ...

/**
 * Simple sample Servlet which will display the tasks in the default task list of the user.
 */
@SuppressWarnings("serial")
public class PrintTasksTitlesServlet extends HttpServlet {

  /**
   * The OAuth Token DAO implementation, used to persist the OAuth refresh token.
   * Consider injecting it instead of using a static initialization. Also we are
   * using a simple memory implementation as a mock. Change the implementation to
   * using your database system.
   */
  public static OAuthTokenDao oauthTokenDao = new OAuthTokenDaoMemoryImpl();

  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    // Getting the current user
    // This is using App Engine's User Service but you should replace this to
    // your own user/login implementation
    UserService userService = UserServiceFactory.getUserService();
    User user = userService.getCurrentUser();

    // If the user is not logged-in it is redirected to the login service, then back to this page
    if (user == null) {
      resp.sendRedirect(userService.createLoginURL(getFullRequestUrl(req)));
      return;
    }

    // Checking if we already have tokens for this user in store
    AccessTokenResponse accessTokenResponse = oauthTokenDao.getKeys(user.getEmail());

    // If we don't have tokens for this user
    if (accessTokenResponse == null) {
      OAuthProperties oauthProperties = new OAuthProperties();
      // Redirect to the Google OAuth 2.0 authorization endpoint
      resp.sendRedirect(new GoogleAuthorizationRequestUrl(oauthProperties.getClientId(),
          OAuthCodeCallbackHandlerServlet.getOAuthCodeCallbackHandlerUrl(req), oauthProperties
              .getScopesAsString()).build());
      return;
    }
// چاپ لیست وظایف کاربر عناوین در پاسخ resp.setContentType("text/plain"); resp.getWriter().append("عناوین لیست وظایف برای کاربر" + user.getEmail() + ":\n\n"); printTasksTitles(accessTokenResponse, resp.getWriter());
  }

  /**
   * Construct the request's URL without the parameter part.
   *
   * @param req the HttpRequest object
   * @return The constructed request's URL
   */
  public static String getFullRequestUrl(HttpServletRequest req) {
    String scheme = req.getScheme() + "://";
    String serverName = req.getServerName();
    String serverPort = (req.getServerPort() == 80) ? "" : ":" + req.getServerPort();
    String contextPath = req.getContextPath();
    String servletPath = req.getServletPath();
    String pathInfo = (req.getPathInfo() == null) ? "" : req.getPathInfo();
    String queryString = (req.getQueryString() == null) ? "" : "?" + req.getQueryString();
    return scheme + serverName + serverPort + contextPath + servletPath + pathInfo + queryString;
  }
/** * از Google Tasks API برای بازیابی لیستی از وظایف کاربران در لیست کارهای پیش فرض * استفاده می کند. * * @param accessTokenResponse شی OAuth 2.0 AccessTokenResponse * حاوی نشانه دسترسی و یک نشانه تازه سازی است. * @param خروجی نویس جریان خروجی که در آن عناوین لیست وظایف را تنظیم کند * @return لیستی از عناوین وظایف کاربران در لیست وظایف پیش فرض. * @throws IOException */ public void printTasksTitles (AccessTokenResponse accessTokenResponse، خروجی Writer) IOException را پرتاب می کند { // راه اندازی سرویس Tasks HttpTransport transport = new NetHttpTransport(); JsonFactory jsonFactory = new JacksonFactory(); OAuthProperties oauthProperties = new OAuthProperties(); GoogleAccessProtectedResource accessProtectedResource = GoogleAccessProtectedResource جدید( accessTokenResponse.accessToken، transport، jsonFactory، oauthProperties.getClientId()، oauthProperties.getClientSecret()، accessTokenResponse.refreshToken); سرویس وظایف = وظایف جدید (حمل و نقل، accessProtectedResource، jsonFactory)؛ // استفاده از سرویس API اولیه Tasks برای پرس و جو از لیست وظایف com.google.api.services.tasks.model.Tasks tasks = service.tasks.list("@default").execute(); for (Task task : tasks.items) { output.append(task.title + "\n"); } }
فایل PrintTasksTitlesServlet.java

کاربر با وظایف خود نمایش داده می شود:

وظایف کاربر
وظایف کاربر

نمونه برنامه

کد این نمونه برنامه را می توانید از اینجا دانلود کنید. به راحتی آن را بررسی کنید.