问题描述
|
当我执行CalendarService.setoAuthCredentials(oauthParameters,new OAuthHmacSha1Signer());我收到OAuthException 401错误未知授权标头。
我正在使用GWT + GAE,但我不知道为什么收到此错误,oauthParameters似乎还可以。
我得到用户登录
loginService.login
我检查我是否有
身份验证已经开启
oauthService.checkOauthTokenSecret
如果没有,我将重定向到Google
GCalendar的认证页面
允许
我得到查询字符串
由Google返回,我获得了访问权限
令牌和访问令牌的秘密和
将其设置为用户实体以备后用
在oauthService.upgradeLogin上使用。
并尝试获取日历
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);
}
}
解决方法
我最近一直在使用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对诊断我的问题很有用。
我希望这有帮助,