實現第三方系統單點登錄


思路舉例:

  以QQ為例:pc端QQ界面中所有的第三方軟件系統,以QQ郵箱舉例,

  QQ中成功登陸,從而點擊QQ郵箱可以直接打開網頁進入郵箱並無需登錄

  在這里就使用了單點登錄,QQ郵箱就是QQ信任的第三方系統,雙方達成協議,

  雙方需要把加密方式,和加密串達成一致。當然如果公司是中型企業,加密串后期

  會有運維去和客戶溝通。 接下來貼代碼。

代碼實例:

  首先設置一個加密串,這里是在properties文件中定義,嫌麻煩可以直接在接口中定義靜態私有屬性

  #秘鑰
  AtsecretKey=Activity0CoJUm6123456789
  

  
 //引入秘鑰 
@Value("${AtsecretKey}") private String AtsecretKey; /** * 根據請求的參數加密判斷 * @param currTime * @param idcardno * @param type * @param signature * @return */ @RequestMapping("/token") @ResponseBody public ResultEntity checkToken(String currTime,String idcardno,String type,String signature ){ ResultEntity resultEntity=new ResultEntity(); Map<String,String> desMap=new HashMap<>(); desMap.put("currTime",currTime); desMap.put("idcardno",idcardno); desMap.put("type",type); StringBuffer sb = new StringBuffer(); StringBuffer sbkey = new StringBuffer(); Set es = desMap.entrySet(); //所有參與傳參的參數按照accsii排序(升序) Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); Object v = entry.getValue(); //空值不傳遞,不參與簽名組串 if(null != v && !"".equals(v)) { sb.append(v); sbkey.append(v); } } sbkey=sbkey.append(AtsecretKey); System.out.println("字符串:"+sbkey.toString()); String md5Item = MD5Util.md5(sbkey.toString()); System.out.println("MD5加密值:"+md5Item); System.out.println(sb.toString()+"sign="+md5Item); //拼字符串后加密 if (md5Item.equals(signature)){ long nowTime=System.currentTimeMillis(); if (((nowTime - Long.parseLong(currTime))*1.0 /(1000 * 60))>20){ resultEntity.setState(HttpCode.FAILED); resultEntity.setRetMessage("認證時間超時"); return resultEntity; } DESPlus desPlus=new DESPlus(); String strJson=JsonUtils.toJson(desMap); String desMessage=desPlus.encrypt(strJson); resultEntity.setState(HttpCode.SUCCESS); resultEntity.setMessage("認證通過"); resultEntity.setResult(desMessage); return resultEntity; } resultEntity.setState(HttpCode.FAILED); resultEntity.setMessage("請求失敗"); return resultEntity; }

 

代碼解釋:
  ResultEntity:工具類,用於封裝json數據,返回頁面響應請求
  currTime:時間戳
  idcardno:身份證號
  type:設備類型手機或者pc  
   signature:加密串,

  
Map<String,String> desMap=new HashMap<>();
        desMap.put("currTime",currTime);
        desMap.put("idcardno",idcardno);
        desMap.put("type",type);

將參數放入map中,方便接下來排序

StringBuffer sb = new StringBuffer();
        StringBuffer sbkey = new StringBuffer();
        Set es = desMap.entrySet();  //所有參與傳參的參數按照accsii排序(升序)
        Iterator it = es.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            //空值不傳遞,不參與簽名組串
            if(null != v && !"".equals(v)) {
                sb.append(v);
                sbkey.append(v);
            }
sbkey=sbkey.append(AtsecretKey);
System.out.println("字符串:"+sbkey.toString());
String md5Item = MD5Util.md5(sbkey.toString());
System.out.println("MD5加密值:"+md5Item);
System.out.println(sb.toString()+"sign="+md5Item);
 
        
 
        
這里需要用的accsii排序,accsii詳細解釋可以去查一下
通過迭代器迭代排序,並且清除空值,然后將值封裝好key,value
另外在排序后的值后面加上加密串(
AtsecretKey),生成加密簽名
接着使用md5工具類加密參數
//拼字符串后加密
        if (md5Item.equals(signature)){
            long nowTime=System.currentTimeMillis();
            if (((nowTime - Long.parseLong(currTime))*1.0 /(1000 * 60))>20){
                resultEntity.setState(HttpCode.FAILED);
                resultEntity.setRetMessage("認證時間超時");
                return resultEntity;
            }
            DESPlus desPlus=new DESPlus();
            String strJson=JsonUtils.toJson(desMap);
            String desMessage=desPlus.encrypt(strJson);
            resultEntity.setState(HttpCode.SUCCESS);
            resultEntity.setMessage("認證通過");
            resultEntity.setResult(desMessage);
            return resultEntity;
        }
        resultEntity.setState(HttpCode.FAILED);
        resultEntity.setMessage("請求失敗");
        return resultEntity;

 

這里將加密后得參數和第三方傳的signature判斷是否相同,如果相同證明是信任的第三方,
才可以執行下面的操作
拿到第三方發送的時間戳(currTime)並且獲取當前的時間戳,設置時間戳過期時間,
這里是防止惡意攻擊,不可能第二天還可以拿着前一天的請求來訪問,
成功設置后在使用DES加密,因為des是可以解密的,將之前map的參數在一次用des加密,
轉換成json數據,讓后放進工具類返回請求,第三方拿到參數,再次帶着參數來訪問接口,

/**
     * 根據第三方的Token來處理單點登錄
     * @param request
     * @param session
     * @return
     */
    @RequestMapping("/IntoLogin")
    public String intoLogin( HttpServletRequest request, HttpSession session,String token){
        //拿到token解密
        DESPlus desPlus=new DESPlus();
        try {
            String decToken=desPlus.decrypt(token);
            Map<String,String>map=JsonUtils.fromJson(decToken,Map.class);
            ReaderEntity record = new ReaderEntity();
            record.setCardno(map.get("cardno"));
            record.setIdcardno(map.get("idcardno"));
            String type=map.get("type");
            String currTime=map.get("currTime");
            ReaderSession readerSession =null;
            long nowTime=System.currentTimeMillis();
            //判斷過期時長,請求時間超過20分鍾就無效
            if (((nowTime - Long.parseLong(currTime))*1.0 /(1000 * 60))<20) {
                readerSession = readerService.login(record, request);
            }
            if(readerSession!=null) {
                    session.setAttribute("readerInfo", readerSession);
                    UnionUserSession unionUserSession = new UnionUserSession();
                    unionUserSession.setUserType(2);
                    unionUserSession.setUserId(readerSession.getReader().getRecno().toString());
                    request.getSession().setAttribute(UnionUserSession.SESSION_ID, unionUserSession);
                    //這里判斷密鑰類型是pc還是移動端,登錄后將跳轉不同頁面
                    if (type.equals("0")){
                        return "/pc/index";
                    }else{
                        return "/mobile/activity/home";
                        }
                    }
        }catch (Exception e) {
            return "/pc/index";
        }
        return "/pc/index";
    }

這里的代碼不多做解釋,應該能看得懂,其實這種單點登錄思路要屢清楚

為了安全性參數一定是要加密的,特別是加密協議,密鑰是雙方知道的,第三方

請求的時候也是帶着參數可已經加密的參數來求接口,如果我們拿着他們的參數排序

在加上密鑰以后加密,發現加密后的字符串一致說明是我們信任的第三方,

這里單點登錄要用兩個接口,所以我們需要使用des加密后返回給他們再次請求,

一個接口負責判斷是否第三方,另一個接口登錄,

這里只提供接口供第三方訪問。



 
        

 


免責聲明!

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



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