Programmatically using j_security_check - java

I have page like localhost:7001/MyServlet. I am making a http connection request from like below
String url = "http://localhost:7001/MyServlet"
PostMethod method = new PostMethod(url);
HttpClient client = new HttpClient();
However "MyServlet" is protected by j_security_check. So when I am making my connection , getting redirected to login page.
How to get authenticated and access my url , in one HttpConnection
Note: I use apache common httpclient
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;

I doubt you can log in and call the server in a single request, unless HTTP BASIC authentication is enabled. While I do not know the details of HTTPClient's API yet, basically you will need to track a session using cookies; POST your login to /j_security_check; then access the servlet. (The same basic process works for /j_acegi_security_check if using ACEGI Security.)
A nasty wrinkle in Tomcat is that just posting right away to /j_security_check gives a 400 "bad request"; its authenticator is rather finicky about state transitions and was clearly not designed with programmatic clients in mind. You need to first access /loginEntry (you can throw away the response other than session cookies); then post your login information to /j_security_check; then follow the resulting redirect (back to /loginEntry I think) which will actually store your new login information; finally post to the desired servlet! NetBeans #5c3cb7fb60fe shows this in action logging in to a Hudson server using Tomcat's container authentication.

Related

Javalin sessionAttribute() isn't Persisting Between Requests

I'm setting up Javalin as a microservice, providing API endpoints for my React app. Locally, Javalin is running on port 7070 and React is running on 3000 (via the built-in server with create-react-app).
I'm attempting to wire up the login/logout services, and in my login controller I have this code.
boolean isValid = User.isPasswordValid(u, password);
if (isValid)
{
ctx.sessionAttribute("currentUser", u.userHash);
}
In the React code, it listens to the success response from this controller and then reroutes to the /dashboard page. The /dashboard page loads up data, and I'm getting the data appropriate for the user by getting that userHash out of the Session like this:
String userHash = ctx.sessionAttribute("currentUser");
However, this is always returning null.
It seems like this should work, and even matches the tutorial code posted on the Javalin website https://javalin.io/tutorials/website-example
Is the fact that the React code and the Javalin running on different servers cause this to not work? I tried replacing the sessionAttribute() with cookieStore() and it has the same null issue.
Edit - Adding The Reponse information showing a JSESSIONID
After discussing with the Javalin creator, the correct answer is to include this line in the server creation:
app.before(ctx -> ctx.header("Access-Control-Allow-Credentials", "true"));
and ensure your JavaScript call includes the option:
credentials: "include",

URL not changing on page redirection in Jersey and MongoDB

My scenario is like this:
I'm building a website where I'm posting an ad regarding a topic. So, after the form filling of ad, the request goes to a REST service class as:
http://localhost:8080/cloudproject/postadvaction?title=tution&tag=tution&description=tution+%401000+%2F+month&category=TUTOR&location=indore
Here, the details of ad go in the database which is MongoDB. After all of this is done I'm redirecting to the profile page of user using Viewable model of jersey, where he can see all the ads posted by him. It is done as:
return new Viewable("/profile.jsp");
After this the response is redirected to profile page of the user.
But the problem is that, on redirecting the response to simply profile.jsp, the URL in the address bar has not changed to http://localhost:8080/profile.jsp, instead, it has remained the same as mentioned above. So, when user refreshes the page, the request of same ad post triggers and the whole process is followed again. Since, database is MongoDB, same ad is stored twice in it and same is displayed on the profile page of user with 2 identical ads.
So, how can I redirect to profile page without having the address of servlet in address bar?
Update: The question is related to PRG technique & Duplicate Form Submissions and not to just redirection.
See Post/Redirect/Get
When a web form is submitted to a server through an HTTP POST request, a web user that attempts to refresh the server response in certain user agents can cause the contents of the original HTTP POST request to be resubmitted, possibly causing undesired results, such as a duplicate web purchase.
To avoid this problem, many web developers use the PRG pattern[1] — instead of returning a web page directly, the POST operation returns a redirection command. The HTTP 1.1 specification introduced the HTTP 303 ("See other") response code to ensure that in this situation, the web user's browser can safely refresh the server response without causing the initial HTTP POST request to be resubmitted. However most common commercial applications in use today (new and old alike) still continue to issue HTTP 302 ("Found") responses in these situations.
With Jersey you can use
Response.seeOther(URI) - Create a new ResponseBuilder for a redirection. Used in the redirect-after-POST (aka POST/redirect/GET) pattern.
You just need to change your method signature to return a Response and return the built Response
return Response.seeOther(URI.create(...)).build();
Also stated about the URI parameter
the redirection URI. If a relative URI is supplied it will be converted into an absolute URI by resolving it relative to the base URI of the application (see UriInfo.getBaseUri()).

How does cookies work, when calling cookie-setting REST services from java VM?

