7

Google Drive işlevini kullanmak istediğim tomcat üzerinde çalışan bir Spring-MVC uygulaması üzerinde çalışıyorum. Yerel makinemde bir hizmet hesabıyla denedim ve sorun yaşamadım. Ancak kodu sunucuya yüklediğimde, tarayıcı URL'si açılmayacak. Sonra bir servis hesabı kullanmam gerektiğini düşündüm, normal bir web-uygulama hesabı kullanmalıyım. Şimdi bunu yaptığımda, bir redirect_uri_mismatch olsun.Spring: Google kimlik doğrulaması redirect_uri_mismatch ve URL tarayıcıda açılmıyor

Tek bir şey anlamadım, JSON'da akışta yönlendirme URL'sini ayarlıyorum, neden yeryüzü redirect_url'yi rasgele port numaraları ile alıyor. Tarayıcı URL'sinde port numarasını değiştirirsem, iyi çalışıyor. Ama hala sunucuda tarayıcı URL'si açılmıyor, tomcat günlüklerinde görebiliyorum, ama lanet şey URL'yi açmıyor. İşte

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 

benim client_secret.json geçerli:: İşte

Google uygulamasından benim yönlendirme URL olan

{"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"] 
}} 

Ve burada kod nerede olduğunu doğrulamak çalışıyorum:

@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; 
    } 

Bu, yönlendirme URL'sini ayarladığım için beni çok sinirlendiriyor ve neden göz ardı ediliyor? Yeryüzünde, uygulama sunucuda dağıtıldığında bir tarayıcı sekmesi açılmayacaktır.

Güncelleme Bahar sorunu da sabit Aşağıdaki kod tomcat veya başkalarıyla bir sunucuda Google Drive yetkilendirme için kullanılabilir.

@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); 
    } 
} 

Kontrolör yöntemi:

@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 sadece URL'sini tıklamanız için bir düğmeye sahiptir.

+0

yönlendirme uri üretim sunucusunu yerel değil www.whatever.com/callback isteği göndererek sunucunun yeridir. – DaImTo

+0

@DaImTo: Buna katılıyorum, ancak kimlik bilgilerinde bahsettiğim yönlendirme çağrılmıyor. Ve yapılan istek için yönlendirme URL'si ayarlamanın bir yolu yoktur, kod localhost: 8080'de belirtmek için JSON içinde belirttiğim localhost: randomPortNumber olayı ayarlıyor. –

+0

İstemci kitaplığı sizin için gönderdiğiniz adresten gönderildiğini algılar. Yönlendirme URI'sini kodunuza ayarlamamalısınız. Gönderdiğiniz yönlendirmeyi Google Geliştirici konsolunda ayarlamalısınız ve yapmanız gereken tek şey budur. ide'nizi kurmak için rastgele bir port numarası yaratmamak için – DaImTo

cevap

2

Özel olarak, bir kimlik doğrulama kodu almak için olan starts up a jetty instance on a free port kullandığınız için rasgele bağlantı noktaları alıyorsunuz.

Daha yüksek bir düzeyde, bir web server application geliştiriyor gibi görünüyorsunuz, ancak Google OAuth'u bir installed application kullanıyormuş gibi kullanmaya çalışıyorsunuz. Gerçekten bir web sunucusu uygulaması yapıyorsanız, geri bildirim URL'nizde sunucunuzun ana bilgisayar adını kullanıp, flow.newAuthorizationUrl()'u kullanarak kimlik doğrulamasının son kullanıcı için bir bağlantı sağladığını ve geri bildiriminizin flow.newTokenRequest(String) kullanarak belirtecini almasını sağlamalısınız. Ayrıca, console ürününüzde oluşturduğunuz İstemci Kimliği'nin Web uygulaması olduğundan veya get redirect_uri_mismatch errors kullanacağınızdan emin olun. Bunun nasıl yapılacağına dair tam bir çalışma örneği here bulunabilir.Bunun yerine kullanmanın

+0

Şimdi değişiklikleri yapacağım ve size geri döneceğim. Çok teşekkürler. –

+0

Arkadaşım, her şey işe yarayacak gibi görünüyor, sadece sınıf Bahar ile bağlantı kurmuyor. Bu yüzden bir NPE alıyorum. Ana mesajımı düzenliyorum, ne yapabileceğimi kontrol edebilir misiniz? –

+0

Gönderiyi yeni düzenledim. Sahip olduğum Google Yetkilendirme sınıfını kontrol edebilir misiniz? Son yöntemde, bir NPE alıyorum çünkü Bahar otomatik olarak uygun değil. –

2

: Eğer alışkanlık yönlendirme url değiştirmek mümkün olsa da statik port

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

ayarlamak için

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

Kullanım

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

, ancak ana bilgisayar yanı sıra portu ayarlayabilirsiniz. konak kullanacağım .setHost() yöntemini değiştirme için

olarak da varsayılan bir kurucu kullanabilirsiniz:

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