401 Ошибка Неизвестная авторизация при получении Google календарей - PullRequest
3 голосов
/ 30 мая 2011

Когда я выполняю CalendarService.setOAuthCredentials (oauthParameters, new OAuthHmacSha1Signer ()); Я получаю OAuthException 401 Ошибка Неизвестный заголовок авторизации.

Я использую GWT + GAE Я не знаю, почему я получаю эту ошибку, oauthParameters, кажется, в порядке.

  1. Я получаю логин пользователя на loginService.login
  2. Я проверяю, есть ли у меня аутентификация уже включена oauthService.checkOauthTokenSecret
  3. Если нет, я сделаю перенаправление в Google Апроваль страница для GCalendar разрешение
  4. Я получаю строку запроса вернулся Google и я получил доступ Токен и токен доступа установить его для объекта пользователя на потом использовать на oauthService.upgradeLogin.
  5. И пытается получить календари на oauthService.getPublicCalendars.

Я использую шаблон MVP с фреймворком mvp4g, извините, если немного сбивает с толку 0: -)

Есть идеи, почему я получаю ошибку 401? Я думаю, что-то про то, что я прохожу вверх и вниз по клиенту, серверу и внешним страницам ... и чего-то не хватает :-( но все параметры кажутся правильно заполненными.

Клиентская сторона

public void onStart(){
    GWT.log("onStart");
    loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {
        @Override
        public void onSuccess(LoginInfo result) {
            Common.loginInfo = result;
            if(Common.loginInfo.isLoggedIn()) { 
                oauthService.checkOauthTokenSecret(new AsyncCallback<String>() {
                    @Override
                    public void onSuccess(String result) {
                        if (result == null){
                            eventBus.OauthLogin();
                        }else{
                            oauthService.upgradeLogin(Window.Location.getQueryString(),Common.loginInfo, new AsyncCallback<LoginInfo>() {
                                @Override
                                public void onSuccess(LoginInfo result) {
                                    Common.loginInfo = result;
                                    getCitas();
                                }
                                @Override public void onFailure(Throwable caught) {
                                    Common.handleError(caught);                         
                                }
                            });
                        }
                    }
                    @Override public void onFailure(Throwable caught) {
                        Common.handleError(caught);                         
                    }
                });
            }else{
                eventBus.LoadLogin();
            }
        }
        @Override public void onFailure(Throwable caught) {
            Common.handleError(caught);
        }
    });
}

Серверная сторона

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletContext;

import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthException;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gdata.client.authn.oauth.OAuthParameters;
import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarFeed;
import com.google.gdata.util.ServiceException;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.rdt.citas.client.OAuthoritzationService;
import com.rdt.citas.client.shared.LoginInfo;

public class OAuthoritzationServiceImpl extends RemoteServiceServlet 
implements OAuthoritzationService {

/**
 * 
 */
private static final long serialVersionUID = 1L;

private static final Logger log = Logger.getLogger(OAuthoritzationServiceImpl.class.getName());

private static String KEY_PARAM = "oauth_consumer_key";
private static String SECRET_PARAM = "oauth_consumer_secret";
private static String SCOPE_PARAM = "scope_calendars";
private static String CALLBACK_PARAM = "oauth_callback";


public String checkOauthTokenSecret(){

    ServletContext context = this.getServletContext();
    getOauthParams(context);

    return (String) this.getThreadLocalRequest().getSession().getAttribute("oauthTokenSecret");;
}

public String getApprovalOAuthPageURL() throws IOException{

    ServletContext context = this.getServletContext();
    getOauthParams(context);

    GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();

    oauthParameters.setOAuthConsumerKey(getFromSession(KEY_PARAM));
    oauthParameters.setOAuthConsumerSecret(getFromSession(SECRET_PARAM));
    oauthParameters.setScope(getFromSession(SCOPE_PARAM));
    oauthParameters.setOAuthCallback(getFromSession(CALLBACK_PARAM));
    GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer());

    try {                       
        oauthHelper.getUnauthorizedRequestToken(oauthParameters);

        String approvalPageUrl = oauthHelper.createUserAuthorizationUrl(oauthParameters);
        String oauthTokenSecret = oauthParameters.getOAuthTokenSecret();

        this.getThreadLocalRequest().getSession().setAttribute("oauthTokenSecret", oauthTokenSecret);

        return approvalPageUrl;

    } catch (OAuthException e) {
        log.log(Level.WARNING,e.toString());
        return "";
    } finally{
    }

}

