View Full Version : Controlling access to pages
jeremiah_lopez
Sep 11th, 2007, 02:43 PM
My project has all of the JSPs in the WEB-INF/classes directory and an index.jsp file that users will initially go to. index.jsp redirects to another jsp with the WEB-INF/classes directory (the initial menu). My question is how do I prevent users from accessing pages directly in a browser? Currently, I'm able to access http://localhost:7001/springapp/SSNValidation.html because all of the files specified as ending in .html are mapped to jsps. However, this will cause 500 errors because the user hasn't gone through 2 or 3 other pages previously in the flow and certain objects aren't set. I was thinking there was something I could do in formBackingObject() to check if certain objects are not set and then redirect back to the initial menu, but the only parameter available in formBackingObject is the request object, not response. Is there possibly another method I could use or any other recommendations? I cannot use Spring Web Flow either at this point.
infinity2heaven
Sep 11th, 2007, 03:13 PM
It's always a good practice to place all your jsps under WEB-INF/views or WEB-INF/pages. This will ensure that a user cannot access the files directly via a browser. For all other publicly accessible resources (login page, error page, css etc)
The web.xml setup looks like this
<servlet>
<servlet-name>public</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>public</servlet-name>
<url-pattern>/public/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>webapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webapp</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
Configure two applicationContext files namely public-servlet.xml & webapp-servlet.xml. Again all your public resources should be configured in public-servlet.
As for restricting access, if the user still types in the following
http://localhost:8080/webapp/pages/showEmployeeDetails
It is upto your authentication framework to intercept that request action and act accordingly (redirect to login page etc). With Acegi, you add a servlet filter and it's pretty much the same with other Security frameworks too
jeremiah_lopez
Sep 11th, 2007, 03:16 PM
Sorry, I misspoke on my initial post. All of the jsps are in WEB-INF/jsps, not WEB-INF/classes. I am not using an authentication framework like Acegi in my application; it is not needed. I just want to redirect users from accessing certain pages directly if they haven't stepped through the required flow and have certain objects populated. Isn't there some pattern in Spring MVC, namely using the SimpleFormController class, that can handle this?
infinity2heaven
Sep 11th, 2007, 03:41 PM
I just want to redirect users from accessing certain pages directly if they haven't stepped through the required flow
This is "Authorization", a feature of any Security Framework.
have certain objects populated
You can do this in formBackingObject but again, the right pattern to authorize this is via intercepting the request and redirecting to the Controller.
If you dont have any Security framework, then try writing a base class for your AbstractController which does something like
handleRequestInternal(request, response , ...) {
preprocess(request);
handleRequestProcess(request, response, ...);
postprocess();
}
in your preprocess, write your logic for "if they haven't stepped through the required flow " and return ModelAndView("errorPage");
or just return null. Let your subclass overwrite handleRequestProcess and write your usual logic of Controller returning the appropriate ModelAndView.
Isn't there some pattern in Spring MVC, namely using the SimpleFormController class, that can handle this?
I'm afraid your Issue is not relevant to a particular Controller. I'd suggest, referring the reference (http://www.springframework.org/docs/api/org/springframework/web/servlet/mvc/SimpleFormController.html)for a quick overview
Marten Deinum
Sep 11th, 2007, 04:19 PM
Why a base controller class?! Why not simply write an interceptor, wire it up to your HandlerMapping and you are good to go. Or if you really want to be sure you could even write a Filter to do it. However as a start a Interceptor should do nicely.
public class SecurityHandlerInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (request.getSession(true).getAttribute("yourattribute") == null) {
response.sendError(HttpServletResponse.SC_UNAUTHOR IZED);
return false;
} else {
return true;
}
}
}
This will send a normal UNAUTHORIZED code back to the client, this you can handle in your web.xml and redirect it back to your login page.
You could also place this code in a Filter and do the redirection/forwarding at once. It gives you a bit more control in places.
infinity2heaven
Sep 11th, 2007, 04:23 PM
I agree with you, however I wan't sure if jeremiah_lopez would be comfortable with interceptors (not using Acegi yet), hence proposed a simpler solution to begin with.
Interceptors is definitely more elegant!
Marten Deinum
Sep 11th, 2007, 04:26 PM
What has the use of interceptors to do with the usage of Acegi?! I don't see the link. We were using interceptors before using Acegi and we are still using them with Acegi.
jeremiah_lopez
Sep 12th, 2007, 07:09 PM
Why a base controller class?! Why not simply write an interceptor, wire it up to your HandlerMapping and you are good to go. Or if you really want to be sure you could even write a Filter to do it. However as a start a Interceptor should do nicely.
public class SecurityHandlerInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (request.getSession(true).getAttribute("yourattribute") == null) {
response.sendError(HttpServletResponse.SC_UNAUTHOR IZED);
return false;
} else {
return true;
}
}
}
This will send a normal UNAUTHORIZED code back to the client, this you can handle in your web.xml and redirect it back to your login page.
You could also place this code in a Filter and do the redirection/forwarding at once. It gives you a bit more control in places.
Forgive me for my ignorance on this matter, but how do I go about implementing an interceptor in my application? I understand that I create this class that extends HandlerInterceptorAdapter, but what additional configuration needs to happen? I assuming I need to setup the interceptor in web.xml. Is that it?
<venting>
On a side note, I personally think the Spring MVC, and the rest of the Spring documentation, is not very clear for newbies. If I have to spend two weeks reading through docs that are the size of a novel just to figure out how to do trivial tasks, then it's really not worth it to my clients who are expecting something in a month. A Google search on "Spring MVC tutorial" only brings up one worthwhile tutorial and the tasks that it covers are quite trivial.
</venting>
Jörg Heinicke
Sep 13th, 2007, 12:40 AM
I understand that I create this class that extends HandlerInterceptorAdapter, but what additional configuration needs to happen?
Somewhere you should have a HandlerMapping set up in your application context. You add the interceptors (http://static.springframework.org/spring/docs/2.0.x/reference/mvc.html#mvc-handlermapping-interceptor) to it.
<venting>
On a side note, I personally think the Spring MVC, and the rest of the Spring documentation, is not very clear for newbies. If I have to spend two weeks reading through docs that are the size of a novel just to figure out how to do trivial tasks, then it's really not worth it to my clients who are expecting something in a month. A Google search on "Spring MVC tutorial" only brings up one worthwhile tutorial and the tasks that it covers are quite trivial.
</venting>
Don't ask me how I made it but I did not find it unclear at all at the beginning and got everything running pretty fast. What I noticed so far though is that you at least have to also work with the Javadoc and sometimes even with the Java code itself.
Joerg
Marten Deinum
Sep 13th, 2007, 03:07 AM
As Jorg pointed out add it to your HandlerMapping as an interceptor and you should be good to go.
As for starting up, I normally start with the sample applications to see how things work. If I cannot figure it out I read that part of the reference guide. It is imho never a good idea to simple plugin a spring.jar and expect that everything is happening automatically for you. (You can ofcourse replace spring.jar with your framework of choice).
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.