安徽泗县建设银行网站,wordpress如何登录界面,泰安贴吧百度贴吧,上海网站建设 s在本教程的第一部分中#xff0c; 我描述了如何使用OAuth进行Google API服务的访问/身份验证。 不幸的是#xff0c;正如我稍后发现的那样#xff0c;我使用的方法是OAuth 1.0#xff0c;显然现在Google正式弃用了OAuth 1.0#xff0c;改用OAuth 2.0版本。 显然#xff0… 在本教程的第一部分中 我描述了如何使用OAuth进行Google API服务的访问/身份验证。 不幸的是正如我稍后发现的那样我使用的方法是OAuth 1.0显然现在Google正式弃用了OAuth 1.0改用OAuth 2.0版本。 显然发现这一点让我有些沮丧并承诺我将创建一个新博客条目其中包含有关如何使用2.0的说明。 好消息是有了2.0支持Google添加了一些附加的帮助程序类这些类使事情变得更加容易特别是如果您使用的是Google App Engine这正是我在本教程中使用的。 Google Developers网站现在对如何设置OAuth 2.0进行了很好的描述 。 但是事实证明配置一个真实的示例如何完成它是一个挑战因此我想记录下我学到的东西。 教程场景在上一个教程中我创建的项目说明了如何访问用户的Google Docs文件列表。 在本教程中我做了一些改动而是使用YouTube的API来显示用户喜欢的视频的列表。 访问用户的收藏夹确实需要使用OAuth进行身份验证因此这是一个很好的测试。 入门 可以在此处找到本教程的Eclipse项目。 您必须做的第一件事是遵循Google官方文档中概述的有关使用OAuth 2.0的步骤。 由于我正在创建一个Web应用程序因此您将需要遵循这些文档中名为“ Web服务器应用程序”的部分。 此外我之前讨论的用于设置Google App Engine的步骤仍然很重要因此我将直接跳入代码并跳过这些设置步骤。 注意可以在这里找到Eclipse项目-我再次选择不使用Maven以使那些没有安装Maven或在Maven方面有丰富知识的人保持简单。 应用程序流程非常简单假设是首次使用用户 用户访问Web应用程序时假设您正在使用GAE开发人员模拟器在http// localhost8888在本地运行该Web应用程序则他们必须首先使用其gmail或Google域帐户登录到Google。 登录后用户将被重定向到一个简单的JSP页面该页面具有指向其YouTube最喜欢的视频的链接。 当点击链接时servlet将启动OAuth流程以获取对其YouTube帐户的访问权限。 此过程的第一部分将重定向到Google Page该页面会提示他们是否要授予应用程序访问权限。 假设用户回答肯定将显示10个带有链接的收藏夹列表。 如果他们单击链接将加载视频。 这是前3页流程的描述 这是最后两页假设用户单击了给定的链接 尽管此示例特定于YouTube但相同的通用原则也适用于访问任何基于Google的云服务例如Google Google DriveDocs等。它们创建此类集成的关键推动因素显然是OAuth因此让我们来看一下该过程有效。 OAuth 2.0处理流程 对于刚开始学习这项技术的新开发人员而言使用OAuth可能会有些不知所措。 其背后的主要前提是允许用户有选择地确定他们希望外部应用程序可以访问哪些“私有”资源例如我们正在为本教程开发的资源。 通过使用OAuth用户可以避免与第三方共享其登录凭据而可以简单地向该第三方授予访问其某些信息的权限。 为了实现此功能需要将用户导航到其私人数据所在的源在本例中为YouTube。 然后他们可以允许或拒绝访问请求。 如果他们允许则私有数据YouTube的源将一次性授权代码返回给第三方应用程序。 由于每次需要访问权限时用户都必须授予访问权限是一件很麻烦的事情因此可以玩一个额外的通话它将“以旧换新”他们的单次使用授权更长的时间。 我们为本教程开发的Web应用程序的总体流程如下所示。 OAuth流程 进行的第一步是确定用户是否已经使用其gmail或Google Domain帐户登录到Google。 尽管不直接与OAuth流程绑定但使用户能够使用其Google帐户登录非常方便而不是要求用户登录您的网站。 这是对Google的第一个标注。 然后一旦登录应用程序将确定用户是否具有授予OAuth权限的本地帐户设置。 如果他们是第一次登录则不会。 在这种情况下将启动OAuth流程。 该过程的第一步是向OAuth提供程序在本例中为Google YouTube指定请求访问的“范围”。 由于Google提供了很多服务因此它们具有很多范围。 您可以使用其OAuth 2.0沙箱轻松确定。 当您启动OAuth流程时会向他们提供您想要访问的范围以及Google为您提供的OAuth客户端凭据这些步骤实际上是支持OAuth的任何提供程序所通用的。 为了我们的目的我们正在寻求访问该用户的YouTube帐户的权限因此Google提供的范围是https//gdata.youtube.com/。 如果最终用户授予对由范围标识的资源的访问权限则Google会将授权码发回给应用程序。 这是在servlet中捕获的。 由于返回的代码只是“一次性”代码因此将其交换为运行时间更长的访问令牌和相关的刷新令牌。 上面的步骤由标题为“请求访问和刷新令牌”的活动/框表示。 一旦配备了访问令牌应用程序便可以通过将API调用与令牌一起放置来访问用户的私有数据。 如果一切顺利API将返回结果。 这不是一个可怕的复杂过程它只涉及几个步骤。 让我们看一些具体的实现细节首先从servlet过滤器开始该过滤器确定用户是否已经登录Google和/或已授予OAuth访问权限。 授权过滤器 让我们看一下AuthorizationFilter的前几行要了解如何将其配置为过滤器请参阅web.xml文件。 public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException {HttpServletRequest request (HttpServletRequest) req;HttpServletResponse response (HttpServletResponse) res;HttpSession session request.getSession();if not present, add credential store to servlet contextif (session.getServletContext().getAttribute(Constant.GOOG_CREDENTIAL_STORE) null) {LOGGER.fine(Adding credential store to context credentialStore);session.getServletContext().setAttribute(Constant.GOOG_CREDENTIAL_STORE, credentialStore);}if google user isnt in session, add itif (session.getAttribute(Constant.AUTH_USER_ID) null) {LOGGER.fine(Add user to session);UserService userService UserServiceFactory.getUserService();User user userService.getCurrentUser();session.setAttribute(Constant.AUTH_USER_ID, user.getUserId());session.setAttribute(Constant.AUTH_USER_NICKNAME, user.getNickname());if not running on app engine prod, hard-code my email address for testingif (SystemProperty.environment.value() SystemProperty.Environment.Value.Production) {session.setAttribute(Constant.AUTH_USER_EMAIL, user.getEmail());} else {session.setAttribute(Constant.AUTH_USER_EMAIL, jeffdaviscogmail.com);}} 前几行简单地将通用servlet请求和响应转换为它们对应的Http等效项-这是必需的因为我们要访问HTTP会话。 下一步是确定Servlet上下文中是否存在CredentialStore。 正如我们将看到的它用于存储用户的凭据因此在后续的servlet中随时可以使用它很方便。 当我们使用以下命令检查用户是否已经在会话中时事情就开始了 if (session.getAttribute(Constant.AUTH_USER_ID) null) { 如果没有我们将使用Google的UserService类获取其Google登录凭据。 这是GAE用户可用来获取用户的Google用户ID电子邮件和昵称的帮助程序类。 从UserService获得此信息后我们将在会话中存储一些用户的详细信息。 目前我们还没有对OAuth做任何事情但是在接下来的代码行系列中会有所改变 尝试{ Utils.getActiveCredentialrequestcredentialStore; } catchNoRefreshTokenException e1{ //如果输入了该catch块则需要执行oauth流程 LOGGER.info未找到用户–授权URL为 e1.getAuthorizationUrl; response.sendRedirecte1.getAuthorizationUrl; } 大多数OAuth处理都使用一个称为Utils的帮助程序类。 在这种情况下我们将调用静态方法getActiveCredential。 稍后我们将看到如果以前没有为用户捕获OAuth凭据则此方法将返回NoRefreshTokenException。 作为自定义例外它将返回URL值该URL值用于将用户重定向到Google以寻求OAuth批准。 让我们更详细地了解getActiveCredential方法因为这是管理许多OAuth处理的地方。 public static Credential getActiveCredential(HttpServletRequest request, CredentialStore credentialStore) throws NoRefreshTokenException {String userId (String) request.getSession().getAttribute(Constant.AUTH_USER_ID);Credential credential null;try {if (userId ! null) {credential getStoredCredential(userId, credentialStore);}if ((credential null || credential.getRefreshToken() null) request.getParameter(code) ! null) {credential exchangeCode(request.getParameter(code));LOGGER.fine(Credential access token is: credential.getAccessToken());if (credential ! null) {if (credential.getRefreshToken() ! null) {credentialStore.store(userId, credential);}}}if (credential null || credential.getRefreshToken() null) {String email (String) request.getSession().getAttribute(Constant.AUTH_USER_EMAIL);String authorizationUrl getAuthorizationUrl(email, request);throw new NoRefreshTokenException(authorizationUrl);}} catch (CodeExchangeException e) {e.printStackTrace();} return credential;} 我们要做的第一件事是从会话中获取Google userId如果没有填充则无法做到这一点。 接下来我们尝试使用Utils静态方法getStoredCredential从CredentialStore获取用户的OAuth凭据以相同名称存储在Google类中。 如果找不到该用户的凭据则调用名为getAuthorizationUrl的Utils方法。 如下所示此方法用于构造浏览器重定向到的URL该URL用于提示用户授权访问其私有数据该URL由Google提供因为它将询问用户批准。 private static String getAuthorizationUrl(String emailAddress, HttpServletRequest request) {GoogleAuthorizationCodeRequestUrl urlBuilder null;try {urlBuilder new GoogleAuthorizationCodeRequestUrl(getClientCredential().getWeb().getClientId(),Constant.OATH_CALLBACK,Constant.SCOPES).setAccessType(offline).setApprovalPrompt(force);} catch (IOException e) {TODO Auto-generated catch blocke.printStackTrace();}urlBuilder.set(state, request.getRequestURI());if (emailAddress ! null) {urlBuilder.set(user_id, emailAddress);}return urlBuilder.build();} 如您所见此方法正在使用称为GoogleAuthorizationCodeRequestUrl的类来自Google。 它使用您注册使用OAuth时由Google提供的OAuth客户端凭据来构造HTTP调用巧合的是这些凭据存储在一个名为client_secrets.json的文件中。其他参数包括OAuth请求的范围和URL如果获得用户的批准该用户将被重定向回该URL。该URL是您在注册Google的OAuth访问权限时指定的URL 现在如果用户已经授予OAuth访问权限则getActiveCredential方法将改为从CredentialStore获取凭据。 回到接收OAuth凭据结果的URL在本例中为http// localhost8888 / authSub您可能想知道Google如何发布到该内部专用地址 好吧实际上是用户的浏览器发回了结果因此在这种情况下本地主机就可以很好地解决问题。 让我们看一下用于处理此回调的名为OAuth2Callback的servlet有关如何完成authSub的servlet映射的信息请参见web.xml。 public class OAuth2Callback extends HttpServlet {private static final long serialVersionUID 1L;private final static Logger LOGGER Logger.getLogger(OAuth2Callback.class.getName());public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {StringBuffer fullUrlBuf request.getRequestURL();Credential credential null;if (request.getQueryString() ! null) {fullUrlBuf.append(?).append(request.getQueryString());}LOGGER.info(requestURL is: fullUrlBuf);AuthorizationCodeResponseUrl authResponse new AuthorizationCodeResponseUrl(fullUrlBuf.toString());check for user-denied errorif (authResponse.getError() ! null) {LOGGER.info(User-denied access);} else {LOGGER.info(User granted oauth access);String authCode authResponse.getCode();request.getSession().setAttribute(code, authCode);response.sendRedirect(authResponse.getState());}}} 该课程最重要的收获是 AuthorizationCodeResponseUrl authResponse 新的AuthorizationCodeResponseUrlfullUrlBuf.toString; Google提供了AuthorizationCodeResponseUrl类以方便分析OAuth请求的结果。 如果该类的getError方法不为null则意味着用户拒绝了该请求。 如果它为null表示用户已批准该请求则使用方法调用getCode来检索一次性授权码。 此代码值放置在用户的会话中并且在重定向到用户的目标URL通过过滤器后调用Utils.getActiveCredential时它将将该授权代码交换为长期访问权限并使用电话 凭证 exchangeCodeStringrequest.getSession。getAttributecode; 接下来显示Utils.exchangeCode方法 public static Credential exchangeCode(String authorizationCode)throws CodeExchangeException {try {GoogleTokenResponse response new GoogleAuthorizationCodeTokenRequest(new NetHttpTransport(), Constant.JSON_FACTORY, Utils.getClientCredential().getWeb().getClientId(), Utils.getClientCredential().getWeb().getClientSecret(),authorizationCode, Constant.OATH_CALLBACK).execute();return Utils.buildEmptyCredential().setFromTokenResponse(response);} catch (IOException e) {e.printStackTrace();throw new CodeExchangeException();}} 此方法还使用称为GoogleAuthorizationCodeTokenRequest的Google类该类用于调用Google以将一次性OAuth授权代码交换为较长时间的访问令牌。 现在我们已经最终获得了YouTube API所需的访问令牌我们准备向用户显示其视频收藏夹中的10个。 调用YouTube API服务 有了访问令牌我们现在可以继续向用户显示其收藏夹列表。 为此调用了一个名为“ FavoritesServlet”的servlet。 它将调用YouTube API通过Jackson将生成的JSON-C格式解析为一些本地Java类然后将结果发送到JSP页面进行处理。 这是servlet public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {LOGGER.fine(Running FavoritesServlet);Credential credential Utils.getStoredCredential((String) request.getSession().getAttribute(Constant.AUTH_USER_ID), (CredentialStore) request.getSession().getServletContext().getAttribute(Constant.GOOG_CREDENTIAL_STORE));VideoFeed feed null;if the request fails, its likely because access token is expired - well refreshtry {LOGGER.fine(Using access token: credential.getAccessToken());feed YouTube.fetchFavs(credential.getAccessToken());} catch (Exception e) {LOGGER.fine(Refreshing credentials);credential.refreshToken();credential Utils.refreshToken(request, credential);GoogleCredential googleCredential Utils.refreshCredentials(credential);LOGGER.fine(Using refreshed access token: credential.getAccessToken());retry feed YouTube.fetchFavs(credential.getAccessToken());} LOGGER.fine(Video feed results are: feed);request.setAttribute(Constant.VIDEO_FAVS, feed);RequestDispatcher dispatcher getServletContext().getRequestDispatcher(htmllistVids.jsp);dispatcher.forward(request, response); } 由于这篇文章主要是关于OAuth流程的因此我不会过多介绍API调用的放置方式但是最重要的代码行是feed YouTube.fetchFavscredential.getAccessToken; feed是VideoFeed的实例。 如您所见另一个名为YouTube的帮助程序类用于执行繁重的工作。 为了总结一下我将展示fetchFavs方法。 public static VideoFeed fetchFavs(String accessToken) throws IOException, HttpResponseException {HttpTransport transport new NetHttpTransport();final JsonFactory jsonFactory new JacksonFactory();HttpRequestFactory factory transport.createRequestFactory(new HttpRequestInitializer() {Overridepublic void initialize(HttpRequest request) {set the parserJsonCParser parser new JsonCParser(jsonFactory);request.addParser(parser);set up the Google headersGoogleHeaders headers new GoogleHeaders();headers.setApplicationName(YouTube Favorites1.0);headers.gdataVersion 2;request.setHeaders(headers);}});build the YouTube URLYouTubeUrl url new YouTubeUrl(Constant.GOOGLE_YOUTUBE_FEED);url.maxResults 10;url.access_token accessToken;build the HTTP GET requestHttpRequest request factory.buildGetRequest(url);HttpResponse response request.execute();execute the request and the parse video feedVideoFeed feed response.parseAs(VideoFeed.class);return feed;} 它使用称为HttpRequestFactory的Google类构造对YouTube的出站HTTP API调用。 由于我们使用的是GAE因此我们只能使用哪些类来发出此类请求。 注意代码行 url.access_token accessToken; 那就是我们使用通过OAuth流程获取的访问令牌的地方。 因此虽然需要花费大量代码才能使OAuth内容正常运行但是一旦到位您就可以准备调用各种Google API服务来进行滚动 参考我们的JCG合作伙伴 Jeff Davis在Jeffs SOA Ruminations博客上为Google Services进行了认证第2部分 。 翻译自: https://www.javacodegeeks.com/2012/06/google-services-authentication-in-app_20.html