public LoginInfo upgradeLogin(String queryString, LoginInfo login){
    // receiving '?key1=value1&key2=value2
    queryString = queryString.substring(1, queryString.length());
    String k = getFromSession(KEY_PARAM);
    String s = getFromSession(SECRET_PARAM);

    GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
    oauthParameters.setOAuthConsumerKey(k);
    oauthParameters.setOAuthConsumerSecret(s);

    String oauthTS = (String) this.getThreadLocalRequest().getSession().getAttribute("oauthTokenSecret");//oauthParameters.getOAuthTokenSecret();
    oauthParameters.setOAuthTokenSecret(oauthTS);

    GoogleOAuthHelper oauthHelper = new GoogleOAuthHelper(new OAuthHmacSha1Signer());
    oauthHelper.getOAuthParametersFromCallback(queryString,oauthParameters);

    login.setQueryStringTokens(queryString);
    login.setAccessTokenSecret(oauthTS);

    try {
        String accesToken = oauthHelper.getAccessToken(oauthParameters);
        login.setTokenSecret(accesToken);
    } catch (OAuthException e) {
        log.log(Level.WARNING,e.toString());
    }
    return login;
} 

public ArrayList<String> getPublicCalendars(String accessToken, String accessTokenSecret){
    ArrayList<String> result = new ArrayList<String>();
    CalendarFeed calendarResultFeed = null;

    GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
    oauthParameters.setOAuthConsumerKey(getFromSession(KEY_PARAM));
    oauthParameters.setOAuthConsumerSecret(getFromSession(SECRET_PARAM));
    oauthParameters.setOAuthToken(accessToken);
    oauthParameters.setOAuthTokenSecret(accessTokenSecret);            
    oauthParameters.setOAuthType(OAuthParameters.OAuthType.THREE_LEGGED_OAUTH);
    oauthParameters.setScope(getFromSession(SCOPE_PARAM));

    CalendarService myService = new CalendarService("exampleCo-exampleApp-1");                  

    try {
        myService.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
        URL calendarFeedUrl = new URL("https://www.google.com/calendar/feeds/default/owncalendars/full");
        calendarResultFeed = myService.getFeed(calendarFeedUrl, CalendarFeed.class);
    } catch (OAuthException e) {
        log.info("OAuthException");
        log.log(Level.WARNING,e.toString());
        e.printStackTrace();
    } catch (MalformedURLException e) {
        log.info("MalformedURLException");
        log.log(Level.WARNING,e.toString());
        e.printStackTrace();
    } catch (IOException e) {
        log.info("IOException");
        log.log(Level.WARNING,e.toString());
        e.printStackTrace();
    } catch (ServiceException e) {
        log.info("ServiceException");
        log.log(Level.WARNING,e.toString());
        e.printStackTrace();
    }

    if (calendarResultFeed != null && calendarResultFeed.getEntries() != null) {
        for (int i = 0; i < calendarResultFeed.getEntries().size(); i++) {
            CalendarEntry entry = calendarResultFeed.getEntries().get(i);
            result.add(entry.getTitle().getPlainText());              
        } 
    }
    return result;
}


private void getOauthParams(ServletContext context) {
    this.getThreadLocalRequest().getSession()
        .setAttribute(KEY_PARAM, context.getInitParameter(KEY_PARAM));
    this.getThreadLocalRequest().getSession()
        .setAttribute(SECRET_PARAM, context.getInitParameter(SECRET_PARAM));
    this.getThreadLocalRequest().getSession()
        .setAttribute(SCOPE_PARAM, context.getInitParameter(SCOPE_PARAM));
    this.getThreadLocalRequest().getSession()
        .setAttribute(CALLBACK_PARAM, context.getInitParameter(CALLBACK_PARAM));
}

private String getFromSession(String param){
    return (String) this.getThreadLocalRequest().getSession().getAttribute(param);
}

}

1 Ответ

1 голос
/ 06 июля 2011

Я недавно работал с oAuth. Внутри upgradeLogin (...) при обновлении до токена доступа вы не получаете соответствующий секретный токен доступа.

Секрет токена доступа после запроса getAccessToken () отличается от секрета токена доступа до запроса. В настоящее время вы устанавливаете секрет токена доступа (через login.setAccessTokenSecret (oauthTS)), это предварительно обновленное значение секрета токена доступа, которое вы используете. Вам необходимо установить для него секретное значение токена доступа, которое возвращается после запроса на обновление:

String accesToken = oauthHelper.getAccessToken(oauthParameters);
String accesTokenSecret = oauthParameters.getOAuthTokenSecret();                
login.setTokenSecret(accesToken);
login.setAccessTokenSecret(accesTokenSecret);

Вы также, вероятно, хотите где-то хранить эту обновленную пару токен / секрет. Именно это значение секретного токена доступа следует затем использовать внутри getPublicCalendars (...) в строке:

oauthParameters.setOAuthTokenSecret(accessTokenSecret);

Пара токен доступа / секретный ключ после обновления является долгоживущей и поэтому может использоваться повторно (без необходимости ее обновления) до тех пор, пока она не будет отменена.

Кстати, я обнаружил, что oAuth Playground Tool полезен при диагностике моих проблем.

Надеюсь, это поможет,

...