asp.net 实现一个简单CAS Server

项目代码下载 http://files.cnblogs.com/mobile/cas_demo.zip

CAS的原理,参加 http://blog.csdn.net/HuDon/archive/2007/02/01/1499815.aspx

根据下图所示,我们需要实现CASClient端得"拦截器",我们通过HttpModule实现,服务端需要两个页面,一个是登陆界面,一个途中第5步通过token获取的用户信息的页面或者ashx。

1、客户端的代码和配置

新建一个类,代码如下:

1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.SessionState;
 6 using System.Text;
 7 using System.Net;
 8 using System.IO;
 9 
10 namespace client
11 {
12     public class filter : IHttpModule, IRequiresSessionState
13     {
14         string login_url = "http://localhost:10888/Default.aspx";
15         string verify_url = "http://localhost:10888/method.ashx";
16 
17         public void Dispose()
18         {
19 
20         }
21 
22         public void Init(HttpApplication context)
23         {
24             context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);            
25         }
26 
27         void context_PreRequestHandlerExecute(object sender, EventArgs e)
28         {
29             try
30             {
31                 HttpApplication ha = (HttpApplication)sender;
32 
33                 HttpRequest Request = ha.Context.Request;
34                 HttpResponse Response = ha.Context.Response;
35 
36                 string continue_url = Request.Url.AbsoluteUri;
37                 string path = ha.Context.Request.Url.AbsolutePath;
38 
39 
40                 string token = Request["token"];
41                 if (!string.IsNullOrEmpty(token)) //这次请求是从CAS登陆后跳转而来
42                 {
43                     //使用POST连接CAS的method.ashx,通过token获取用户信息
44                     string res = Post(verify_url, "token=" + token, "utf-8");
45                     ha.Session["user"] = res;
46                     Response.Redirect(ha.Session["continue_url"].ToString());
47                 }
48 
49                 if ((ha.Session == null) || (ha.Session["user"] == null)) //通过Session判断登陆状态
50                 {
51                     ha.Session["continue_url"] = continue_url;
52                     ha.Response.Redirect(login_url + "?continute_url=" + continue_url); //去登陆cas页面
53                 }
54             }
55             catch (Exception ex)
56             {
57                 (sender as HttpApplication).Response.Write(ex.Message);
58             }
59         }
60 
61         public string Post(string postUrl, string postData, string chars_set)
62         {
63             Encoding encoding = Encoding.GetEncoding(chars_set);
64             HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(postUrl);
65             CookieContainer cookieContainer = new CookieContainer();
66             Request.CookieContainer = cookieContainer;
67             Request.Method = "POST";
68             Request.ContentType = "application/x-www-form-urlencoded";
69             Request.AllowAutoRedirect = true;
70             byte[] postdata = encoding.GetBytes(postData);
71             using (Stream newStream = Request.GetRequestStream())
72             {
73                 newStream.Write(postdata, 0, postdata.Length);
74             }
75             using (HttpWebResponse response = (HttpWebResponse)Request.GetResponse())
76             {
77                 using (Stream stream = response.GetResponseStream())
78                 {
79                     using (StreamReader reader = new StreamReader(stream, encoding, true))
80                     {
81                         return reader.ReadToEnd();
82                     }
83                 }
84             }
85         }
86     }
87 }
88

需要在拦截所有请求,在web.config中配置

<httpModules>

..............

<add name="LoginMoudle" type="client.filter"/> //type由于写在项目中只需要namespace.class方式,如果放在dll中,需要加",dll文件名"

</httpModules>

2、CAS服务端代码

1)登陆页面

1     <form id="form1" runat="server" method="post" action="login.ashx">
2     <div>Login ID:<input type="text" id="loginid" name="loginid" /></div>
3     <div>Password:<input type="password" id="password" name="password" /></div>
4     <div><input type="hidden" id="continute_url" name="continute_url" value="<%=Request["continute_url"] %>"/></div>
5     <div><input type="submit" value="Login" /></div>
6     </form

其中continute_url是filer传来的

2)登陆代码

