單點登錄原理的一些理解

  在某新聞客戶端實習第二週。組裏在開發了一個內部使用的內容投放系統,系統剛開發不久,用戶登錄還是使用註冊的方式,組裏想接入公司的SSO系統,這個工作讓我來做了。首先了解了下單點登陸的原理,然後根據公司給的接口,實現了單點登錄系統的接入。下面結合自己的接入代碼,簡單闡述一下單點登陸的原理。

  單點登錄是什麼就不再闡述。首先要登錄系統A,系統A會對請求進行攔截,檢查session和cookie是否有登錄憑證。如果沒有,直接通知瀏覽器跳轉到SSO認證中心去請求登錄。在跳轉時會傳入約定好的token,backurl(用戶需要請求到A的地址)、authurl(驗證成功後通知瀏覽器重新定向請求的回調函數)。瀏覽器請求認證中心登錄時會先檢查cookie(這是瀏覽器和認證中心的cookie),如果沒有,則進入登錄頁面,登錄成功後會爲創建一個cookie並將兩者建立的sessionid放入其中,並且返回給瀏覽器一個憑證,裏面有新的token和udi、backurl。並且通知瀏覽器重定向到authurl並帶上參數(也就是那個憑證)。瀏覽器向回調函數發起請求。在回調函數裏會再次向SSO認證中心發送一個驗證(使用URLconnect),取得返回的標誌。驗證標誌成功後就可以發送請求獲取賬戶登錄的信息了,把登錄憑證存到瀏覽器和系統A之間的cookie和session中。初寫博客,感覺敘述比較凌亂。j_0064.gif相關代碼如下:

HttpServletRequest hrequest = (HttpServletRequest) request;
String url = hrequest.getRequestURI();
//判斷是否在過濾url之外  
if(url.indexOf(this.excludedPages)<0 && url.indexOf("error.html")<0){
   
   HttpServletResponse hresponse = (HttpServletResponse) response;
   HttpSession session = hrequest.getSession();
   Cookie[] cookies = hrequest.getCookies();

   if (session.getAttribute("uid") == null) {
      boolean flag = true;

      if (cookies != null) {
         for (int i = 0; i < cookies.length; i++) {
            Cookie c = cookies[i];
            if (c.getName().equalsIgnoreCase("name")) {
               String name = c.getValue();
               session.setAttribute("name", name);
            } else if (c.getName().equalsIgnoreCase("uid")) {
               String uid = c.getValue();
               session.setAttribute("uid", uid);
               flag = false;
            }
         }
      }
      log.info("sso flag=" + flag);
      if (flag) {
         String from = ComParameter.FROM;
         String key = ComParameter.KEY;
         String tm = "" + System.currentTimeMillis();

         String localIp = hrequest.getScheme() + "://"
               + hrequest.getServerName() + ":"
               + hrequest.getServerPort() + "/";
         String authurl = "";
         String backurl = "";
         if(localIp.contains("push.tongji.ifeng.com")){   //部署到工作環境中的地址
            authurl = localIp + "domainCheck";
            backurl = localIp;
         }else{
            authurl = localIp + "operate-web/domainCheck";
            backurl = localIp + "operate-web/testLogin";           //SSO認證中心返回uid和name後轉發到的地址,同時也作爲瀏覽器請求地址
         }

         String token1 = MD5Util.encode(from + key + tm + authurl + backurl);
         String redirectUrl = ComParameter.SSO_INTF_1 + "?from="
               + from + "&tm=" + tm + "&authurl=" + authurl
               + "&backurl=" + backurl + "&token1=" + token1;

         hresponse.sendRedirect(redirectUrl);
      }
      這是攔截並重定向到SSO認證中心
@Controller
public class DomainCheckController {
    @RequestMapping(value = "/domainCheck")
    public String domainCheck(HttpServletRequest hrequest, HttpServletResponse hresponse, HttpSession httpSession,String token2,String uid,String tm,String backurl) throws UnsupportedEncodingException {
        String result = userValide(token2);
        if("<ret>1</ret>".equals(result)){
            String userInfo = getUserInfo(uid,"json");
            JSONObject jsonObject = JSONObject.fromObject(userInfo);
            String name = jsonObject.getString("cn");
            httpSession.setAttribute("name",name);
            httpSession.setAttribute("uid",uid);
            Cookie nameCookie = new Cookie("name", URLEncoder.encode(name, "UTF-8"));
            nameCookie.setMaxAge(60 * 60 * 24 * 30);
            nameCookie.setPath("/");
            Cookie uidCookie = new Cookie("uid", uid);
            uidCookie.setMaxAge(60 * 60 * 24 * 30);
            uidCookie.setPath("/");
            hresponse.addCookie(nameCookie);
            hresponse.addCookie(uidCookie);
        }else {
            return "redirect:/";
        }
        hrequest.setAttribute("finalUrl",backurl);
        return "domainCheck/domain";
    }


    public static String userValide(String token2){
        String from = ComParameter.FROM;
        String key = ComParameter.KEY;
        String token3 = MD5Util.encode(from+key+token2).toLowerCase();
        String ret = HttpReqUtil.getDataFromURL(ComParameter.SSO_INTF_2+"?token3="+token3);
        return ret;
    }

    public static String getUserInfo(String uid , String fmt){
        String from = ComParameter.FROM;
        String key = ComParameter.KEY;
        String userUrl = ComParameter.SSO_INTF_3;
        long millis = Calendar.getInstance().getTimeInMillis();
        String time = "" + millis;
        String token4 = MD5Util.encode(uid+key+time+from).toLowerCase();
        String ret = HttpReqUtil.getDataFromURL(userUrl + "?uid=" + uid
                + "&tm=" + time + "&from=" + from + "&fmt=" + fmt + "&token4="
                + token4);
        return ret;
    }
    //這是回調函數

參考博客及文檔http://blog.csdn.net/cuo9958/article/details/53580466

https://apereo.github.io/cas/4.1.x/protocol/CAS-Protocol.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章