在某新闻客户端实习第二周。组里在开发了一个内部使用的内容投放系统,系统刚开发不久,用户登录还是使用注册的方式,组里想接入公司的SSO系统,这个工作让我来做了。首先了解了下单点登陆的原理,然后根据公司给的接口,实现了单点登录系统的接入。下面结合自己的接入代码,简单阐述一下单点登陆的原理。
单点登录是什么就不再阐述。首先要登录系统A,系统A会对请求进行拦截,检查session和cookie是否有登录凭证。如果没有,直接通知浏览器跳转到SSO认证中心去请求登录。在跳转时会传入约定好的token,backurl(用户需要请求到A的地址)、authurl(验证成功后通知浏览器重新定向请求的回调函数)。浏览器请求认证中心登录时会先检查cookie(这是浏览器和认证中心的cookie),如果没有,则进入登录页面,登录成功后会为创建一个cookie并将两者建立的sessionid放入其中,并且返回给浏览器一个凭证,里面有新的token和udi、backurl。并且通知浏览器重定向到authurl并带上参数(也就是那个凭证)。浏览器向回调函数发起请求。在回调函数里会再次向SSO认证中心发送一个验证(使用URLconnect),取得返回的标志。验证标志成功后就可以发送请求获取账户登录的信息了,把登录凭证存到浏览器和系统A之间的cookie和session中。初写博客,感觉叙述比较凌乱。相关代码如下:
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
转载于:https://blog.51cto.com/blithe/1961379