天天看点

web程序的统一认证实现:filter操作

现在web程序很多都用到统一认证这东西,刚好看《jsp2.0技术手册》看到这块,看完感觉有点模糊,所以就自己写代码试了一下,花了好长一段时间,原因终于在今天找到了,并且成功解决,但是我并没有因此而感到自豪,因为我越来越感觉自己蠢了,蠢得无可救药。废话不说了,看下面的东西吧:

  用filter实现统一认证我用了5个页面,分别为:login.jsp,filter2.jsp,filter3.jsp,LoginCheck.java,SessionCheck.java.其中最主要的是SessionCheck.java.另外还需要配置web.xml文件,这个千万不能忘记哦。

  下面是我的web程序的结构图:

web程序的统一认证实现:filter操作

下面看下各个页面的代码(内含很多注释,方便理解):

SessionCheck.java:

1 package filter;  

2   

3 import java.io.IOException;  

4 import javax.servlet.Filter;  

5 import javax.servlet.FilterChain;  

6 import javax.servlet.FilterConfig;  

7 import javax.servlet.ServletContext; 

8 import javax.servlet.ServletException; 

9 import javax.servlet.ServletRequest;

10 import javax.servlet.ServletResponse; 

11 import javax.servlet.http.HttpServletRequest; 

12 import javax.servlet.http.HttpServletResponse; 

13 import javax.servlet.http.HttpSession; 

14  

15  

16 public class SessionCheck implements Filter {

17     

18     private ServletContext context;

19     private String targetUri; 

20 

21     public void destroy() { 

22         // TODO Auto-generated method stub 

23          

24     } 

25  

26     public void doFilter( 

27             ServletRequest request,  

28             ServletResponse response, 

29             FilterChain chain) throws IOException, ServletException { 

30         // TODO Auto-generated method stub 

31         HttpServletRequest httpRequest = (HttpServletRequest)request; 

32         HttpServletResponse httpResponse = (HttpServletResponse) response; 

33         /** 

34          * getSession(false)此方法如果得不到session,也不会自动创建一个session 

35          *  

36          * 插曲:看到getSeesion(false)表示之前没看到过,不知道意思,本能的猜测是: 

37          * 如果没有得到sesson,则返回null,如果参数为true,得不到session那就重新创建一个 

38          * 因为只是猜测,所以上csdn查了下,结果看到一帖子,说的果断和我的理解相反,

              接着看,下面各种各样的回复,琳琅满目 

39          * 当然,在找之前已经用debug验证过了,我的想法只要不是验证方法错了那我的理解肯定是对的 

40          * 结果在csdn看到几乎一样的问题,而且一楼回答刚好跟我的完全相反,并且楼主还给了30分,这让我不由的蛋疼了下,

41          * 结论完全相反呀,继续忐忑的往下看,一哥们什么都没解释,直接把关于session的官方文档给拉出来贴着,全英文,还好哥虽然没过6鸡

42          * 但也还是能看懂几个abc的,意思跟我理解一样,忐忑的心终于有点放下了,继续往下看,一看id,俨然是楼主本人,一看内容,我热泪盈眶 

43          * 楼主你Y真是好人啊,一楼理解完全相反你Y居然给30分,你妹啊,害得我还犹豫了半天,纳闷了半天,不过还好你出来纠正了你之前的 

44          * NC行径,也算是一大进步。 

45 */ 

46         HttpSession session = httpRequest.getSession(false);

47          

48         if(session != null){

49             String passed = (String)session.getAttribute("passed"); 

50             if("true".equals(passed)){ 

51                 chain.doFilter(httpRequest, httpResponse);

52                 /** 

53                  * return 说明filter在执行了chain.doFilter之后会返回来继续执行原先的filter

54                  * 相当于一个递归调用 

55                  * return 下面的代码表示执行失败的情况 

56 */

57                 return; 

58             }else if("passing".equals(passed)){ 

59                 /** 

60                  * httpRequest.getRequestURL()获取绝对路径

61                  * 例如http://127.0.0.1:8088/webTest/filter1/login.jsp 

62                  *  

63                  * httpRequest.getRequestURI()获取相对路径。 

64                  * /webTest/filter/LoginCheck,其中filter/LoginCheck为jsp页面中form表单的action值

65                  * 对应的Servlet的<url-pattern>要写成/filter/LoginCheck 66 */

67                 if("/webTest/filter/LoginCheck".equals(new String(httpRequest.getRequestURI()))){ 

68                     chain.doFilter(httpRequest, httpResponse); 

69                     return; 

70                 }

71             } 

72             /** 

73              * 如果之前的filter执行均失败,则说明这个session中的passed认证已经是错误的,必须删除 

74 */ 

75             session.removeAttribute("passed"); 

76         } 

77         /** 

78          * requestUrl保存当前请求的url 

79          * query保存当前请求下的参数 

80 */

81         StringBuffer requestUrl = new StringBuffer(httpRequest.getRequestURI());

82         String query = httpRequest.getQueryString(); 

83         if(null != query){ 

84             requestUrl.append(query); 

85         }

86         /**

87          * 设置request范围内的originalUri(认证之前的请求地址),用于在login页面获取,并可以通过隐藏参数的形式把这个值传递到LoginCheck 

88          * 当登录之后就可以直接转到login认证之前的页面 

89 */ 

90         httpRequest.setAttribute("originalUri", new String(requestUrl));

91         httpRequest.getRequestDispatcher(targetUri).forward(httpRequest, httpResponse); 

92     } 

93  

94     public void init(FilterConfig config) throws ServletException { 

95         // TODO Auto-generated method stub 

96         this.context = config.getServletContext(); 

97         /** 

98          * 获取filter的初始化参数,当需要认证的时候都会跳转到targetUri指定页面,一般都是登录页面

99 */

100         this.targetUri = config.getInitParameter("targetUri");

101     }

102 

103 

104 }

      LoginCheck.java:

