I creating a web application using JSF,Hibernate,Spring. I have added a filter for checking session. My Filter code is :
public class AdminFilter implements Filter{
private ArrayList<String> urlList;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
String urls = filterConfig.getInitParameter("avoid-urls");
StringTokenizer token = new StringTokenizer(urls, ",");
urlList = new ArrayList<String>();
while (token.hasMoreTokens()) {
urlList.add(token.nextToken());
}
}
// Checking if user is logged in
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req= (HttpServletRequest) request;
HttpServletResponse resp= (HttpServletResponse) response;
String url = req.getServletPath();
HttpSession session = req.getSession();
if(!urlList.contains(url) && session.getAttribute("user")==null)
{
resp.sendRedirect(req.getContextPath() + "/backend/login/index.xhtml");
}
chain.doFilter(req, resp);
}
#Override
public void destroy() {
// throw new UnsupportedOperationException("Not supported yet.");
}
}
In the init method of filter i have some avoid URL for which session checking should be skipped, like for login page itself. This is working correct but this filter is restricting my CSS,images and JS to load on the login page.
Suggest me what is the problem in my filter ?
Your login page needs some resources (CSS, JS, Images) which are requested from browser in separate request which will be intercepted by Filter and since you don't have any parameters that skips such requests for resources (being used on login page) it will block this request
Suggestion:
You could use Spring-Security, rather than investing time in writing yours, it has got lots of flexibility by configuration
Based on your current config, Currently your filter is ignoring if the URL is for fetching css, images or any other resource.
boolean staticResources = (url.contains("css") || url.contains("images"));
if(!urlList.contains(url) && session.getAttribute("user")==null && !staticResources) {
resp.sendRedirect(req.getContextPath() + "/backend/login/index.xhtml");
}
This will avoid session checking for static contents.
Better way of doing this will be using the declarative security as part of Java EE Web Security using realm.
Related
I have a simple implementation of login filter.
public class LoginFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("loggedInUser") == null) {
response.sendRedirect(request.getContextPath() + "/login.jsp");
} else {
chain.doFilter(request, response);
}
}
#Override
public void destroy() {}
}
When I go to any registered page(i.e. /account?id=1) without session attribute loggedInUser, filter works fine. It redirects me to login page.
But if I go to non-exists page (i.e. /blablabla.html), filter redirects me to login page again. Is there any method to get 404 error on entering non-exists pages and redirect to /login on exists?
The bug is in the requirement: you filter all requests to deny access to guests but still want the request to be processed if it's a 404. This would be conceptually wrong: a 404 is still an applicative response in the sense that it gives the user a view of the internals of the system - so the user must be authorized before knowing that something is or is not there.
Another option is splitting your app in a public and a private zone:
/public/style.css
/public/app.js
...
/private/customer/123
/private/oder/8932
...
and just filter requests in the private zone.
Note: if you are concerned about the beauty of the URL consider that the /private/ prefix is not a requirement. The filter can be attached in such a way that any prefix can be omitted
Remember the filters are there to filter any incoming request or outcoming response, so actually the flow is something like this.
client -----> request ---- > filter ----> servlet dispather ----> resources
So now, unfortunately the request will be intercepted by the filter no matter is the resource exist or not, and this happens before the servlet dispather can get the request and get realize that the resource doesn't exist.
I hope, this explanation can answer your question.
Thanks.
In My application I did java project with ajax calling here I have a problem without Login also user can type url accessing the pages for that I used the below code but when i add the below code it's not working. I am getting Page not found error even I am unable to getting a login page also.
#WebFilter("/*")
public class LoginFilters implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
// If you have any <init-param> in web.xml, then you could get them
// here by config.getInitParameter("name") and assign it as field.
}
private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<partial-response><redirect url=\"%s\"></redirect></partial-response>";
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURL = request.getContextPath() + "/Login.jsp";
boolean loggedIn = (session != null) && (session.getAttribute("Username") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + "/Login.jsp");
boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));
if (loggedIn || loginRequest || resourceRequest) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response); // So, just continue request.
}
else if (ajaxRequest) {
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
}
else {
response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
}
}
#Override
public void destroy() {
// TODO Auto-generated method stub
}
// ...
}
can anyone tell me how can i do this
You should take a look to this : Securing a Web Application
Securing a Web Application
This guide walks you through the process of creating a simple web
application with resources that are protected by Spring Security.
What you’ll build
You’ll build a Spring MVC application that secures the page with a
login form backed by a fixed list of users.
Spring is absolutely the best solution and I really recommend to use it: it helps you on everything! If you don't want to use it right now and you don't care about security too much you can roughly use a session token or a simple static token(even a boolean, a char or a string) that checks if the user is coming from a certain page or not:
if the code in a certain servlet(or in spring controller) is executed you should set this boolean-whateverYouWant field to a certain value: when you load a page you can check the value of that field(spring mvc-angularJs or javascript) and then you can show the right page: "Not Allowed" if the token is null or void or what you prefer!
The best and definitely solution would be spring security-angularJs and web services exposed in a spring mvc controller. Seriously... think about learning spring!
I've created a RenderingPlugin, for use in WebSphere Portal, which is invoked serverside before sending markup to client. The plugin loops through all cookies and if 'test' is not found, I'd like to set that cookie.
I know this is possible with a HttpServletResponse but the RenderingPlugin doesn't have access to that object. It only has a HttpServletRequest.
Is there another way to do this?
public class Request implements com.ibm.workplace.wcm.api.plugin.RenderingPlugin {
#Override
public boolean render(RenderingPluginModel rpm) throws RenderingPluginException {
boolean found = false;
HttpServletRequest servletRequest = (HttpServletRequest) rpm.getRequest();
Cookie[] cookie = servletRequest.getCookies();
// loop through cookies
for (int i = 0; i < cookie.length; i++) {
// if test found
if (cookie[i].getName().equals("test")) {
found = true;
}
}
if (!found){
// set cookie here
}
}
}
Did you try using javascript code to set the cookie ?
<script>
document.cookie = "test=1;path=/";
</script>
you send this as part of the content you give to the Writer rpm.getWriter() and it will be executed by the browser.
I had a problem to simulate a cookie, that is only sending in production, in my test environment.
I solve with HttpServletRequestWrapper in a filter.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
Cookie cookie = new Cookie("Key", "Value");
chain.doFilter(new CustomRequest((HttpServletRequest) request, cookie), response);
}
}
class CustomRequest extends HttpServletRequestWrapper {
private final Cookie cookie;
public CustomRequest(HttpServletRequest request, Cookie cookie) {
super(request);
this.cookie = cookie;
}
#Override
public Cookie[] getCookies() {
//This is a example, get all cookies here and put your with a new Array
return new Cookie[] {cookie};
}
}
This filter is only started in test environment. My class WebConfig take care of this:
#HandlesTypes(WebApplicationInitializer.class)
public class WebConfig implements WebApplicationInitializer
I'm currently writing a little dynamic web-application in Java.
The application is supposed to be an event-platform where you can create a user-account, log in, and then you can see all open events (in a later iteration, users can create/participate in those events).
Right now, the structure of the web-app could be (simplified) described like this:
Register-Servlet -> Register.jsp
|
V
Login-Servlet -> Login.jsp
|
V
Main-page-Servlet -> Main.jsp
So right now, a user could go to Login.jsp, his login-information would be sent to the Login-Servlet, which would validate it and then send it to the Main-Page-Servlet.
The Main-Page-Servlet then (after validating login again) gets all current events from a database, attaches it to the request, and forwards it to the Main.jsp, which displays it for the user to see.
Now, if a user wants to access the Main.jsp directly (without coming from the Main-Page-Servlet), it obviously can not display the available events. The workaround I'm using currently is doing a null-check to see if the events are there, and if not, redirect to the Main-Page-Servlet.
It bothers me to solve my problem like that, as I don't think that's the best practice and I think it will just create a lot of other problems the bigger my application gets.
My first thought about this was, that it might be useful if I could simply "hide" all .jsp's from the user, so the user would be landing on servlets only and could not access the .jsp's in a different way.
Is there a way to do that? Or, if not, what would be the best practice solution if I would be writing a professional enterprise-level application?
This can be handled in a Filter and there are great explanation and example in StackOverflow Servlet-Filter wiki.
Adapting the code there for your problem (note the addition and usage of the needsAuthentication method):
#WebFilter("/*")
public class LoginFilter implements Filter {
#Override
public void init(FilterConfig config)
throws ServletException {
// If you have any <init-param> in web.xml, then you could get them
// here by config.getInitParameter("name") and assign it as field.
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String requestPath = httpServletRequest.getRequestURI();
if (needsAuthentication(requestPath) ||
session == null ||
session.getAttribute("user") == null) { // change "user" for the session attribute you have defined
response.sendRedirect(request.getContextPath() + "/login"); // No logged-in user found, so redirect to login page.
} else {
chain.doFilter(req, res); // Logged-in user found, so just continue request.
}
}
#Override
public void destroy() {
// If you have assigned any expensive resources as field of
// this Filter class, then you could clean/close them here.
}
//basic validation of pages that do not require authentication
private boolean needsAuthentication(String url) {
String[] validNonAuthenticationUrls =
{ "Login.jsp", "Register.jsp" };
for(String validUrl : validNonAuthenticationUrls) {
if (url.endsWith(validUrl)) {
return false;
}
}
return true;
}
}
I would recommend to move all the pages that require authentication inside a folder like app and then change the web filter to
#WebFilter("/app/*")
In this way, you can remove the needsAuthentication method from the filter.
There're several ways to do it such as servlet filter as above. I saw in some projects they use a simpler mechanism to do it by creating a common action (servlet). So instead of extends HttpServlet, all servlet will be extended the common action. And you can implement a lot of common stuffs such as authentication, validations, permissions...
Here's common action example:
public class CommonServlet extends HttpServlet {
................
................
protected boolean validate(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
request.setCharacterEncoding("UTF-8");
String email = (String) request.getSession().getAttribute("email");
Object salaryGroup = request.getSession().getAttribute("SALARY_GROUP");
if (email == null || email.equals("")) {
request.setAttribute("err", "You have not logged in");
request.getRequestDispatcher("/login.jsp").forward(request, response);
return false;
}
................
................
}
public void setRoleAndValidate(HttpServletRequest request, HttpServletResponse response, String role)
throws ServletException, IOException {
if (!validate(request, response)) {
return;
}
setRoleCode(role);
}
................
................
}
Your action servlet will be as below:
#WebServlet("/employeeManager")
public class EmployeeManager extends CommonServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
request.setCharacterEncoding("UTF-8");
setRoleAndValidate(request, response, Permission.EMPLOYEE_LIST.toString());
String action = request.getParameter("action");
.....
Here's the simple implementation
I'm running a web application in JBoss AS 5. I also have a servlet filter which intercepts all the requests to the server. Now, I want to redirect the users to the login page, if the session has expired. I need to do this 'isSessionExpired()' check in the filter and need to redirect the user accordingly. How do I do it? I'm setting my session time limit in web.xml, as below:
<session-config>
<session-timeout>15</session-timeout>
</session-config>
You could use a Filter and do the following test:
HttpSession session = request.getSession(false);// don't create if it doesn't exist
if(session != null && !session.isNew()) {
chain.doFilter(request, response);
} else {
response.sendRedirect("/login.jsp");
}
The above code is untested.
This isn't the most extensive solution however. You should also test that some domain-specific object or flag is available in the session before assuming that because a session isn't new the user must've logged in. Be paranoid!
How to redirect to Login page when Session is expired in Java web application?
This is a wrong question. You should differentiate between the cases "User is not logged in" and "Session is expired". You basically want to redirect to login page when user is not logged in. Not when session is expired. The currently accepted answer only checks HttpSession#isNew(). But this obviously fails when the user has sent more than one request in the same session when the session is implicitly created by the JSP or what not. E.g. when just pressing F5 on the login page.
As said, you should instead be checking if the user is logged in or not. Given the fact that you're asking this kind of question while standard authentication frameworks like j_security_check, Shiro, Spring Security, etc already transparently manage this (and thus there would be no need to ask this kind of question on them), that can only mean that you're using a homegrown authentication approach.
Assuming that you're storing the logged-in user in the session in some login servlet like below:
#WebServlet("/login")
public class LoginServlet extends HttpServlet {
#EJB
private UserService userService;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
response.sendRedirect(request.getContextPath() + "/home");
} else {
request.setAttribute("error", "Unknown login, try again");
doGet(request, response);
}
}
}
Then you can check for that in a login filter like below:
#WebFilter("/*")
public class LoginFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURI = request.getContextPath() + "/login";
boolean loggedIn = session != null && session.getAttribute("user") != null;
boolean loginRequest = request.getRequestURI().equals(loginURI);
if (loggedIn || loginRequest) {
chain.doFilter(request, response);
} else {
response.sendRedirect(loginURI);
}
}
// ...
}
No need to fiddle around with brittle HttpSession#isNew() checks.
you can also do it with a filter like this:
public class RedirectFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)request;
//check if "role" attribute is null
if(req.getSession().getAttribute("role")==null) {
//forward request to login.jsp
req.getRequestDispatcher("/login.jsp").forward(request, response);
} else {
chain.doFilter(request, response);
}
}
}
Check for session is new.
HttpSession session = request.getSession(false);
if (!session.isNew()) {
// Session is valid
}
else {
//Session has expired - redirect to login.jsp
}
Inside the filter inject this JavaScript which will bring the login page like this.
If you don't do this then in your AJAX call you will get login page and the contents of login page will be appended.
Inside your filter or redirect insert this script in response:
String scr = "<script>window.location=\""+request.getContextPath()+"/login.do\"</script>";
response.getWriter().write(scr);
You need to implement the HttpSessionListener interface, server will notify session time outs.
like this;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class ApplicationSessionListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
System.out.println("Session Created");
}
public void sessionDestroyed(HttpSessionEvent event) {
//write your logic
System.out.println("Session Destroyed");
}
}
Check this example for better understanding
http://www.myjavarecipes.com/how-to-catch-session-timeouts/
Until the session timeout we get a normal request, after which we get an Ajax request. We can identify it the following way:
String ajaxRequestHeader = request.getHeader("X-Requested-With");
if ("XMLHttpRequest".equals(ajaxRequestHeader)) {
response.sendRedirect("/login.jsp");
}
i found this posible solution:
public void logout() {
ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();
String ctxPath = ((ServletContext) ctx.getContext()).getContextPath();
try {
//Use the context of JSF for invalidate the session,
//without servlet
((HttpSession) ctx.getSession(false)).invalidate();
//redirect with JSF context.
ctx.redirect(ctxPath + "absolute/path/index.jsp");
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
When the use logs in, put its username in the session:
`session.setAttribute("USER", username);`
At the beginning of each page you can do this:
<%
String username = (String)session.getAttribute("USER");
if(username==null)
// if session is expired, forward it to login page
%>
<jsp:forward page="Login.jsp" />
<% { } %>