SSM博客实战(9)-拦截器验证权限和登录与注销的实现

本文将介绍通过拦截器验证权限和后台登录与注销。

拦截器的作用在于,比如我们输入 xxx.com/admin 发起请求进入 网站后台或者其他后台页面。我们的拦截器会在 Controller  调用之前进行拦截,至于什么拦截,由我们来写。比如,判断用户是否登录(可以通过 session 判断),如果没有登录,我们让它跳转到登录页面。

一、拦截器的基本使用

1、新建一个 拦截器

SecurityInterceptor.java

  1. package com.liuyanzhao.blog.Interceptor;
  2. import org.springframework.web.servlet.HandlerInterceptor;
  3. import org.springframework.web.servlet.ModelAndView;
  4. import javax.servlet.http.HttpServletRequest;
  5. import javax.servlet.http.HttpServletResponse;
  6. public class SecurityInterceptor implements HandlerInterceptor {
  7.     @Override
  8.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
  9.         System.out.println("SecurityInterceptor...preHandle...");
  10.         //这里可以根据session的用户来判断角色的权限,根据权限来转发不同的页面
  11.         if(request.getSession().getAttribute("userId") == null) {
  12.             request.getRequestDispatcher("/login").forward(request,response);
  13.             return false;
  14.         }
  15.         return true;
  16.     }
  17.     @Override
  18.     public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  19.     }
  20.     @Override
  21.     public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  22.     }
  23. }

判断是否有 userId 这个session,如果没有(或者过期了)转发到登录页面

 

2、配置 springmvc.xml

通过使用 mvc:interceptors 标签来声明需要加入到SpringMVC拦截器链中的拦截器。

  1. <mvc:interceptors>
  2.       <mvc:interceptor>
  3.           <mvc:mapping path="/admin"/>
  4.           <bean class="com.liuyanzhao.blog.Interceptor.SecurityInterceptor"/>
  5.       </mvc:interceptor>
  6.       <mvc:interceptor>
  7.           <mvc:mapping path="/admin/**"/>
  8.           <bean class="com.liuyanzhao.blog.Interceptor.SecurityInterceptor"/>
  9.       </mvc:interceptor>
  10.   </mvc:interceptors>

 

只需两步,我们已经能成功拦截  /admin 和其其前缀的如 /admin/article 等其他所有路径啦。

 

二、登录实现

登录主要是验证该用户是否存在,密码是否正确。然后添加 session 和页面跳转

1、登录表单

login.jsp

  1. <%
  2.          String username = "";
  3.          String password = "";
  4.          //获取当前站点的所有Cookie
  5.          Cookie[] cookies = request.getCookies();
  6.          for (int i = 0; i < cookies.length; i++) {//对cookies中的数据进行遍历,找到用户名、密码的数据
  7.              if ("username".equals(cookies[i].getName())) {
  8.                     username = cookies[i].getValue();
  9.              } else if ("password".equals(cookies[i].getName())) {
  10.                  password = cookies[i].getValue();
  11.              }
  12.          }
  13. %>
  14.     <form name="loginForm" id="loginForm"  method="post">
  15.                 <input type="text" name="username" id="user_login"
  16.                            class="input" value="<%=username%>" size="20" required/></label>
  17.                 <input type="password" name="password" id="user_pass"
  18.                            class="input" value="<%=password%>" size="20" required/>
  19.                  <input name="rememberme" type="checkbox" id="rememberme" value="1" /> 记住密码
  20.                 <input type="button" name="wp-submit" id="submit-btn" class="button button-primary button-large" value="登录" />
  21.     </form>

为了代码简洁,这里去掉了多余的标签和属性。我这里是扒了 wordpress 的登录页面,这里也用到了 cookie 。

SSM博客实战(9)-拦截器验证权限和登录与注销的实现

注意:这里的 form 表单里没有 action 属性,最终发送数据通过 ajax 。同样,也没有 submit 按钮,为了防止 ajax+form+submit 导致 success 里无法页面跳转。

 

