我正在開發一個運行在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。
重定向URI是服務器發送www.whatever.com/callback生產服務器不是本地主機請求的位置。 – DaImTo
@DaImTo:我同意這一點,但我沒有提到在憑據中提到的重定向URI。並且我沒有辦法找到爲請求設置重定向url,代碼將其設置爲localhost:randomPortNumber eventhough我已經在JSON中指定使用localhost:8080。 –
客戶端庫爲您檢測到它是從您發送的位置發送的。你不應該在代碼中設置重定向URI。你應該設置你從Google Developer控制檯發送的重定向URI,這就是你需要做的。設置你的IDE,以免它創建一個隨機的端口號 – DaImTo