b/s类型的项目我们可以使用前文的方法很容易就做了集成,如果是c/s类型的应用呢?还有些比较特殊b/s类型的项目,既希望能够集成sso,又希望能保留自己的登录画面和本地用户,这里就需要用到官方提供的REST协议。
这一段尝试过程很顺利,官方的文档虽然简单到不行不过没啥大毛病,笔者尝试用C#实现了一下一次通过,小伙伴们可以很轻松的参照C#代码码出其他语言的代码,因为只是做几次简单的http请求。
private void btnClick_Click(object sender, EventArgs e)
{
//获取TGT
string tid = HtmlPost("https://sso.xxx.com/cas/v1/tickets", "username=zhangsan&password=1", "POST");
//返回的格式是html,需要解析抽取TGT
Regex regex = new Regex("(?<=tickets/).+?(?=\")", RegexOptions.Singleline);
tid = regex.Match(tid).Value;
//获取服务(客户端惟一url,可以捏造但必须惟一)凭据,有效期1.8秒
string data = "service=" + HttpUtility.UrlEncode("https://www.xxx.com");
string ticket = HtmlPost("https://sso.xxx.com/cas/v1/tickets/" + tid, data, "POST");
//凭借客户端惟一url和它的凭据获取用户凭据
string content = HtmlGet("https://sso.xxx.com/cas/p3/serviceValidate?service=https://www.xxx.com&ticket=" + ticket);
//返回的content是xml格式的,需要自行解析
//注销凭据
string result = HtmlPost("https://sso.xxx.com/cas/v1/tickets/" + tid, "", "DELETE");
}
string HtmlPost(string url, string data, string method)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = method;
byte[] form = Encoding.Default.GetBytes(data);
req.ContentLength = form.Length;
req.GetRequestStream().Write(form, 0, form.Length);
req.GetRequestStream().Close();
HttpWebResponse rep = (HttpWebResponse)req.GetResponse();
StreamReader sr = new StreamReader(rep.GetResponseStream());
string str = sr.ReadToEnd();
sr.Close();
rep.GetResponseStream().Close();
return str;
}
string HtmlGet(string url)
{
WebClient wc = new WebClient();
wc.Encoding = Encoding.UTF8;
return wc.DownloadString(url);
}