1 package filter; 

2  

3 import java.io.IOException;

4 import javax.servlet.ServletException;

5 import javax.servlet.http.HttpServlet;

6 import javax.servlet.http.HttpServletRequest;

7 import javax.servlet.http.HttpServletResponse;

8 import javax.servlet.http.HttpSession; 

10 public class LoginCheck extends HttpServlet {

11     

12     private static final long serialVersionUID = -4075113258177758412L;

13    

14     protected void doPost(HttpServletRequest request,HttpServletResponse response)

15         throws IOException,ServletException{

16         String user = request.getParameter("user");

17         String pwd = request.getParameter("pwd");

18         String targetUri = request.getParameter("originalUri");

19         

20         if(!"LH123".equals(user) || !"123LH".equals(pwd)){

21             System.out.println("认证失败");

22             throw new ServletException("认证失败");

23         }

24         /**

25          * 认证成功的情况

26 */

27         HttpSession session = request.getSession();

28         session.setAttribute("passed", "true");

29         request.setAttribute("user", user);

30         request.setAttribute("pwd", pwd);

31         if(!"".equals(targetUri)){

32             /**

33              * SessionCheck中保存入的之前的请求的uri的格式为:/webTest/filter/filter3.jsp

34              * 而getRequestDispatcher这种方法传递过去的是一个相对路径,不需要再加上/webTest

35              * 这个方法可以把页面表单的值传递到另外一个页面,而不只是纯粹的跳转

36 */

37             request.getRequestDispatcher(targetUri.substring(8)).forward(request, response);

38         }else{

39             response.sendRedirect("http://127.0.0.1:8088/webTest/filter1/filter2.jsp");

40         }

41     }

42 }

       login.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@ taglib prefix ="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>  

  <head>

    <base href="<%=basePath%>">

        <title>测试filter</title>

        <meta http-equiv="pragma" content="no-cache">

        <meta http-equiv="cache-control" content="no-cache">

        <meta http-equiv="expires" content="0">

        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    

        <meta http-equiv="description" content="This is my page">

        <!--    <link rel="stylesheet" type="text/css" href="styles.css">    -->  

   </head> 

