單點登陸SSO(二)認證中心登陸、驗證

單點登陸github

github:https://github.com/Handoking/Single-Sign-on

單點登陸的原理

客戶端一攔截器

認證中心代碼

這裏並沒有使用數據庫,僅僅是使用了數據結構保存了session。同時只是爲了實現兩個客戶端的登陸,所以直接驗證了用戶名和密碼。
數據結構類UserDB.class

package com.handoking.db;

import com.handoking.pojo.ClientInfoVo;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
 * @ClassName UserDB
 * @Description TODO
 * @Author Handoking
 * @Date 2019/12/27 10:00
 **/
public class UserDB {

       public  static HashSet<String> tokenSet = new HashSet<>();
       /**
        * 用戶登出地址和sessionid。map中key爲token,值爲多個客戶端的登出地址和sessionid組成的列表,比如天貓,淘寶等
        */
       public static Map<String,List<ClientInfoVo>> clientInfo=
              new HashMap<>();
}

完成登陸、驗證登陸、驗證令牌,註銷登陸。

package com.handoking.controller;

import com.handoking.db.UserDB;
import com.handoking.pojo.ClientInfoVo;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @ClassName SsoServerController
 * @Description TODO
 * @Author Handoking
 * @Date 2019/12/17 17:12
 **/

@Controller
public class SsoServerController {
    @RequestMapping("/index")
    public String index(){
        return "login";
    }
    @RequestMapping("/login")
    public String login(String userName,String passwd,HttpSession session,Model model,String redirectUrl){
        System.out.println("====================================");
        System.out.println("userName:"+userName+"\tpasswd:"+passwd);

        if("handoking".equals(userName)&&"123456".equals(passwd)){
            //用戶存在,驗證成功
            System.out.println("登陸校驗成功");
            //生成令牌
            String token = UUID.randomUUID().toString();
            System.out.println("成功生成token:"+token);
            //存到服務器本地
            session.setAttribute("token",token);
            UserDB.tokenSet.add(token);
            //返回給用戶 model和?token=傳參作用一樣,重定向到來的地方
            model.addAttribute("token",token);
            return "redirect:"+redirectUrl;
        }
        //用戶名或者密碼錯誤,重新登陸,但需要帶上從哪裏來url,登陸成功後重定向到此url
        System.out.println("用戶名或密碼錯誤");
        model.addAttribute("redirectUrl",redirectUrl);
        return "login";
    }
    @RequestMapping("/checkLogin")
    public String checkLogin(HttpSession session, String redirectUrl, Model model){
        //1.判斷有沒有全局會話 token是服務器生成
        String token = (String) session.getAttribute("token");

        if(StringUtils.isEmpty(token)){
            //如果全局會話不存在,返回登陸界面
            model.addAttribute("redirectUrl", redirectUrl);
            return "login";
        }else{
            //如果全局會話存在,那麼拿到token,重定向到來的url
            System.out.println(System.currentTimeMillis()+" 會話存在");
            model.addAttribute("token",token);
            return "redirect:"+redirectUrl;
        }
    }
    /**
     *@params  [token, clientUrl, jessionId]
     *@return  java.lang.String
     *@author  Handoking
     *@date  2019/12/30 16:12
     * 驗證token的同時,將退出登錄的clientUrl和當前session id存到認證中心
     */
    @RequestMapping("/verify")
    @ResponseBody
    public String verify(String token,String clientUrl,String jessionId){
        if (UserDB.tokenSet.contains(token)){
            System.out.println(System.currentTimeMillis()+" 服務器存在當前token,驗證成功");
            //將clientUrl和sessionId等用戶信息存入認證中心
            List<ClientInfoVo> clientList = UserDB.clientInfo.computeIfAbsent(token, k -> new ArrayList<>());
      //      以上寫法等同於下面的寫法
//            List<ClientInfoVo> clientList = UserDB.clientInfo.get(token);
//            if (clientList == null){
//                //第一次判斷一定爲空
//                clientList = new ArrayList<>();
//                UserDB.clientInfo.put(token,clientList);
//            }

            ClientInfoVo vo = new ClientInfoVo();
            vo.setClientUrl(clientUrl);
            vo.setJessionId(jessionId);
            clientList.add(vo);
            System.out.println("客戶端的登出地址和jession已經添加到list");
            return "true";
        }
        return "false";
    }
    /**
     *@params  [session]
     *@return  java.lang.String
     *@author  Handoking
     *@date  2019/12/30 19:32
     * 服務器端註銷,使用監聽器
     */
    @RequestMapping("/logOut")
    public String logOut(HttpSession session){
        //手動銷燬全局會話,前提是session還沒有自動註銷的。
        session.invalidate();
        //通知子系統註銷,調用所有的子系統,並銷燬子系統的session
        //使用監聽器,監聽session是否過期
        //銷燬session時調用監聽器
        return "login";
    }

}
發佈了131 篇原創文章 · 獲贊 74 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章