I am using Facebook4j to post something on facebook. The following code worked the first time, but now it says: "This authorization code has been used". I would assume, this would give me a new access code everytime I use this, but apperently it does not. How can I tell facebook to give me a new access token instead of the same one over and over?
public class FacebookPublisher extends HttpServlet{
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Facebook facebook = new FacebookFactory().getInstance();
facebook.setOAuthAppId("appId", "appSecret");
facebook.setOAuthPermissions("email,manage_pages,publish_pages,publish_actions");
request.getSession().setAttribute("facebook", facebook);
StringBuffer callbackURL = request.getRequestURL();
int index = callbackURL.lastIndexOf("/");
callbackURL.replace(index, callbackURL.length(), "").append("/fb1callback");
response.sendRedirect(facebook.getOAuthAuthorizationURL(callbackURL.toString()));
}
}
This is the callback servlet and code:
public class FacebookPublisherCallback extends HttpServlet {
private static final long serialVersionUID = 6305643034487441839L;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Facebook facebook = (Facebook) request.getSession().getAttribute("facebook");
String oauthCode = request.getParameter("code");
try {
token = facebook.getOAuthAccessToken(oauthCode).getToken();
facebook = new FacebookFactory().getInstance();
facebook.setOAuthAppId("appId", "appSecret");
facebook.setOAuthPermissions("email,manage_pages,publish_pages,publish_actions");
facebook.setOAuthAccessToken(new AccessToken(token));
facebook.postStatusMessage("Hello World from Facebook4J.");
} catch (FacebookException e) {
e.printStackTrace();
}
}
}
Related
I have generated dynamic delete link for each row in a table in jsp. When I click on that link It should delete the associated row,It works Fine. But it should not delete the row once I logged out..I copied the delete link and logged out..Now If I run that link It redirects me to Login page, If I login again viewed the students in a table..It deletes that particular row.
Why this even after removed the attribute and invalidate the session It still able to reach the servlet?
generated link for delete student..
http://localhost:8080/feeManagement/Delete_Action_Student?delete=67657
Here are my DeleteStudent,Logout servlets.
#WebServlet("/Delete_Action_Student")
public class Delete_Action_Student extends HttpServlet {
private static final long serialVersionUID = 1L;
public Delete_Action_Student() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
if (request.getAttribute("Accemail") != "") {
String id = request.getParameter("delete");
try {
if (StudentDAOimpl.removeStudent(id)) {
request.setAttribute("msg", "deleted successfully");
getServletContext().getRequestDispatcher("/Delete_Student").forward(request, response);
} else {
request.setAttribute("msg", "failed to remove");
getServletContext().getRequestDispatcher("/Delete_Student").forward(request, response);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
response.sendRedirect("/loginjsp.jsp");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
Logout snippet.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
session.removeAttribute("Accemail");
session.invalidate();
response.sendRedirect("loginjsp.jsp");
}
It's the behavior of browser to store the url where you came from to login page. So After successful login it redirect to that url.
After successful login if you want to land always to home page you can do that by using filter.
I have a static 404 page with fancy stuff in it.
In case the user enters a wrong url of a page that does not exist, I would like him to see that 404 page , but also would like to keep the url as is in order for user to see what mistake s/he has done typing the url .
The page entered and that does not exist :
http://localhost:10039/my.website/my/halp.html
The 404 page :
http://localhost:10039/my.website/my/notfound.html
Briefly, instead of using "sendRedirect" here, I would to "get content" of pageNotFoundUrl and show it while the url is still http://localhost:10039/my.website/my/halp.html
Instead of redirect, I also tried "forward" as Kayaman suggested but in this case I get " Cannot forward. Response already committed."
TestServlet is defined in web.xml , and this class extends UtilFreemarkerServlet which extends FreemarkerServlet.
UtilFreemarkerServlet
public abstract class UtilFreemarkerServlet extends FreemarkerServlet {
private static final long serialVersionUID = 1L;
public static final String REQUEST_OBJECT_NAME = "RequestObject";
private Logger logger = LoggerFactory.getLogger(getClass());
#Override
public void init() throws ServletException {
logger.info("init started");
super.init();
Configuration cfg = getConfiguration();
cfg.setLocalizedLookup(false);
}
#Override
protected ObjectWrapper createObjectWrapper() {
return ObjectWrapper.BEANS_WRAPPER;
}
#Override
protected HttpRequestParametersHashModel createRequestParametersHashModel(HttpServletRequest request) {
request.setAttribute(REQUEST_OBJECT_NAME, request);
return super.createRequestParametersHashModel(request);
}
}
TestServlet
public class TestServlet extends UtilFreemarkerServlet{
private static final long serialVersionUID = 1L;
private String website;
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
boolean handleResult = handlerForRequest(req, resp);
}
protected boolean handlerForRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (resp.getStatus() == 404) {
String pageNotFoundUrl = "http://localhost:10039/my.website/my/notfound.html";
RequestDispatcher rd = req.getRequestDispatcher(url);
rd.forward(req, resp);
// resp.sendRedirect(url);
}
return true;
}
}
Do a forward instead of a redirect to the wanted resource, and the URL will stay the same.
RequestDispatcher rd = request.getRequestDispatcher("my_404.html");
rd.forward(request, response);
RequestDispatcher is not useful in my case because the response has always been committed. Here is the solution I end up with for Freemarker Servlets;
I am overriding a couple of methods of Freemarker servlet for my purpose such as service() and requestUrlToTemplatePath(). By this way, I am able to interfere right before the response is committed.
First Override is for the service method. My purpose is to check if the requested url page exists or not.
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
checkIfPageExists(req);
super.service(req, resp);
}
checkIfPageTemplateExists checks if the template of the page is null or not. If null, then it means it is not available. In this case I set a request attribute. Otherwise, it means it exists.
protected void checkIfPageExists(HttpServletRequest req)
throws ServletException {
String relativeUrl = requestUrlToTemplatePath(req);
try {
getConfiguration().getTemplate(relativeUrl); //throws exception if the template cannot be accessed
} catch (TemplateNotFoundException e) {
logger.debug("TemplateNotFoundException for " + relativeUrl);
pageNotFound = "/customNotFoundPage.html";
} catch (IOException e) {
logger.debug("IOException for " + relativeUrl);
pageNotFound = "/customNotFoundPage.html";
}
req.setAttribute(NOT_FOUND_PAGE, pageNotFoundPage);
}
And the last line stated in bullet 1 is for super.service() method. This will trigger the requestUrlToTemplatePath() method which is actually the method you can specify what url page to be shown without changing the url.
I am just checking if the request has a NOT_FOUND_PAGE attribute. If so, just overwrite the path itself and move on to the next step in the flow. Otherwise, just use the path of super class.
#Override
protected String requestUrlToTemplatePath(HttpServletRequest request)
throws ServletException {
String path = super.requestUrlToTemplatePath(request);
//Check if NOT_FOUND_PAGE is requested
if(request.getAttribute(NOT_FOUND_PAGE) != null) {
path = (String) request.getAttribute(NOT_FOUND_PAGE);
}
return path;
}
I have created simple app using Google Drive API with OAuth2 authentication based on this sample plus-appengine-sample
So, I have two servlets implementations: AbstractAppEngineAuthorizationCodeServlet and AbstractAppEngineAuthorizationCodeCallbackServlet which should do all the hard work for me (oauth work flow).
public class DriveServlet extends AbstractAppEngineAuthorizationCodeServlet {
private static final String MY_APP_NAME = "Drive API demo";
private static final long serialVersionUID = 1L;
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
AuthorizationCodeFlow authFlow = initializeFlow();
Credential credential = authFlow.loadCredential(getUserId(req));
if (credential == null) {
resp.sendRedirect(authFlow.newAuthorizationUrl()
.setRedirectUri(OAuthUtils.getRedirectUri(req)).build());
return;
}
Drive drive = new Drive.Builder(OAuthUtils.HTTP_TRANSPORT_REQUEST,
OAuthUtils.JSON_FACTORY, credential).setApplicationName(MY_APP_NAME).build();
// API calls (examines drive structure)
DriveMiner miner = new DriveMiner(drive);
req.setAttribute("miner", miner);
RequestDispatcher view = req.getRequestDispatcher("/Drive.jsp");
view.forward(req, resp);
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws ServletException, IOException {
return OAuthUtils.initializeFlow();
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
return OAuthUtils.getRedirectUri(req);
}
}
public class OAuthCallbackServlet extends AbstractAppEngineAuthorizationCodeCallbackServlet {
private static final long serialVersionUID = 1L;
#Override
protected AuthorizationCodeFlow initializeFlow() throws ServletException, IOException {
return OAuthUtils.initializeFlow();
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
return OAuthUtils.getRedirectUri(req);
}
#Override
protected void onSuccess(HttpServletRequest req, HttpServletResponse resp,
Credential credential) throws ServletException, IOException {
resp.sendRedirect(OAuthUtils.MAIN_SERVLET_PATH);
}
#Override
protected void onError(HttpServletRequest req, HttpServletResponse resp,
AuthorizationCodeResponseUrl errorResponse) throws ServletException, IOException {
String nickname = UserServiceFactory.getUserService().getCurrentUser().getNickname();
resp.getWriter().print(
"<h3>I am sorry" + nickname+ ", an internal server error occured. Try it later.</h1>");
resp.setStatus(500);
resp.addHeader("Content-Type", "text/html");
return;
}
}
public class OAuthUtils {
private static final String CLIENT_SECRETS_FILE_PATH = "/client_secrets.json";
static final JacksonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
static final UrlFetchTransport HTTP_TRANSPORT_REQUEST = new UrlFetchTransport();
private static final Set<String> PERMISSION_SCOPES = Collections.singleton(DriveScopes.DRIVE_READONLY);
private static final AppEngineDataStoreFactory DATA_STORE_FACTORY = AppEngineDataStoreFactory.getDefaultInstance();
private static final String AUTH_CALLBACK_SERVLET_PATH = "/oauth2callback";
static final String MAIN_SERVLET_PATH = "/drive";
private static GoogleClientSecrets clientSecrets = null;
private OAuthUtils() {}
private static GoogleClientSecrets getClientSecrets() throws IOException {
if (clientSecrets == null) {
InputStream jsonStream = OAuthUtils.class.getResourceAsStream(CLIENT_SECRETS_FILE_PATH);
InputStreamReader jsonReader = new InputStreamReader(jsonStream);
clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, jsonReader);
}
return clientSecrets;
}
static GoogleAuthorizationCodeFlow initializeFlow() throws IOException {
return new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT_REQUEST,
JSON_FACTORY, getClientSecrets(), PERMISSION_SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline").build();
}
static String getRedirectUri(HttpServletRequest req) {
GenericUrl requestUrl = new GenericUrl(req.getRequestURL().toString());
requestUrl.setRawPath(AUTH_CALLBACK_SERVLET_PATH);
return requestUrl.build();
}
}
Authentication flow works as expected as well as Drive API calls, but somehow, after some period of time, I'm getting this exception on refresh:
Uncaught exception from servlet
com.google.api.client.googleapis.json.GoogleJsonResponseException: 401
{
"code" : 401,
"errors" : [{ "domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Invalid Credentials",
"reason" : "authError" }],
"message" : "Invalid Credentials"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1049)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at sk.ennova.teamscom.drive.DriveMiner.getRootFolderId(DriveMiner.java:46)
at org.apache.jsp.Drive_jsp._jspService(Drive_jsp.java:61)
It seems that token has expired, but isn't it a work for servlets to request a new access token with the refresh token which they stored? I use offline access type, so refresh token should be delivered to callback servlet at first request.
Here "401 Unauthorized" when trying to watch changes on Google Drive with Java API Client are some hints where could be the problem, but handling token expiration should not be my case if I'm using these servlets (correct me if I am wrong). Also scope DriveScopes.DRIVE_READONLY seems OK for reading "drive" tree structure (get files of given folder and so on). Where could be the problem?
You need to first specify that you need a refresh token for offline / long term access and then save the refresh token for later use when the access token expires. You can request a new access token using the refresh token until the user revokes your access to her account. See the official documentation here:
https://developers.google.com/accounts/docs/OAuth2WebServer#refresh
To begin I am a bit new to java.
I have a web application I have been assigned to work on. It collects various user inputs via form and sends them via an a4j commandButton to a method in my jar folder. The method uses the form data to construct a web service client call. Part of the requirement is that I pass, as an element in the web service call, the current JSESSIONID from the request.
Steps I have taken:
In the class that contains the method I am calling I have set up getters and setters (outside of the helper class below).
I have added a helper class to my class as follows:
class GetSessionId extends HttpServlet {
private String sessionid;
public void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
sessionid = session.getId();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
public String getSessionId(){
return sessionid;
}
public void setSessionId(String sessionid){
this.sessionid=sessionid;
}
}
When I need the get the sessionid I used:
GetSessionId session_ID = new GetSessionId();
String sessionid = session_ID.getSessionId();
String sessionId = sessionid;
System.out.println("show me = " + sessionId);
But in the console (testing on my localhost) sessionid is null.
What am I doing wrong?
I am testing scribe for facebook authentication. I am not receiving the oauth_verifier when authenticating against facebook - let me know if this is incorrect behavior. For facebook auth, how should I go about creating the verifier in order to create the OAuthRequest.
redirect_uri=http%3A%2F%2Flocalhost%2Foauth%2Ffacebook
Thanks
LoginServlet:
public void doGet(HttpServletRequest req, HttpServletResponse res) {
OAuthService service = new ServiceBuilder().provider(FacebookApi.class).apiKey(FACEBBOK_APP_KEY)
.apiSecret(FACEBOOK_APP_SECRET).callback(FACEBOOK_CALLBACK);
String authenticationUrl = service.getAuthorizationUrl(null);
res.sendRedirect(authenticationUrl);
}
CallbackServlet:
public void doGet(HttpServletRequest req, HttpServletResponse res) {
String code = "";
Enumeration paramEnum = req.getParameterNames();
while (paramEnum.hasMoreElements()) {
String name = (String) paramEnum.nextElement();
if (name.equals("code")) {
code = req.getParameter(name);
}
OAuthService service = new ServiceBuilder().provider(FacebookApi.class).apiKey(FACEBBOK_APP_KEY)
.apiSecret(FACEBOOK_APP_SECRET).callback(FACEBOOK_CALLBACK);
Verifier verifier = new Verifier(code);
//....
}