<body>    

   <c:set var = "passed" value = "passing" scope = "session">

   </c:set>

    <form action = "filter/LoginCheck" method = "post">

        <table>

            <tr>

                <th>用户账号:</th>

                <td><input type = "text" name = "user" value = ""/></td>

            </tr>

                <th>登录密码:</th>

                <td><input type = "password" name = "pwd" value = ""/></td>

                <th>

                    <input type = "hidden" name = "originalUri" value = "${requestScope.originalUri}"/>

                </th>

               <td><input type = "submit" name = "submit" value = "提交"/></td>           </tr>

        </table>

    </form>

  </body>

</html>

    filter2.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 

2 <%@ taglib prefix ="c" uri ="http://java.sun.com/jsp/jstl/core"%> 

3 <% 

4 String path = request.getContextPath(); 

5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; 

6 %> 

7  

8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 

9 <html>

10   <head>

11     <base href="<%=basePath%>">

12     

13     <title>My JSP 'filter2.jsp' starting page</title>

14     

15     <meta http-equiv="pragma" content="no-cache">

16     <meta http-equiv="cache-control" content="no-cache">

17     <meta http-equiv="expires" content="0">   

18     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

19     <meta http-equiv="description" content="This is my page">

20     <!--21     <link rel="stylesheet" type="text/css" href="styles.css">22 -->23 24   </head>25   26   <body>

27       HHHHH

28      

29   </body>

30 </html>

    filter3.jsp

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

2 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

3 <%

4 String path = request.getContextPath();

5 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

6 %>

8 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

12    

13     <title>My JSP 'filter3.jsp' starting page</title>

14    

17     <meta http-equiv="expires" content="0">    

20     <!--21     <link rel="stylesheet" type="text/css" href="styles.css">

22 -->

23

24   </head>

26   <body>

27     <c:out value="${user}"></c:out> <br>

28     <c:out value="${pwd}"></c:out> <br>

      web.xml:  

1 <?xml version="1.0" encoding="UTF-8"?>

2 <web-app version="2.5"  

3     xmlns="http://java.sun.com/xml/ns/javaee"  

4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  

6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

7     <servlet>

8         <servlet-name>LoginCheck</servlet-name>

9         <servlet-class>filter.LoginCheck</servlet-class>

10     </servlet>

11     <servlet-mapping>

12         <servlet-name>LoginCheck</servlet-name>

13         <url-pattern>/filter/LoginCheck</url-pattern>

14     </servlet-mapping>

15    

16     <filter>

17         <filter-name>SessionCheck</filter-name>

18         <filter-class>filter.SessionCheck</filter-class>

19         <init-param>

20             <param-name>targetUri</param-name>

21             <param-value>/filter1/login.jsp</param-value>

22         </init-param>

23     </filter>

24     <filter-mapping>

25         <filter-name>SessionCheck</filter-name>

26         <url-pattern>/*</url-pattern>

27     </filter-mapping>

28   <welcome-file-list>

29     <welcome-file>index.jsp</welcome-file>

30   </welcome-file-list>

31 </web-app>

      代码就是以上这些,效果:

  直接访问filter3.jsp,将会跳转到login.jsp,当通过用户认证之后就会跳转到filter3.jsp,这个功能很好用,比如csdn下载东西,你没有登录直接点击下载,系统会让你先登录,登录完了可以直接进入到下载页面,不需要再进行其他的操作。

  直接访问login.jsp,通过认证以后会跳转到默认的页面,比如csdn,直接登录的话,会跳转到csdn的首页

  注意:此例子的用户名和密码分别为 LH123和123LH,只有用这对组合才可以通过认证,才得以测试本例子。 

本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/735592,如需转载请自行联系原作者