JavaWeb 使用Filter实现自动登录
思路
使用cookie存储账号、密码,使用Filter拦截,从cookie中取出账号、密码。若用户要注销|登出、不再想使用自动登录,将cookie的有效期设置为0即可。
浏览器可以查看Cookie,不能直接存储账号、密码的明文,使用Cookie存储账号、密码时需要加密,从Cookie中取出来时需要解密。
每次HTTP请求都使用Filter拦截,从Cookie中解密出账号、密码,每次都要解密,浪费时间。第一次从Cookie中解密出账号、密码后,可以将账号、密码放到session域中,会话期间直接从session中取,不必再解密。
登录页面
用户名:
密码:
登录
${requestScope.errorMsg}
EL表达式没有空指针异常,没有时返回空串。所以没有errorMsg时,${requestScope.errorMsg}也不会出错。
将登录页面设为项目初始页面
/login.jsp
处理登录表单的Servlet
1 @WebServlet("/loginServlet")
2 public class LoginServlet extends HttpServlet {
3 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
4 String user=request.getParameter("user");
5 String pwd=request.getParameter("pwd");
6
7 //连接数据库,检查是否正确
8 //......
9 if (true){
10 //放到session中
11 HttpSession session = request.getSession();
12 session.setAttribute("user",user);
13 session.setAttribute("pwd","pwd");
14
15 //将值加密后存储在Cookie中,此处略过加密
16 Cookie cookie=new Cookie("autoLogin",user+"-"+pwd);
17 //整个项目中可用
18 cookie.setPath(request.getContextPath());
19 //这个域名地址下的所有webApp都可用
20 //cookie.setPath("/");
21 cookie.setMaxAge(60*60*24*7);
22 response.addCookie(cookie);
23
24 //重定向到目标页面。request.getContextPath()获取的是当前web应用的根目录
25 response.sendRedirect(request.getContextPath()+"/index.jsp");
26 //不能这样写,这样写表示域名下的index.jsp,不是域名/web应用/index.jsp。
27 //response.sendRedirect("/index.jsp");
28 }
29 else{
30 //转发到登录页面,附加错误信息
31 request.setAttribute("errorMsg","账户名或密码错误");
32 request.getRequestDispatcher("/login").forward(request,response);
33 }
34
35 }
36
37 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
38 doPost(request,response);
39 }
40 }
首页
hello,${sessionScope.user}
Filter实现自动登录
1 @WebFilter("/*")
2 public class HandlerFilter implements Filter {
3 public void destroy() {
4 }
5
6 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
7 //统一全站编码
8 req.setCharacterEncoding("utf-8");
9 resp.setContentType("text/html;charset=utf-8");
10
11 //ServletRequest不能获取session、cookie,需要强转为HttpServletRequest
12 HttpServletRequest httpReq = (HttpServletRequest) req;
13
14 //检查session中有没有用户信息
15 HttpSession session = httpReq.getSession();
16 if (session.getAttribute("user")==null){
17 //如果session中没有,从Cookie中找autoLogin。可能是会话结束后再次访问,比如离开网站30min(session默认超时时间)后再次访问、关闭浏览器后重新打开再次访问。
18 Cookie[] cookies = httpReq.getCookies();
19 //需要先检测cookies是否为null,为null时会报空指针异常
20 if (cookies!=null){
21 for (Cookie cookie:cookies){
22 if (cookie.getName().equals("autoLogin")) {
23 //需要先解密,此处略过
24 //......
25 String[] userInfo=cookie.getValue().split("-");
26 session.setAttribute("user",userInfo[0]);
27 session.setAttribute("pwd",userInfo[1]);
28 }
29 }
30 }
31 }
32
33 chain.doFilter(req, resp);
34 }
35
36 public void init(FilterConfig config) throws ServletException {
37
38 }
39
40 }
ServletRequest不能获取session、cookie,需要强转为HttpServletRequest才可以。
处理注销 | 登出 | 不再使用自动登录 的Servlet
1 @WebServlet("/logoutServlet")
2 public class LogoutServlet extends HttpServlet {
3 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
4 //从session中移出用户信息
5 HttpSession session = request.getSession();
6 session.removeAttribute("user");
7 session.removeAttribute("pwd");
8
9 //删除Cookie,此处采用同名覆盖,也可以遍历获取,再将有效期设为0
10 Cookie cookie=new Cookie("autoLogin","");
11 cookie.setPath(request.getContextPath());
12 cookie.setMaxAge(0);
13 response.addCookie(cookie);
14 }
15
16 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
17 doPost(request,response);
18 }
19 }
获取当前WebApp的根目录:
String path1 = request.getContextPath(); //通过request对象来获取
String path2 = getServletContext().getContextPath(); //通过ServletContext对象来获取
这2种方式获取的都是相对路径。
获取当前WebApp中的某个资源在服务器上的绝对路径:
String path3 = getServletContext().getRealPath("/index.jsp"); //通过ServletContext对象来获取
就是把当前项目的根目录(绝对路径)、参数中的路径拼接在一起。