后端实现用户登录验证和同时只能允许一个用户登录

之前网上看了一些文章又是redis又是Cookie的感觉没有必要

现实中遇见大神好多,但是网上的文章写的却不咋地,可能大神很忙,没时间写吧。

废话不多说

思路:

用户登录校验思路:

1.将登录的用户信息放在session中

2.每次请求过来的数据对他进行校验看session中是否存在用户信息,没有就返回首页

用户校验+只允许一个用户登录该系统思路:

1.将登录的用户信息放在session中

2.每次请求过来的数据对他进行校验:

  2.1看session中是否存在用户信息,没有就返回首页

  2.2如果有看他的session中保存的用户的sessionId是否和数据库中当前用户的sessionId相同

    相同:通过他的请求

    不同:注销请求过来的session并返回首页,提醒用户,该账户在其他地方登录。

代码实现:

1.用户登录

这里的用户名和密码是要前端获取的,我这样写只是为了好测试。

setMaxInactiveInterval()是设置session过期时间的,单位秒
    /**
     *用户登录
     */
    @GetMapping("/login")
    public String login(HttpServletRequest request){
        HttpSession session = request.getSession();
//       User user=new User();
//       user.setName("张三");
//       user.setPassword("123456");
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        User user1 = new User();
        user1.setName("张三");
        user1.setPassword("123456");
        wrapper.setEntity(user1);
        User one = userService.getOne(wrapper);
        if(one==null){
            return "登陆失败";
        }
         one.setSessionId(session.getId());
        //更新登录状态
        userService.saveOrUpdate(one);
       session.setAttribute("user",one);

//        session.setMaxInactiveInterval(10);
//        setMaxInactiveInterval(int   i)
//        i的单位是秒。
//        如果设置的值为零或负数,则表示会话将永远不会超时。常用于设置当前会话时间。
        return "ok";
    }
View Code

2.用户校验

这里校验分2中:

       1.判断用户是否登录

       2.判断当前的请求中用户是否在其他地方已经登陆了

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.could.demo.entity.User;
import com.could.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


/**
 * AUTHOR :zhao
 * 日期:2020/3/20 18:48
 * 用户登录校验
 * HandlerInterceptorAdapter相当于一个Filter拦截器,但是这个颗粒度更细,能使用Spring的@Autowired注入。
 */
@Component
public class HandlerInterceptorConfigurer extends HandlerInterceptorAdapter {
    /**
     *preHandle在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制等处理;
     * postHandle在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView;
     * afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面),可以根据ex是否为null判断是否发生了异常,进行日志记录;
     */

    @Autowired
    private UserService userService;

    /**
     * 判断用户是否登录 通过session 实现
     *  @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        if (user != null){
            QueryWrapper<User> wrapper = new QueryWrapper<>();
            User user1 = new User();
            user1.setName(user.getName());
            wrapper.setEntity(user1);
            User one = userService.getOne(wrapper);
            /**
             * 登录过的用户分2中
             * 1.登录被挤下去的
             * 2.刚登陆的
             */
            //1.
            /**
             * 如果是登录页面让进来
             * 如果当前请求的sessionId和存在user表中的id不一样给他说该账号在其他地方已经登陆了
             */
            //如果当前的用户sessionid不等于数据库中的sessionid
            if(!session.getId().equals(one.getSessionId())){
                session.invalidate();
                // 跳转登录
                String url = "/index";
                //表示该用户没有登录,输出 出错信息
//                PrintWriter out = null;
//                try{
//                    response.setHeader("Content-type", "text/html;charset=UTF-8");
//                    out = response.getWriter();
//                    out.append("{\"success\":false,\"code\":SOS,\"msg\":\"您的账号在其他地方登录请您重新登陆\"}");
////                    response.sendRedirect(url);
//                }catch(IOException e){
//                    e.printStackTrace();
//                }finally {
//                    if (out != null) {
//                        out.close();
//                    }
//                }
                response.sendRedirect(url);
                return false;
            }

            //2.
//            QueryWrapper<User> wrapper = new QueryWrapper<>();
//            User user1 = new User();
//            user1.setName(user.getName());
//            wrapper.setEntity(user1);
//            User one = userService.getOne(wrapper);
//            if(one!=null&&user.getPassword().equals(one.getPassword())){

                return true;
//            }
        }
        // 跳转登录
        String url = "/index";
        response.sendRedirect(url);
        return false;
    }
}
View Code

3.用户注销

invalidate()方法清空session对象         removeAttribute() 清空session对象中的变量

 @GetMapping("/logout")
    public String add(HttpServletRequest request, HttpServletResponse response,HttpSession session1){
        //System.out.println(session1.getId());
        session1.invalidate();
//        session1.removeAttribute("user");  //清空Session变量
        return "注销成功";
    }

4.返回首页

getSession(false) 判断当前的session是否存在,存在返回当前对象不存在返回null。
   /**
     *首页
     */
    @GetMapping("/index")
    public String index(HttpServletRequest request){
        if(request.getSession(false)==null){
            return "您的账号已退出或在其他地方登录,请重新登陆";
        }
        return "首页";
        }

好了收工。

 缺点:session保存东西越小越好,毕竟占服务器内存!

 sessionId能被用户看见

posted @ 2020-03-21 19:07  Angry-rookie  阅读(2142)  评论(0)    收藏  举报