I'm in the process of learning how to use HP Quality Center's REST api to query and manipulate data. Unlike REST standard, this API is not completely stateless. It uses cookies to store authentication sessions.
I've tried to implement a very simple test, using the Jersey Client library. I can successfully authenticate my user, by sending my credentials. The API reference claims that this will set a cookie, and I am good to go with further calling the REST api. However, a simple "is-authenticated" call returns a 401, Authentication failed.
I have a feeling that the cookie writing or reading is not working properly, as everything else seems to work as it should. But I haven't been able to find out if or how cookies are set and read, when no browser is involved. So How does cookies work, when calling cookie-setting REST services from java VM? Does it work at all? Where are they stored?
I am using Eclipse Kepler as my IDE, if that matters at all, and a 32-bit java 1.6 JDK and JRE.
Code, and response strings below:
1. Logging in:
Client client = ClientBuilder.newClient();
Response response = client
.target("http://[host]:[port]").path("qcbin/authentication-
point/alm-authenticate")
.request().post(Entity.entity("<alm-authentication>
<user>username</user>
<password>secret</password></alm-authentication>",
MediaType.TEXT_XML_TYPE));
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=POST,
uri=http://[host]:[port]/qcbin/authentication-point/alm-authenticate,
status=200, reason=OK}}
API Return description:
One of:
HTTP code 200 and sets the LWSSO cookie (LWSSO_COOKIE_KEY).
HTTP code 401 for non-authenticated request. Sends header
WWW-Authenticate: ALMAUTH
2. Verifying Logged in:
response = client.target("http://[host]:[port]")
.path("qcbin/rest/is-authenticated")
.request().get();
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=GET,
uri=http://[host]:[port]/rest/is-authenticated, status=401,
reason=Authentication failed. Browser based integrations - to login append
'?login-form-required=y to the url you tried to access.}}
PS: adding the ?login-form-required=y to the URL, will bring up a log-in window when called in a browser, but not here. Appending the line to the URL actually still gives the same error message, and suggestion to append it again. Also, when called in a browser, the is-authenticated returns a 200, success, even without the login-form.
When you log in, you're getting a cookie which is a name plus a value.
The REST server expects you to pass this in the request header with every request you make.
Look into the object which you get for client.request(); there should be a way to specify additional headers to send to the server. The header name must be Cookie and the header value must be name=value.
So if the server responds with a cookie called sessionID with the value 1234, then you need something like:
client.request().header("Cookie", "sessionID=1234")
Related:
http://en.wikipedia.org/wiki/HTTP_cookie

How can I access a 'Web App' built in Google Apps Script from Android?

I can successfully access Google Drive and Spreadsheet functionality from my application.
So I have an authorised instance of com.google.api.client.auth.oauth2.Credential.
Now I wish to execute a Google Apps Script that is deployed as a 'Web App'. This will also require authentication to run. This script runs in the browser if I hit the endpoint and am authenticated.
Here's some psuedo code :
String url = "https://script.google.com/a/macros/mycompany.com/s/xxxx/dev";
GenericUrl webAppEndPoint = new GenericUrl(url);
final HttpTransport httpTransport = AndroidHttp.newCompatibleTransport();
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(currentCredential);
// Do POST for service
String requestBody = URLEncoder.encode("{\"name\":\"John Smith\",\"company\":\"Virginia Company\",\"pdf\":\""+getPdfBase64()+"\"}", "UTF-8");
HttpRequest postRequest =requestFactory.buildPostRequest(new GenericUrl(url), ByteArrayContent.fromString(null, requestBody));
postRequest.getHeaders().setAccept("application/json");
postRequest.setFollowRedirects(true);
postRequest.setLoggingEnabled(true);
HttpResponse postResponse = postRequest.execute();
If I run the code I get the following error : com.google.api.client.http.HttpResponseException: HttpResponseException 405 Method Not Allowed
UPDATE : So - originally i was POSTing to the wrong URL ( i'd copied the redirected URL from a browser instead of the script URL )
The POST is now successful ( authentication included ) using the above code, but it still doesn't handle the GET redirect after submission. I can work with this now but it would be good to be able to get a response from the server.
I think that com.google.api.client.http.HttpRequest doesn't handle authenticated POST redirects properly.
Your pseudocode isn’t very illuminating; to really see what’s going on you’d need to show the actual HTTP traffic. I should say though that a 302 redirect to a specified redict_uri is a normal part of the OAuth 2 authentication flow.
1) you cant call an apps script with authentication. You need to publish it as anonymous access as a contentService.
2)you are also calling the wrong url. Call the service url not the redirected one that you get in the browser.

How to take a redirection URL

I have a problem with redirection, in my work I have to make a connection to a URL that automatically go to another URL at this point it takes the credential (username and password) and redirect to a URL that contains a parameter which need me. How can I take this parameter?
To be precise, I have to do this:
Embed a Web browser with the URL https://graph.facebook.com/oauth/authorize with your client_id and the type set to user_agent. Since your application is embedding a small window, you can trigger a compact "popup" version of the authorization dialog with the display parameter:
graph.facebook.com/oauth/authorize?
client_id=...&
redirect_uri=www.facebook.com/connect/login_success.html&
type=user_agent&
display=popup
After the user authorizes your application, we redirect the user back to www.facebook.com/connect/login_success.html with the access token in the URL fragment: www.facebook.com/connect/login_success.html#access_token=...&expires_in=... Intercept the redirect above and read the access token out of the URL. Use the access token to fetch data from the Graph API on behalf of the user:
graph.facebook.com/me?access_token=....
I need access_token.
you can use apache http components httpclient to do this,
it will automatically follow redirects
HttpClient client=new HttpClient();
GetMethod get=new GetMethod("graph.facebook.com/oauth/authorize?client_id=...& redirect_uri=www.facebook.com/connect/login_success.html&type=user_agent&display=popup");
int status=client.exectueMethod(get);
Then you will have the information you need in the Location header of the response which you can access by using:
String location=get.getResponseHeader("location").getValue();
and parse the location-header for the url fragment you want.
hope that helped

Categories

Resources