后端實現用戶登錄驗證和同時只能允許一個用戶登錄


之前網上看了一些文章又是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能被用戶看見


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM