I'm writing a simple little application, which is a booking system. In the system there are two roles: administrator and user. All requests are working through the only servlet. Index.jsp (loginpage for user and admin) works without its help. So I have the starting url looking like this:
localhost:8080/[AppName]/index.jsp
To ensure security, I wrote a filter that will not allow anonymous users going to any page, except index.jsp; admin go on user page, and user go on admin page. But the problem is that I can't map the filter properly, because all the URLs in my app look like:
localhost:8080/[AppName]/servlet?command=[commandName]
Because of this, such a mapping, like (of course, in the web.xml the filter has already described before this mapping):
<filter-mapping>
<filter-name>Security</filter-name>
<url-pattern>/servlet?command=[commandName]</url-pattern>
</filter-mapping>
does not work, and I don't like it at all, because in this case it is necessary to prescribe all the commands of an application.
In this regard, I have an idea to make the url when smbdy log on like these:
localhost:8080/[AppName]/user - for user
localhost:8080/[AppName]/admin - for admin
In the web-inf folder I have inner folder "pages", in which there are several inner folders: "error", "admin" and "user", which keep jsp pages for these roles and errors.
How to implement the proposed idea? I suspect that this is quite trivial, but I didn't found the answer, because I even have no idea, how to name my issue.
I think i get it now;
-First make initial servlet (index.jsp ain't servlet), once user access your page he is being redirected to it. For example localhost:8080/YouWebAppName/IndexServlet.
IndexServlet check whether session is set, if not it redirects to accessible index.jsp, if the session is set then it checks the role, if the role is set to user it redirects to localhost:8080/YourWebAppName/UserServlet, if the session is set to Admin it redirects to localhost:8080/YourWebAppName/AdminServlet.
In both Admin and User servlet you check in the first place if the session variable equals respectively user/admin.
If there are methods that you want to share in both servlets, make third servlet call it however you want and then UserServlet and AdminServlet should extend that servlet
I've recently had something similiar in my project, try like that:
<servlet-mapping>
<servlet-name>YourServletName</servlet-name>
<url-pattern>/YourServletName/*</url-pattern>
</servlet-mapping>
In the servlet code I've got method:
protected String getActionSegment(HttpServletRequest request) {
String action = request.getRequestURI().
replace(request.getContextPath() +
request.getServletPath(), "").
replace("/", "").
trim();
return action.length() > 0 ? action : "index";
}
That method returns the name of the action, if the Url is localhost:8080/MyWebApp/MyServlet, then by default it redirects to index.jsp (you can change that)
In the servlet execution method you simply define what it should do (and where to redirect) in each case for example:
if(action.equals("admin")) {
//do something
} else if (action.equals("user")) {
//do something else
}
Let me know if that's what you meant.
Btw you can also restrict access to jsp folder and only make it work if servlet redirects to the jsp.
Related
So here is my problem, I am somewhat new to programming, and now I want to make "web.xml" in Java EE project, to rout every url that contains "/profile/" to a profile page, where depending on the id after "/profile/" it'll show current users data. I have the servlet mapped as below...
<servlet-mapping>
<servlet-name>RoutServlet</servlet-name>
<url-pattern>profile/*</url-pattern>
</servlet-mapping>
But what I am supposed to do in the servlet so I can get the id, and show current users data?
Please give me an advice, or nice resource where I can see how it's done.
Thank you in advance ! :)
That looks fine for the web.xml. In short, if you're using a JAX-RS implementation (e.g. Jersey), you should use the #Path annotation with #PathParam for the parameters, so something like:
#Path("/profile")
public class ProfileService {
#GET
#Path("/{id}")
public Profile getProfile(#PathParam("id") String id) {
//...
}
See the Oracle guide on RESTful Web services for some more background.
Firstly I would change tha mapping to the following:
<servlet-mapping>
<servlet-name>RoutServlet</servlet-name>
<url-pattern>/profile</url-pattern>
</servlet-mapping>
Secondly in RoutServlet you should have a the following code to get the userId
int userId = Integer.parseInt(req.getParameter("userId"));
And finally any URL's that sends a request to RoutServlet should look like this
http://someurl.com/profile?userId=//someId
This way you can let RoutServlet retrieve all the information of the User depending on what Id is in the GET request.
I would let RoutServlet put all the data it retrieves in an ArrayList<Object> profileData, redirect to a JSP and retrieve the data there using Expression Language, but I dont know what you use/prefer to display the data.
I working on Spring MVC app. The app funcionality is accessible through ReST API which jsp containing ajax logic consume. I am using spring security with defined roles (USER, COMPANY, ADMIN). Methods use requestMapping with responseBody such as:
www.app.com/auth/{userId}/request/{requestId}
It, of course, support GET for obtaining resource and POST for its creating or updating.
The problem is that after succesful login with, for example, userId = 1 I want GET request with requestId = 99. But when I run WebDev client for Chrome, I can also access another resource with easy request in format
www.app.com/auth/5/request/{requestId}
So basically, I can access resources, which I am not allowed to see. I hope you got the idea, where I am heading.
My question is - What is the best approach to secure this?
I was thinking about storing logged user Id (Integer) in session and comparing it everytime request for resource is made, but it seems to me that I am pulling the wrong end of rope :)
Thank you for any advice
You should have a look into the Expression-Based Access Control section of the spring security documentation.
Example copied from the documentation:
#PreAuthorize("#contact.name == authentication.name")
public void doSomething(Contact contact) {
..
}
This would check if name of the contact is equal to the name of the currently logged in user.
Using this this feature you can build much more sophisticated access rules than you could do with simple roles. However, this does not exclude using roles. You can still keep roles for basic security checks.
I want to allow users to create groups in my application and access them via URL. For example, if you made a group called "sweethatclub," you could access it at http://mysite.com/sweethatclub. Of course, the same code will run for /sweethatclub and /drillteam and even /students/yearbook
I'm running in a Java servlet environment, and can't quite get the paths to align for this. I can write a filter that intercepts all requests and adds information to the request by parsing the URL, but then I want to run the code of an index.jsp. I don't want to map index.jsp to all URLs, because, for example, /images/smiley.jpg still needs to respond the with appropriate file instead of index.jsp.
Is there a way to send all requests to a servlet, unless the request is matched by a plain-old file? Or, is there some other way to accomplish what I want here?
Please let me know if I need to supply more information. I'm new to this environment.
The URL patterns in the web.xml are not supposed to be smart enough to figure out target URL's nature. If you can tolerate it, the easiest way would be to place all the user specified paths under a a well known root... someplace separate from the static files. So you end up with user specified paths like http://mysite.com/sites/sweethatclub.
Alternatively, you can move all your static content under http://mysite.com/static/, and set up the servlet mappings or filters to treat anything starting with 'static' different from the dynamic URL space.
If you are in a Unix invironment, you could just create all the "group sites" as virtual directories that just point to your default one.
Map the servlet on a specific URL pattern
<url-pattern>/groups/*</url-pattern>
Put all static content in a common folder, e.g. /static and fix all URLs in the pages to point to that URL instead.
Create a filter which is mapped on
<url-pattern>/*</url-pattern>
and does the following job in doFilter() method
String uri = ((HttpServletRequest) request).getRequestURI();
if (uri.startsWith("/static/")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/groups" + uri).forward(request, response);
}
No, this does not end up with /groups in browser address bar URL. It's fully transparent. You can if necessary make "/static" and/or "/groups" an <init-param> of the filter so that it's externally configureable.
I'm studying EJB3.
I have a session bean which provides services to create/update customer accounts.
This session bean offers services on the lines of:
public void addCustomer(Customer c);
public void updateCustomer(Customer c);
Ideally I'd like to have a single servlet: CustomerServlet and it would invoke the session beans that I have listed above.
Problem is that I have two JSPs: UpdateAccount.jsp and CreateAccount.jsp. Both of these JSPs have a form with a method POST and action "CustomerServlet".
How can I distinguish in a customer servlet which operation I should carry out: createAccount or updateAccount?
I guess the alternative is to have a separate servlet for each operation...
Thank you
I'm not really certain about the best practice for this but I have a couple of suggestions that might work:
If your form is being submitted using a submit button, you could distinguish the request on the basis of the value of the <button-name> parameter. So if your buttons had the values Update and Create and were named account-submit, by checking the value you get with request.getParameter('account-submit'), you'd be able to tell which button was clicked to generate this request. If you named them differently, you could also just check which of the two parameters was not null and you'd know which form submit you were handling.
Note that if you have only a single text field in your form and the user hits Enter instead of clicking the button, you'll get a null in your servlet! See my blog post about this behaviour.
Check the Referer header - I wouldn't really recommend this since you wouldn't always know the context of the deployed app, this value may not always be present and it can be easily spoofed.
Add another mapping for your servlet so that it's accessible at both http://myapp.example.com/context/create and http://myapp.example.com/context/update. You can then check the ServletPath (request.getServletPath()) to see what 'servlet' the request came in for. I'd probably go with this one since it seems the most robust to me but you might also want to add the other two checks just to make sure. In your web.xml, you'd want something like
<servlet>
<servlet-name>CreateUpdateServlet</servlet-name>
<servlet-class>my.package.CustomerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CreateUpdateServlet</servlet-name>
<url-pattern>/create</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CreateUpdateServlet</servlet-name>
<url-pattern>/update</url-pattern>
</servlet-mapping>
JSPs are Servlets, just in a different source code form, there is no reason to POST to a different Servlet, you can just POST back to the same JSP.
You don't need the servlet. JSPs (or Facelets) can talk directly to the beans via EL.
Can the JSP servlet that filters on *.jsp (org.apache.jasper.servlet.JspServlet in Tomcat 6) be extended in some way so whenever someone goes to a JSP page I can do some server side authentication to check whether the user can view the page. Our current technique is a taglib in a common include that is imported into each JSP page, but it's not very elegant.
The key here is that I don't want to reinvent the wheel and worry about compiling JSPs into Servlets, I would ideally like to delegate in each method with super.meth().
I've been searching Google but I don't know the right keywords to use. Anything containing JSP and Servlet returns beginner tutorials.
Thanks,
John
Look at Servlet Filters, and use that Filter before forwarding to some JSP or Servlet.
When not taking benefit of the Java EE provided container managed security, then the normal basic practice is that you store the logged-in User in the session scope and uses a Filter on the desired url-pattern to check if the User is logged in.
Here's a basic example to get the picture:
Login:
User user = userDAO.find(username, password);
if (user != null) {
session.setAttribute("user", user);
} else {
// Do your thing to show "Unknown login" error.
}
Filter (which is mapped on an url-pattern of for example /secured/*, /protected/*, etc where in you place the restricted JSP pages expect of the login page):
User user = session.getAttribute("user");
if (user != null) {
chain.doFilter(request, response); // Logged in, so continue with request.
} else {
response.sendRedirect("login"); // Not logged in, redirect to login page.
}
Logout:
session.removeAttribute("user");
// Or, a bit too drastically:
session.invalidate();
You can of course also take benefit of what Java EE out of the box provides with regard to security. A commonly used way is the declarative container managed security wherein you can specify users and roles. You just need to declare a <security-constraint> and a <login-config> in the web.xml and configure an user realm in the appserver. The details depends on the appserver used, but if it is for example Tomcat 6.0, then you can find here some documentation about that.
If basic auth isn't sufficient, maybe Spring Security would be better. It's a natural, especially if you're already using Spring. One big advantage is that it's declarative, so you can easily protect URLs just by adding them to security configuration.
Doing this via inheritance would be brittle and require code changes every time you modified your security. Best to have security as a cross-cutting concern.
Can you not create another filter and put it above JspServlet?
This filter would check your security stuff and do some handling (e.g. redirect to login page) if something is wrong.