单点登录原理的一些理解

  在某新闻客户端实习第二周。组里在开发了一个内部使用的内容投放系统,系统刚开发不久,用户登录还是使用注册的方式,组里想接入公司的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

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