Dynamic url rewriting in a JavaEE JSF application - java

The application is deployed and in operation. The user, named John, comes to the login page - "my-site.com/login.xhtml", and logs in. We get the data about it from the database and must redirect it to the main page of the application - "my-site.com/main.xhtml". At the same time, in the address bar it should have a URL consisting of the data (its name) that we just received from the database, like this - "my-site.com/john".
There are wonderful prettyfaces and rewrite libraries that are designed to solve such problems, but unfortunately for redirection they need to know what URL to display (user name) during the deployment of the application, but of course we do not know it until the user is logged in.
Please help me to implement this?

you can follow this tutorial and use variable templating and query parameters.
https://github.com/ocpsoft/rewrite/blob/master/README.md
as copied from above link and modified:
return ConfigurationBuilder.begin()
.defineRule()
.when(Direction.isInbound().and(Path.matches("/{p}")))
.perform(Forward.to("/main.xhtml?user={p}"));
and let a Cdi bean handle the user parameter.

Related

Dynamic URL from database and MVC in JSP

I am learning JAVA and Spring Framework. I wanted to know that is it possible in java to create Dynamic URL in spring framework using values from url and fetching from database.
I am trying to make URL Shortner in Java and I will need to lookup for url's short code in my database and as we all know, url shortner will look like "url/ShorTCode" and my script will look for "ShorTCode" keyword in database and will redirect to associated weblink.
So I wanted to know that is it even possible in JAVA and Spring? And one more thing, if I make something like this "url/yt/VIdeoCode" or "url/fb/UserProfile"
So it will look at yt object which will redirect to youtube link only and fb object which will redirect to facebook user profile.
I want to clarify that I am still learning JAVA, JSP and Spring but I want to keep this thing in my mind while I am learning so I can focus on some particular things.
Thank you all fro helping me.
If you're asking how your controller could respond with a dynamic redirect, the answer is either:
(1) Have the controller return a "redirect:" result instead of view name. It must be followed with an absolute url, and behavior might depend on your spring version and configuration, but basically it looks like this:
#RequestMapping(...)
public String myMethod(){
String url=... // database lookup, e.g. "http://myUrl"
return "redirect:"+url;
}
(2) Less elegant but sometimes useful: get direct access to the response. If your controller method has a parameter of type HttpServletResponse spring will automatically inject it. So:
#RequestMapping(...)
public String myMethod(HttpServletResponse resp){
...
response.sendRedirect(...)
}

How to get current logged in user in hibernate event listener

I am using hibernate event listeners to record last modified time. I use a Custom Integrator to register the event listeners. I register my integrator by creating a file with a specific name in META-INF as explained here. I also want to record the username of the currently logged in user. I assume that information would be present in the HttpSession. But in the MergeEventListener I do not have access to the HttpSession. How do I get the HttpSession or is there any other way to get the currently logged in user?
The most common solution I have seen is to use a servlet-filter to put the information into a ThreadLocal when the request comes in, so that you can access it from a static context at whatever arbitrary point down the stack that you need it.
You can create one utility method in a singleton class and put the following line of code, which any time return the logged in Usrename
SecurityContextHolder.getContext().getAuthentication().getPrincipal()
I did the same in my web applicaiton using Spring + Hibernate.
Hope this will help for you as well.

does mvc architecture affect SEO?

I have my MVC architecture in my webapplication.Now the flow is as follows:
starter.jsp -> SERVLET ->view.jsp
Now view.jsp expects cetrtain request parameters to be present in request object.
When view.jsp is called using above workflow everything works fine.But if view.jsp is called directly then it does not get expected attributes in request and forwards to error.jsp
Now Will search engine directly call view.jsp? or will it travel from starter.jsp to view.jsp?
Detailed example:
main page has a href to a article.
href ="servlet?id=xyz"
Now servlet gets the id from request.
Servlet gets details for id from DB , puts the Object obtained from DB as request attribute
idDetails
And forwards to view.jsp
View.jsp gets request attribute idDetails
So view.jsp expects idDetails to be present as request attribute
There is no correlation between SEO and MVC. MVC manages the internals of your application while SEO is some external tweak. If they correlate somehow then there is something wrong with your application in my opinion.
If some files are public so the search engine can see them it is likely that they will be indexed. If in doubt you can always check your pages in google for example using the site: prefix.
So the point is that if you can see it google can see it.
I agree with Adam's reply. SEO and MVC architecture are not related at all.
If you have fear like, what happen If "CRAWLERS" will directly access your view.jsp page, then I suggest you to use Filters and Interceptors in your application.
So here your interceptor/filter will intercept the incoming request and filter it out if they are directly made by "Crawler Algorithm" OR "Suspect User".

How can I simulate/mock/bypass a JEE6 container managed login?

I'm using JEE6 security annotations #RolesAllowed("Admin") and a programmatic login:
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
request.login(loginUser.getUserName(), loginUser.getPassword());
However, for testing, I'd like to be able to 'simulate' a user login, and fool the app that a user logged in, without actually executing the above code. request.login(...) will ping the container for a login, I just want to tell the container that foo user has logged in and there is no need to check the password. I really don't want a solution that involves writing a login module or changing the settings of the entire container.
Thanks guys!
EDIT #1: What appserver am I using?
I'm using GlassFish 3.1.1. However, if possible, I'd like a solution that is 'container independent' using any available JEE6 api.
EDIT #2: Mr. Balus (a well regarded expert) is unaware of any api-neutral way bypassing the actual login. I supposed I could write my own "Yes-Man" login module, but I'm curious if anyone knows how to bypass the restriction specifically in the GlassFish environment.
Thanks!
EDIT #3: To anyone who finds this question later, I'm switched to Apache Shiro. I've used Spring Security in the past, but it's overkill for this app.
There's no API-provided facility for that. You could create a Filter which checks a certain VM argument or environment variable or even a JNDI variable and then does the login automagically.
E.g.
String login = System.getProperty("development.login");
if (login != null && request.getRemoteUser() == null) {
String[] nameAndPassword = login.split(":"); // Assuming "name:password".
request.login(nameAndPassword[0], nameAndPassword[1]);
}

Java EE Authentication Error Handling

We are currently trying to implement a web application which is using the Java EE authentication mechanism with a FORM-based login, inside the Websphere 6.1 web container. If the authentication is successful, we have everything working; the LDAP membership groups are being retrieved, the group to role mapping is being performed, and the roles are being returned to and correctly interpreted by the web application.
If the authentication is not successful, the form-login-error page is being returned. However, this is a static page that simply says something like "there was an error". How do we trap the specific error that prevented the successful login (username/password incorrect, LDAP repository unavailable, account locked, password expired, etc.)? It seems like there should be some easy way to do this, as you would want to treat some "security" exceptions differently than others.
I use Struts so it will do forwarding for you. If you don't have a framework (why not?) you'll will have to do it manually.
The Java EE spec covers the j_security_check servlet.
The login page POSTs j_username and j_password to the j_security_check servlet. Your app will be configured to error to an unauthorized page (see web.xml) but will (initially) call a servlet. 401 or 403 will go to a forbidden page (again web.xml)
Inside that servlet (which extends the HttpServlet) - you will check for all that good stuff.
public final void doGet(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
// initialize the app
AppInit initializer = new AppInit();
// get the logger
log = new Log4jWrapper(this.getClass());
// initialize the application session
HttpSession sess = request.getSession(true);
sess.setAttribute(CommonConstants.SESSION_CURR_USER_ID, request.getRemoteUser());
// initialize the JSP to forward to based on the user role
String fwdJSP = "SetupMainPage.jsp";
if (request.isUserInRole(CommonConstants.ROLE_MANAGER)) {
log.debug("User is a Manager");
}
//else other role checks - (these are users in groups in the LDAP)
// initialize the application session and set a variable to indicate that
// we are coming from a first time login (not a timeout login)
sess.setAttribute(CommonConstants.SESSION_COMING_FROM_INITIAL_LOGIN,"TRUE");
disp = getServletContext().getRequestDispatcher("SetupMainPage.jsp");
disp.forward(request, response);
}
//else failure
Unknown user
[11/22/08 8:54:47:993 EST] 7f6ac69c FormLoginServ E SECJ0118E: Authentication error during authentication for user s
right user - wrong password, but the request.getRemoteUser() will have a value
[11/22/08 8:56:45:082 EST] 7f51469c FormLoginServ E SECJ0118E: Authentication error during authentication for user jbsymolo
Unfortunately - i don't have any examples of someone locked out but I going to assume that the main security directory (LDAP) you will have an entry for the user for that.
This is from someone else (so I can't take credit)
I think this page describes how to do what you want to do.
Specifically how to retrieve the authentication exception from an arbitrary underlying authentication source (looks like Websphere calls them user registries).
Throwable t = com.ibm.websphere.security.auth.WSSubject.getRootLoginException();
if (t != null)
t = determineCause(t);
Where determineCause() is defined on the same page. This way, even if your server is configured to authenticate against a John Deer tractor, you will have access to the "OutOfGasLoginException" if there is one. The above code can go into the Servlet, Servlet Filter, or JSP that is redirect to by the container (as described above by jsymolon). It simply examines the exceptions and then places a corresponding friendly error message on the resulting page.
This is ancient knowledge - I believe to have done such a thing with tomcat. There was, as far as I can remember, no standard way, as the implementation was completely decoupled from the request and frontend web stuff, so that it was difficult to establish any means of communication between the authenticating component and the frontend (e.g. error page).
We ended up with a tomcat specific way, relying heavily on the current implementation. I'm no longer with that company, so I can't tell about the current state of the code or the solution we chose back then. I believe you'll also have to have some Websphere specific solution - be it the use of thread local variables, keying messages with the username that attempted to log in, somehow getting hold of the session identifier or similar.
Check this article Securing J2EE Applications with a Servlet Filter. I believe it covers your requirement to be able to pass the reason for the authentication error.
The JavaEE specification does not provide a standard mean to get an authentication feedback like error codes.
According to the following IBM Redpaper about z/OS security integration in gray note on page 57: IBM specific extension is available so that the error page JSP can report a specific message (like password expired) based on an error status code.
According to the WebSphere InfoCenter the FormLoginWeb sample from the TechSamp package in your WebSphere installation (samples/src/TechSamp/FormLoginWeb) is supposed to demonstrate such IBM specific extension but... The only thing interesting is the LoginFilter that intercepts calls on /j_security_check and is able to do pre-login validation and post-login action as explained in details in that paper.
With such a mechanism it is possible to get login exception from JAAS Subject and set an login error code in HttpSession so that the error page can generate a specific message.

Categories