2、js 代码

  1. <%--登录验证--%>
  2.  $("#submit-btn").click(function () {
  3.      var user = $("#user_login").val();
  4.      var password = $("#user_pass").val();
  5.      if(user=="") {
  6.          alert("用户名不可为空!");
  7.      } else if(password==""){
  8.          alert("密码不可为空!");
  9.      } else {
  10.          $.ajax({
  11.              async: false,//同步,待请求完毕后再执行后面的代码
  12.              type: "POST",
  13.              url: '${pageContext.request.contextPath}/loginVerify',
  14.              contentType: "application/x-www-form-urlencoded; charset=utf-8",
  15.              data: $("#loginForm").serialize(),
  16.              dataType: "json",
  17.              success: function (data) {
  18.                  if(data.code==0) {
  19.                      alert(data.msg);
  20.                  } else {
  21.                      window.location.href="${pageContext.request.contextPath}/admin";
  22.                  }
  23.              },
  24.              error: function () {
  25.                  alert("数据获取失败")
  26.              }
  27.          })
  28.      }
  29.  })

这里 ajax 使用同步,防止出现后台没有返回值,就执行了后面的js代码,进而出现 ajax 执行 error:function() 里的代码。数据类型使用 json,当然也可以使用 text,只不过 text 只能 返回普通的字符串。

最后,如果验证通过,将跳转到 xxx.com/admin 页面(当然后台需要加入session,否则拦截器会拦截)。

 

3、控制器代码

  1. //登录页面显示
  2.     @RequestMapping("/login")
  3.     public ModelAndView loginView() {
  4.         ModelAndView modelAndView = new ModelAndView();
  5.         modelAndView.setViewName("/Admin/login");
  6.         return modelAndView;
  7.     }
  8.     //登录验证
  9.     @RequestMapping(value = "/loginVerify",method = RequestMethod.POST)
  10.     @ResponseBody
  11.     public String loginVerify(HttpServletRequest request, HttpServletResponse response) throws Exception {
  12.         Map<String, Object> map = new HashMap<String, Object>();
  13.         String username = request.getParameter("username");
  14.         String password = request.getParameter("password");
  15.         String rememberme = request.getParameter("rememberme");
  16.         UserCustom userCustom = userService.getUserByNameOrEmail(username);
  17.         if(userCustom==null) {
  18.             map.put("code",0);
  19.             map.put("msg","用户名无效!");
  20.         } else if(!userCustom.getUserPass().equals(password)) {
  21.             map.put("code",0);
  22.             map.put("msg","密码错误!");
  23.         } else {
  24.             //登录成功
  25.             map.put("code",1);
  26.             map.put("msg","");
  27.             //添加session
  28.             request.getSession().setAttribute("user", userCustom);
  29.             //添加cookie
  30.             if(rememberme!=null) {
  31.                 //创建两个Cookie对象
  32.                 Cookie nameCookie = new Cookie("username", username);
  33.                 //设置Cookie的有效期为3天
  34.                 nameCookie.setMaxAge(60 * 60 * 24 * 3);
  35.                 Cookie pwdCookie = new Cookie("password", password);
  36.                 pwdCookie.setMaxAge(60 * 60 * 24 * 3);
  37.                 response.addCookie(nameCookie);
  38.                 response.addCookie(pwdCookie);
  39.             }
  40.         }
  41.         String result = new JSONObject(map).toString();
  42.         return result;
  43.     }

这里登录验证方法内,getUserByNameOrEmail() 方法用来从数据库里查找是否有该用户(用户名或者邮箱)。如果有,而且密码正确,添加一条 session,要和拦截器里写的一致哦。并将信息添加到 Map 中,然后转成 JSON 数据,这里需要导入 对应JSON 的jar 哦。

  1. <dependency>
  2.   <groupId>org.json</groupId>
  3.   <artifactId>json</artifactId>
  4.   <version>20170516</version>
  5. </dependency>

 

4、Service 和 DAO

这里就不贴 Service 和 Dao 的代码了,主要就是根据 字符串查找用户的操作啦。

 

 

三、注销实现

注销就比较简单了,清除 session 就行了。

1、jsp 页面

  1. <a href="${pageContext.request.contextPath}/admin/logout">退了</a>

 

2、控制器代码

  1. //退出登录
  2.    @RequestMapping(value = "/admin/logout")
  3.    public String logout(HttpSession session) throws Exception {
  4.        session.removeAttribute("userId");
  5.        session.invalidate();
  6.        return "redirect:/login";
  7.    }

 

本来准备录制GIF效果图,但是苦于图片太大就不上传了。

  • 微信
  • 赶快加我聊天吧
  • weinxin
  • 博客交流群
  • 海纳百川,大家来水
  • weinxin
言曌

发表评论

:?::razz::sad::evil::!::smile::oops::grin::eek::shock::???::cool::lol::mad::twisted::roll::wink::idea::arrow::neutral::cry::mrgreen: