I am having trouble getting a response from the Twitter API. I am using scribe 1.3.5 here. When TwitterLoginServlet is called from one page it successfully redirects me to twitter and allows me to login. However, on the callback, TwitterCallbackServlet receives the following information in the oAuthResponse.
code - 401
message - Unauthorized
body - Failed to validate oauth signature and token
I am new to using both servlets and oauth so it is completely possible I am making some silly mistake in the following code. I believe this is all that is needed to find a solution to the problem but if you need additional information I will be checking this post vigilantly.
Thanks!
public class TwitterServlet extends HttpServlet {
private static final String SESSION_NAME_REQUEST_TOKN = "twitter.requestToken";
protected Token getRequestToken(HttpServletRequest req) {
HttpSession session = req.getSession();
try {
return (Token) session.getAttribute(SESSION_NAME_REQUEST_TOKN);
}
finally {
session.removeAttribute(SESSION_NAME_REQUEST_TOKN);
}
}
protected void setRequestToken(HttpServletRequest req, Token token) {
HttpSession session = req.getSession();
session.setAttribute(SESSION_NAME_REQUEST_TOKN, token);
}
protected OAuthRequest createRequest() {
OAuthRequest request = new OAuthRequest(Verb.GET, "https://api.twitter.com/oauth/request_token");
return request;
}
}
public class TwitterLoginServlet extends TwitterServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String callback = "http://" + request.getServerName() + ":" + request.getServerPort() + "/******/TwitterCallbackServlet";
OAuthService service = new ServiceBuilder().provider(TwitterApi.SSL.class)
.apiKey("******")
.apiSecret("******")
.callback(callback)
.build();
Token requestToken = service.getRequestToken();
setRequestToken(request, requestToken);
response.sendRedirect(service.getAuthorizationUrl(requestToken));
return;
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
public class TwitterCallbackServlet extends TwitterServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OAuthService service = new ServiceBuilder().provider(TwitterApi.SSL.class)
.apiKey("******")
.apiSecret("******")
.build();
Token requestToken = getRequestToken(request);
// TODO: Check if the requestToken matches the token of this request.
String verifier = request.getParameter(OAuthConstants.VERIFIER);
Token accessToken = service.getAccessToken(requestToken, new Verifier(verifier));
OAuthRequest oAuthRequest = createRequest();
service.signRequest(accessToken, oAuthRequest);
Response oAuthResponse = oAuthRequest.send();
String body = oAuthResponse.getBody();
response.sendRedirect("/******/accountSettings.xhtml");
}
Why are you hitting the requestToken endpoint again after getting the access token? Try accessing a different resource, for example:
"https://api.twitter.com/1.1/account/verify_credentials.json";
Note that you can run the TwitterExample just to check that stuff is working fine.
Related
I use the following rest client implementation of jersey to consume a rest service.I am able to do it successfully.Additionally now I need to send request parameters which will be consumed as part of HttpServletRequest on the producer side.
Consumer side Jersey client code
private ClientResponse getWebClientResponse(String RESOURCE_PATH, String methodType, Object requestObj) {
WebResource webResource;
ClientResponse response = null;
try {
String environmentHost = EnvironmentUtil.resolveEnvironmentHost();
Client client = prepareClient();
String RWP_BASE_URI = environmentHost + "/workflow/rest";
webResource = client.resource(RWP_BASE_URI);
WebResource path = webResource.path(RESOURCE_PATH);
if (GET.equals(methodType)) {
response = path.type(javax.ws.rs.core.MediaType.APPLICATION_JSON).get(
ClientResponse.class);
} else if (POST.equalsIgnoreCase(methodType)) {
response = path.type(javax.ws.rs.core.MediaType.APPLICATION_JSON).post(ClientResponse.class, requestObj);
}
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return response;
}
Producer side
#Context
public void setContext(SecurityContext context) {
this.context = context;
}
public HttpServletRequest getRequest() {
return request;
}
#Context
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public String getSessionUserPID(final HttpServletRequest request,
final SecurityContext context) {
if (request.getSession(false) == null) {
final String exceptionMessage = "getSessionUserPID() failed, session NOT FOUND for this request";
final Response response = Response.status(ExceptionStatus.UNAUTHORIZED.getNumber())
.entity(exceptionMessage).build();
LOG.error(exceptionMessage);
throw new WebApplicationException(response);
}
if (context.getUserPrincipal() == null) {
final String exceptionMessage = "getSessionUserPID() failed, user principal NOT FOUND";
final Response response = Response.status(ExceptionStatus.UNAUTHORIZED.getNumber())
.entity(exceptionMessage).build();
LOG.error(exceptionMessage);
throw new WebApplicationException(response);
}
final String userPID = context.getUserPrincipal().getName();
if (userPID == null || userPID.isEmpty()) {
final String exceptionMessage = "getSessionUserPID() failed, user principal name cannot be null or empty";
final Response response = Response.status(ExceptionStatus.UNAUTHORIZED.getNumber())
.entity(exceptionMessage).build();
LOG.error(exceptionMessage);
throw new WebApplicationException(response);
}
return userPID;
}
The main intention here is currently I get user information from weblogic security context but for a particular scenario I need to pass this part of rest service request and obtain it from HttpServletRequest object.How can I obtain this from httpservletrequest
You can use QueryParam or PathParam in GET method and FormParam in the POST method for sending request parameter to the server.
when i use retrofit .I got the exception java.lang.NoClassDefFoundError: Failed resolution of: Lokio/Buffer;i use okhttpclient in order to set header for retrofit.get userList is a post method,and i need to send body in request.
private void getUserList(int startIndex){
final JSONObject audienceObj = ProtocolHelper.getProtocolUtils(mContext).getUserlistJsonObj(mRoomData.mUid, mRoomData.mRoomId, startIndex);
OkHttpClient okClient = new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("sessionId", CommonData.getUserInfo(mContext).sessionId);
Request request = requestBuilder.build();
return chain.proceed(request);
}
})
.build();
String baseUrl = ProtocolUtils.BASE_URL+"/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(okClient)
.build();
String audienceUrl = ProtocolHelper.getProtocolUtils(mContext).getProtocolUrl(ProtocolUtils.PROTOCOL_MSG_ID_MEMBER_LIST);
AudienceInterface audienceInterface = retrofit.create(AudienceInterface.class);
Call<String> call = audienceInterface.getAudienceList(audienceUrl,audienceObj);
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
Log.d(TAG, "onResponse");
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.d(TAG, "onFailure"+t.getMessage());
}
});
}
public interface AudienceInterface {
#POST("{url}")
Call<String>getAudienceList(#Path("url") String url,#Body JSONObject boder);
}
the log t.getMessage is :java.lang.NoClassDefFoundError: Failed resolution of: Lokio/Buffer;
I solved it by adding:
implementation 'com.squareup.okio:okio:2.1.0'
in dependencies under build.gradle(Module: app).
Alright.~I found this error last time too.
By this:
NoClassDefFoundError: Failed resolution of: Lokio/Buffer
You might lost another jar lib--Okio.
You can download the jar file from github:
https://github.com/square/okio
And add this lib to your project.
In RegServlet class, I have a doGet() method that overrides the doStuff() method. doStuff() method takes the user input from an HTML registration form, then connects to the DB, then stores the user input into the DB.
Here is the doStuff() method in my RegServlet class:
public void doStuff(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, InstantiationException, IllegalAccessException, SQLException {
String userName = request.getParameter("userName");
...
String email = request.getParameter("email");
if(!userName.isEmpty()&&!passWord.isEmpty()) {
request.setAttribute("userName", userName);
...
request.setAttribute("email", email);
//connect to DB
toDB.createConnection();
//insert information to DB
toDB.insertNewUser(userName, passWord, lastName, firstName, age, sex, email);
RequestDispatcher view = request.getRequestDispatcher("login.jsp");
view.forward(request, response);
} else {
RequestDispatcher view = request.getRequestDispatcher("index.jsp");
view.forward(request, response);
}
If the register button is clicked after everything has been entered correctly, it leads me to a login.jsp page. I am now trying to code the log-in mechanism in order for a user (who possesses username & password stored in the DB) to log in and search and add/drop courses.
I am having a hard time because I am not sure how I should go about this.
How can I isolate user registration and authentication? Should I make another class for session management or just another method in this RegServlet class?
Implement your own HTTPServletFilter that check if a user is authenticated:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
if ("a user is authenticated") {
filterChain.doFilter(req, res);
} else {
// authenticate a user
}
}
The link show the basic of HTTPServletFilter:
http://www.oracle.com/technetwork/java/filters-137243.html#70176
I need to send custom HTTP header with login information to my play application (play 1.2.5). That custom header is added by filter.
Problem is that play always throws NullPointerException when I attempt to read:
String loggedUser = request.headers.get("loggeduser").value();
I have also a servlet for testing, where following prints vale from header correctly.
out.println(request.getHeader("loggeduser"));
Am I missing something in play?
Thanks
EDIT: This is my filter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
CustomHeaderWrapper wrapper = new CustomHeaderWrapper((HttpServletRequest) request);
String username = ((HttpServletRequest) request).getRemoteUser();
wrapper.addHeader("loggeduser", username);
chain.doFilter(wrapper, response);
}
And CustomHeaderWrapper:
private Map<String, String> customHeaderMap = null;
public CustomHeaderWrapper(HttpServletRequest request) {
super(request);
customHeaderMap = new HashMap<String, String>();
}
#Override
public String getHeader(String name) {
String header = super.getHeader(name);
return (header != null) ? header : this.getParameter(name);
}
#Override
public Enumeration getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
names.addAll(Collections.list(super.getParameterNames()));
return Collections.enumeration(names);
}
#Override
public String getParameter(String name) {
String paramValue = super.getParameter(name); // query Strings
if (paramValue == null) {
paramValue = customHeaderMap.get(name);
}
return paramValue;
}
public void addHeader(String headerName, String headerValue) {
customHeaderMap.put(headerName, headerValue);
}
I created a little test project, and used the line of code from your question. It works perfectly. I used the Dev HTTP Client plugin for Chrome to set the header.
Remember that all headers are converted to lowercase, before they are added to the request.headers hashmap. So if you placed "loggedUser" inside request.headers.get(), it would never work.
How can I intercept and send custom error messages with file upload when file size is exceeded. I have an annotated exception handler in the controller class, but the request does not come to the controller. The answer I came across on this link How to handle MaxUploadSizeExceededException suggests implementing HandlerExceptionResolver.
Have things changed in Spring 3.5 or is that still the only solution?
I ended up implementing HandlerExceptionResolver:
#Component public class ExceptionResolverImpl implements HandlerExceptionResolver {
private static final Logger LOG = LoggerFactory.getLogger(ExceptionResolverImpl.class);
#Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object obj, Exception exc) {
if(exc instanceof MaxUploadSizeExceededException) {
response.setContentType("text/html");
response.setStatus(HttpStatus.REQUEST_ENTITY_TOO_LARGE.value());
try {
PrintWriter out = response.getWriter();
Long maxSizeInBytes = ((MaxUploadSizeExceededException) exc).getMaxUploadSize();
String message = "Maximum upload size of " + maxSizeInBytes + " Bytes per attachment exceeded";
//send json response
JSONObject json = new JSONObject();
json.put(REConstants.JSON_KEY_MESSAGE, message);
json.put(REConstants.JSON_KEY_SUCCESS, false);
String body = json.toString();
out.println("<html><body><textarea>" + body + "</textarea></body></html>");
return new ModelAndView();
}
catch (IOException e) {
LOG.error("Error writing to output stream", e);
}
}
//for default behaviour
return null;
}
}