2016-02-13 116 views
1

我正在开发使用struts 2hibernate Java Web应用程序,以限制从地址栏来的所有请求。我想限制用户通过直接在地址栏上输入来调用任何struts动作。相反,用户应该使用JSP页面本身提供的链接,因为在我的应用程序中有很多访问级别,所以用户通过在地址栏上直接输入操作名称来进行未经授权的访问。在返回成功之前,我检查了每个功能上登录用户的访问级别。但这不是一个好的做法,可以随处检查。我搜索了使用java Filters要做到这一点,但没有成功这样做。如何使用过滤器

不管我已经习惯了实现过滤器如下: -

的web.xmlSecurity是我的包名称和SessionFilterservlet类)

<filter> 
    <filter-name>SessionFilter</filter-name> 
    <filter-class> 
     Security.SessionFilter 
    </filter-class> 
    <init-param> 
     <param-name>avoid-urls</param-name> 
     <param-value>Index.jsp</param-value> 
    </init-param> 
</filter> 
<filter-mapping> 
    <filter-name>SessionFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

Index.jsp是入口poi nt我的应用程序,所以我想只允许通过在地址栏上输入,直接访问此页面。而如果用户键入地址栏上,他的任何其他动作名称/她应该被重定向到下面的代码再次that'swhy登录页我写了这个response.sendRedirect("Index.jsp");

SessionFilter.java

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.StringTokenizer; 

import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 

public class SessionFilter implements Filter { 

    private ArrayList<String> urlList; 

    public void destroy() { 
    } 

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 

     HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 
     String url = request.getServletPath(); 
     boolean allowedRequest = false; 

     if (urlList.contains(url)) { 
      allowedRequest = true; 
     } 

     if (!allowedRequest) { 
      HttpSession session = request.getSession(false); 
      if (null == session) { 
       response.sendRedirect("Index.jsp"); 
      } 
     } 
     chain.doFilter(req, res); 
    } 

    public void init(FilterConfig config) throws ServletException { 
     String urls = config.getInitParameter("avoid-urls"); 
     StringTokenizer token = new StringTokenizer(urls, ","); 
     urlList = new ArrayList<String>(); 
     while (token.hasMoreTokens()) { 
      urlList.add(token.nextToken()); 
     } 
    } 
} 
+0

“我想限制用户通过直接在地址栏上输入来调用任何struts动作”,然后“我想只允许通过在地址栏上输入任何内容来直接访问此页面”。相互矛盾。 –

+0

我不认为有可能通过直接在地址栏中输入或单击链接来检查用户是否访问特定页面。您应该在服务器端实现适当的安全性(例如,存储一些会话变量等) –

+1

问题确实很奇怪,因为您无处检查过滤器中的已登录用户,但只有在创建HTTP会话时(或“有一个会话“!=”登录用户“!)。至少,这是否提供了见解? http://stackoverflow.com/q/13274279 – BalusC

回答

-2

我得到了我的问题的解决方案,并在我的应用程序成功实施。非常感谢所有有用的答案和建议。

不管我已经实现如下: -

的web.xml

<filter-mapping> 
    <filter-name>struts2</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 
<filter> 
    <filter-name>SessionFilter</filter-name> 
    <filter-class> 
     Security.SessionFilter 
    </filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>SessionFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

SessionFilter.java

package Security; 

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.StringTokenizer; 

import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.RequestDispatcher; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 

public class SessionFilter implements Filter { 

    public void destroy() { 
    } 

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { 

     if (req instanceof HttpServletRequest) { 
      req.setCharacterEncoding("UTF-8"); 
      HttpServletRequest request = (HttpServletRequest) req; 
      String referrer = request.getHeader("referer"); 
      if (null == request.getSession(true).getAttribute("emp_id")) { 
       if (referrer == null) { 
        if (isSessionExcluded(req)) { 
         req.setAttribute("isSessionExpire", "true"); 
         RequestDispatcher reqDisp = req.getRequestDispatcher("/Index.jsp"); 
         reqDisp.forward(req, resp); 
        } 
       } 
      } else { 
       if (referrer == null) { 
        RequestDispatcher reqDisp = req.getRequestDispatcher("/Error.jsp"); 
        reqDisp.forward(req, resp); 
       } 
      } 
      chain.doFilter(req, resp); 
     } 
    } 

    public void init(FilterConfig config) throws ServletException { 
    } 

    private boolean isSessionExcluded(ServletRequest req) { 
     if (req instanceof HttpServletRequest) { 
      HttpServletRequest request = (HttpServletRequest) req; 
      String contextPath = request.getContextPath(); 
      String reqUri = request.getRequestURI(); 
      if (!(contextPath + "/Index.jsp").equals(reqUri)) { 
       return true; 
      } 
     } 
     return false; 
    } 
} 

我用String referrer = request.getHeader("referer"); in doFilter方法。这将区分请求是通过在地址栏上键入还是通过单击某个链接生成的请求。在通过地址栏输入生成请求的情况下,推荐人的值将为null

我希望这个解决方案对其他人也有帮助。

+2

糟糕的做法。原因如下:http://stackoverflow.com/q/2648984和http://stackoverflow.com/q/6880659换句话说:不要依靠引用来控制器/业务逻辑。最终用户可以完全控制其价值。如果用户输入任何操作名称,上述代码中的 – BalusC

+0

将不会受到限制。它只会限制最后会有.jsp扩展名的地址。 – Deepanshu

0

首先,访问级别检查不应该在jsp页面上。这个页面应该只显示视图。用户是否有权访问特定资源应该在服务器端使用某种用户级别或角色级别的安全性进行处理。为此,您可以实现自己的过滤器,也可以使用已经可用的安全库,如spring-security或shiro安全。

但是,如果你不想这样做,并想坚持你目前的做法,那么你可以检查每个请求的标头X-Requested-With。对于ajax请求,它包含XMLHttpRequest。但它不是一个标准头文件,所有的浏览器/用户代理都可能不会发送这个头文件。为了确保关于ajax请求,您可以为从页面发送的每个请求添加一些自定义标头。

但是,再次采用这种方法,如果未经授权的用户想要访问某个操作,他/她可以通过手动将该标头添加到他们的请求中来实现。因此,在服务器端而不是客户端检查授权是一个不错的选择。

+0

我已经完成访问级别的服务器端身份验证。其实我不想让用户通过在地址栏上直接输入操作名称来访问任何页面。的确用户可以使用提供的链接。 – Rish

0

您可以实现Filter来检查授权访问,并通过将其重定向到登录页面或索引页面来拒绝任何未经授权的访问。

但是因为你使用了struts2;您可以利用的优势struts2的拦截器:

定义一个Struts2的拦截器:

public class LogInInterceptor implements Interceptor { 

    @Override 
    public String intercept(ActionInvocation invocation) throws Exception { 

     Map<String, Object> sessionMap = ActionContext.getContext().getSession(); 

     if (sessionMap.get("urlList").contains(url)) { 
      return invocation.invoke(); 
     } else { 
      return "index-jsp-alias"; 
     } 

    } 

    // setters and getters. 
} 

在支柱定义这个拦截。xml文件:

 <interceptors> 
      <interceptor name="mylogging" class="LogInInterceptor" /> 
      <interceptor-stack name="loggingStack"> 
       <interceptor-ref name="mylogging" /> 
       <interceptor-ref name="defaultStack" /> 
      </interceptor-stack> 
     </interceptors> 
     <default-interceptor-ref name="loggingStack" /> 
     <global-results> 
     <result name="index-jsp-alias">Index.jsp</result> 
    </global-results>