7

我正在開發一個運行在tomcat上的Spring-MVC應用程序,其中我想使用Google驅動器功能。我在本地機器上嘗試了一個服務帳戶,我沒有問題。但是當我將代碼上傳到服務器上時,瀏覽器URL不會被打開。然後我想,我不應該使用服務帳戶,我應該使用普通的Web應用程序帳戶。現在當我這樣做時,我得到了一個redirect_uri_mismatch。春天:Google身份驗證redirect_uri_mismatch和網址無法在瀏覽器上打開

我不明白一件事,我在流中設置重定向URL,在JSON中,爲什麼地球上會得到帶有隨機端口號的redirect_url。如果我更改瀏覽器URL中的端口號,它可以正常工作。但仍然在服務器上它不會打開瀏覽器url,我可以在tomcat日誌中看到它,但該死的東西不會打開URL。

下面是谷歌應用我的重定向URL:

http://localhost/authorizeuser 
http://localhost:8080/ 
http://localhost:8080 
http://localhost 
http://localhost:8080/Callback 
https://testserver.net/Callback 
http://testserver.net/Callback 
http://127.0.0.1 

這裏是我的client_secret.json:

{"web": { 
    "client_id": "clientid", 
    "auth_uri": "https://accounts.google.com/o/oauth2/auth", 
    "token_uri": "https://accounts.google.com/o/oauth2/token", 
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 
    "client_email": "clientemailstuff", 
    "client_x509_cert_url": "certurlstuff", 
    "client_secret": "itsasecret", 
    "redirect_uris": ["http://localhost:8080/","http://localhost:8080"], 
    "javascript_origins": ["https://testserver.net", "http://testserver.net","http://localhost:8080"] 
}} 

這裏是代碼,我正在嘗試進行身份驗證:

@Override 
    public Credential authorize() throws IOException { 
     InputStream in = 
       DriveQuickstartImpl.class.getResourceAsStream("/client_secret.json"); 
     GoogleClientSecrets clientSecrets = 
       GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); 

     GoogleAuthorizationCodeFlow flow = 
       new GoogleAuthorizationCodeFlow.Builder(
         HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) 
         .setDataStoreFactory(DATA_STORE_FACTORY) 
         .setAccessType("offline") 
         .build(); 
     flow.newAuthorizationUrl().setState("xyz").setRedirectUri("http://localhost:8080/Callback"); 
     Credential credential = new AuthorizationCodeInstalledApp(
       flow, new LocalServerReceiver()).authorize("user"); 

     if(credential!=null && credential.getRefreshToken() != null){ 
      storeCredentials(credential); 
     } 
     return credential; 
    } 

這是主要讓我失望,因爲我設置重定向網址,它只是被忽略,爲什麼在應用程序部署在服務器上時,瀏覽器選項卡不會被打開。

更新 春天的問題也解決了,下面的代碼可以用於tomcat或其他服務器上的GoogleDrive授權。

@Service 
@Transactional 
public class GoogleAuthorization{ 


    @Autowired 
    private DriveQuickstart driveQuickstart; 

    private static final String APPLICATION_NAME ="APPNAME"; 

    private static final java.io.File DATA_STORE_DIR = new java.io.File(
      "/home/deploy/store"); 

    private static FileDataStoreFactory DATA_STORE_FACTORY; 

    private static final JsonFactory JSON_FACTORY = 
      JacksonFactory.getDefaultInstance(); 

    private static HttpTransport HTTP_TRANSPORT; 

    private static final List<String> SCOPES = 
      Arrays.asList(DriveScopes.DRIVE); 

    private static final String clientid = "clientid"; 
    private static final String clientsecret = "clientsecret"; 

    private static final String CALLBACK_URI = "http://localhost:8080/getgooglelogin"; 

    private String stateToken; 

    private final GoogleAuthorizationCodeFlow flow; 

    public GoogleAuthorization(){ 
     try { 
      HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); 
      DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR); 

     } catch (GeneralSecurityException | IOException e) { 
      e.printStackTrace(); 
     } 

     flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, 
       JSON_FACTORY, clientid, clientsecret, SCOPES).setAccessType("offline").setApprovalPrompt("force").build(); 
     generateStateToken(); 

    } 



    /** 
    * Builds a login URL based on client ID, secret, callback URI, and scope 
    */ 
    public String buildLoginUrl() { 

     final GoogleAuthorizationCodeRequestUrl url = flow.newAuthorizationUrl(); 

     return url.setRedirectUri(CALLBACK_URI).setState(stateToken).build(); 
    } 

    /** 
    * Generates a secure state token 
    */ 
    private void generateStateToken(){ 
     SecureRandom sr1 = new SecureRandom(); 
     stateToken = "google;"+sr1.nextInt(); 
    } 

    /**s 
    * Accessor for state token 
    */ 
    public String getStateToken(){ 
     return stateToken; 
    } 

    /** 
    * Expects an Authentication Code, and makes an authenticated request for the user's profile information 
    * * @param authCode authentication code provided by google 
    */ 
    public void saveCredentials(final String authCode) throws IOException { 

     GoogleTokenResponse response = flow.newTokenRequest(authCode).setRedirectUri(CALLBACK_URI).execute(); 
     Credential credential = flow.createAndStoreCredential(response, null); 
     System.out.println(" Credential access token is "+credential.getAccessToken()); 
     System.out.println("Credential refresh token is "+credential.getRefreshToken()); 
// The line below gives me a NPE. 
     this.driveQuickstart.storeCredentials(credential); 
    } 
} 

控制器的方法:

@RequestMapping(value = "/getgooglelogin") 
    public String getGoogleLogin(HttpServletRequest request, HttpServletResponse response, HttpSession session,Model model) { 
// Below guy should be autowired if you want to use Spring. 
     GoogleAuthorization helper = new GoogleAuthorization(); 

     if (request.getParameter("code") == null 
       || request.getParameter("state") == null) { 

      model.addAttribute("URL", helper.buildLoginUrl()); 
      session.setAttribute("state", helper.getStateToken()); 

     } else if (request.getParameter("code") != null && request.getParameter("state") != null && request.getParameter("state").equals(session.getAttribute("state"))) { 
      session.removeAttribute("state"); 

      try { 
       helper.saveCredentials(request.getParameter("code")); 
       return "redirect:/dashboard"; 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     return "newjsp"; 
    } 

newjsp只是有一個按鈕,點擊該URL。

+0

重定向URI是服務器發送www.whatever.com/callback生產服務器不是本地主機請求的位置。 – DaImTo

+0

@DaImTo:我同意這一點,但我沒有提到在憑據中提到的重定向URI。並且我沒有辦法找到爲請求設置重定向url,代碼將其設置爲localhost:randomPortNumber eventhough我已經在JSON中指定使用localhost:8080。 –

+0

客戶端庫爲您檢測到它是從您發送的位置發送的。你不應該在代碼中設置重定向URI。你應該設置你從Google Developer控制檯發送的重定向URI,這就是你需要做的。設置你的IDE,以免它創建一個隨機的端口號 – DaImTo

回答

2

具體來說,你會得到隨機端口,因爲你使用LocalServerReceiver,其中starts up a jetty instance on a free port爲了接收認證碼。

在更高級別上,您似乎正在開發web server application,但您試圖使用Google OAuth,就好像它是installed application。如果您的確在製作Web服務器應用程序,則應在回調URL中使用服務器的主機名而不是本地主機,並提供一個鏈接供最終用戶使用flow.newAuthorizationUrl()進行身份驗證,並使用flow.newTokenRequest(String)從您的回調中獲取令牌。另外請確保您在console中創建的客戶端ID是Web應用程序的類型,或者您將get redirect_uri_mismatch errors。如何做到這一點的完整實例可以找到here

+0

我會立即做出更改並回復您。非常感謝。 –

+0

我的朋友,一切似乎都奏效,只是班上沒有連接到Spring。這就是我獲得NPE的原因。我正在編輯我的主帖,請你看看我能做些什麼。 –

+0

我剛剛編輯我的帖子。你能檢查我的GoogleAuthorization類,在最後一個方法中,我得到一個NPE,因爲Spring沒有自動裝配 –

2

而不是使用:

Credential credential = new AuthorizationCodeInstalledApp(flow, 
        new LocalServerReceiver).authorize("user"); 

使用

LocalServerReceiver localReceiver = new LocalServerReceiver. 
             Builder().setPort(XXXX).build(); 

用於設置靜態端口號

Credential credential = new AuthorizationCodeInstalledApp(flow, 
             localReceiver).authorize("user"); 

雖然你不會是能夠改變重定向URL,但是你可以設置主機以及端口。 更改主機使用.setHost()方法

您也可以使用默認的構造函數爲:

Credential credential = new AuthorizationCodeInstalledApp(flow, 
      new LocalServerReceiver("Host", XXXX).authorize("user"); 
相關問題