1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Services;
 6 
 7 namespace cas
 8 {
 9     [WebService(Namespace = "http://tempuri.org/")]
10     [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
11     public class login : IHttpHandler
12     {
13 
14         public void ProcessRequest(HttpContext context)
15         {
16             HttpRequest Request = context.Request;
17             string loginid = Request["loginid"];
18             string password = Request["password"];
19             string continute_url = Request["continute_url"];
20 
21             //用户登录验证.
22 
23             string token = DateTime.Now.Ticks.ToString();//登陆成功后 生成token方法,自己考虑,需唯一
24             //缓存token
25             context.Application[token] = "用户名"; //实际使用中存放用户信息类的实例
26             //转移
27             context.Response.Redirect(continute_url + "?token=" + token);
28         }
29 
30         public bool IsReusable
31         {
32             get
33             {
34                 return false;
35             }
36         }
37     }
38 }
39

3)CAS端获取用户信息的页面

1 public class method : IHttpHandler
 2     {
 3 
 4         public void ProcessRequest(HttpContext context)
 5         {
 6             string token = context.Request["token"];
 7            
 8             string user = context.Application[token].ToString(); //获取token映射的用户信息
 9             context.Application.Remove(token); //删除缓存的token,token一次有效
10             
11             context.Response.Write(user);//实际使用中可能需要返回xml或者json格式的用户信息
12         }
13 
14         public bool IsReusable
15         {
16             get
17             {
18                 return false;
19             }
20         }
21

运行过程基本是这样的:用户访问网站,filer首先拦截判断session中用户信息,如果不为空放行,否则,转到CAS登陆界面,登陆界面登陆后,返回地址中夹带token.

网站后台通过get或者post方法使用token去获取用户信息。

最后网站程序通过Session["user"]获取用户信息,无需关心登陆的实现,这样我们就实现了一个简单单点登录系统了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏kwcode

ASP.NET 实现Base64文件流下载PDF

因为业务需要调用接口获取的是 Base64文件流 需要提供给客户下载PDF文档 源码部分借鉴网上,具体地址忘记了。 //Base64文件流 ...

4285
来自专栏ZKEASOFT

纸壳CMS的插件加载机制

纸壳CMS是基于插件化设计的,可以通过扩展插件来实现不同的功能。如何通过插件来扩展,可以参考这篇文章:

1122
来自专栏圣杰的专栏

ABP入门系列(16)——通过webapi与系统进行交互

源码路径:Github-LearningMpaAbp 1. 引言 上一节我们讲解了如何创建微信公众号模块,这一节我们就继续跟进,来讲一讲公众号模块如何与系统...

1.6K6
来自专栏菩提树下的杨过

img标签的src=""会引起的Page_Load多次执行

今天看见园子里有人因img的src为空导致session丢失,详情见http://www.cnblogs.com/kyneblog/archive/2009/0...

21910
来自专栏程序员的SOD蜜

常见.NET功能代码汇总 (3) 33,彻底关闭Excel进程

33,彻底关闭Excel进程 .NET中使用Excel属于使用非托管资源,使用完成后一般都要用GC回收资源,但是,调用GC的位置不正确,Excel进程可能无法彻...

2146
来自专栏恰童鞋骚年

自己动手模拟开发一个简单的Web服务器

开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此...

2483
来自专栏pangguoming

C#开发微信公众平台-就这么简单(附Demo)

  最近公司在做微信开发,其实就是接口开发,网上找了很多资料,当然园友也写了很多教程,但都是理论说了一大堆,实用指导或代码很少。如果你自己仔细研究下,其实就那么...

2061
来自专栏古时的风筝

ASP.NET-自定义HttpModule与HttpHandler

在之前的ASP.NET是如何在IIS下工作的这篇文章中介绍了ASP.NET与IIS配合工作的机制,在http请求经过一系列处理后,最后到达ASP.NET管道中...

3058
来自专栏蘑菇先生的技术笔记

c#实现redis客户端(一)

2946
来自专栏菩提树下的杨过

FckEditor 2.6.4升级手记

说是升级,其实就是把原来的版本替换掉 1.先到www.fckeditor.net上下载fckeditor(html/js包)和fckeditor.net(专用...

3027

扫码关注云+社区

领取腾讯云代金券