Junky's IT Notebook

统计

留言簿(8)

积分与排名

WebSphere Studio

阅读排行榜

评论排行榜

关于单点认证的一个简单实现(结合Form认证)(转)

最近在做一个无敌长的项目,从五一休假做到十一休假!有一个需求就是要求单点登陆(SSO)


解决思路如下:

请求认证的网站 :用一个HttpModule 截取所有请求,判断HttpContext.User是不是Null,如为空,判断Url上是不是有签名过的认证信息, 如果有,判断签名信息是否有效,如果有效,将认证信息写入Cookie中.认证完成

认证的网站: 如果登陆页Url中有要求认证的网址,判断用户是不是已授权,如果已授权,将用户信息签名,写入Url中

二个网站都使用的Form认证

代码
请求认证网站,HttpMoudle如下

  1using System;
  2using System.Collections.Generic;
  3using System.Text;
  4using System.Web;
  5using System.Web.Security;
  6using System.Security.Principal;
  7
  8namespace SSO
  9{
 10    /// <summary>
 11    /// 单点认证的HttpModule
 12    /// </summary>

 13    public class SSOAuthenticateHttpModule:IHttpModule
 14    {
 15        public String ModuleName
 16        {
 17            get return "SSOAuthenticateHttpModule"; }
 18        }

 19
 20        IHttpModule 成员
135    }

136}

137


SSOClient 是一个助手类主要负责认证签名,设置Cookie,从Url中分离出认证信息
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Security.Cryptography;
 5using System.Security.Principal;
 6using System.Web;
 7using System.Web.Security;
 8
 9
10namespace SSO
11{
12    internal class SSOClient
13    {
14        private static String PublicKey = "公钥信息,我用的是RSA,你可以自己生成"
15        internal static bool ValidataData(String data, String signedData)
16        {
17            try
18            {
19                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(512);
20                RSA.FromXmlString(PublicKey);
21
22                UnicodeEncoding ByteConverter = new UnicodeEncoding();
23
24                SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
25                return RSA.VerifyData(ByteConverter.GetBytes(data), new SHA1CryptoServiceProvider(), Convert.FromBase64String(signedData));
26            }

27            catch
28            {
29                return false;
30            }

31
32        }

33
34        internal static String SplitUserName(String data)
35        {
36            UnicodeEncoding ByteConverter = new UnicodeEncoding();
37
38            return data.Split('$')[0];
39        }

40
41
42        internal static String SplitToken(String data)
43        {
44            UnicodeEncoding ByteConverter = new UnicodeEncoding();
45
46
47            return data.Split('$')[1];
48        }

49
50        internal static void SetAuthCookie(HttpContext context, String userName, String token, bool isPersistent)
51        {
52
53
54            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
55            1// Ticket version
56            userName, // Username associated with ticket
57            DateTime.Now, // Date/time issued
58            DateTime.Now.AddMinutes(30), // Date/time to expire
59            isPersistent, // "true" for a persistent user cookie
60            token, // User-data, in this case the roles
61            FormsAuthentication.FormsCookiePath);// Path cookie valid for
62
63            // Encrypt the cookie using the machine key for secure transport
64            string hash = FormsAuthentication.Encrypt(ticket);
65
66            HttpCookie cookie = new HttpCookie(
67               FormsAuthentication.FormsCookieName, // Name of auth cookie
68               hash); // Hashed ticket
69
70            // Set the cookie's expiration time to the tickets expiration time
71            if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;
72
73            // Add the cookie to the list for outgoing response
74            context.Response.Cookies.Add(cookie);
75        }

76
77
78    }

79}

80

被认证的网站的WebConfig文件
<?xml version="1.0"?>
<!-- 
    注意: 除了手动编辑此文件以外,您还可以使用 
    Web 管理工具来配置应用程序的设置。可以使用 Visual Studio 中的
     “网站”->“Asp.Net 配置”选项。
    设置和注释的完整列表在 
    machine.config.comments 中,该文件通常位于 
    \Windows\Microsoft.Net\Framework\v2.x\Config 中
-->
<configuration>
    
<appSettings/>
    
<connectionStrings/>
    
<system.web>
        
<!-- 
            设置 compilation debug="true" 将调试符号插入
            已编译的页面中。但由于这会 
            影响性能,因此只在开发过程中将此值 
            设置为 true。
        
-->
        
<compilation debug="true">
            
<assemblies>
                
<add assembly="System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/></assemblies></compilation>
        
<!--
            通过 <authentication> 节可以配置 ASP.NET 使用的 
            安全身份验证模式,
            以标识传入的用户。 
        
-->
    
<authentication mode="Forms">
      
<forms loginUrl="http://localhost/TestSSOServer/Default.aspx" name=".ASPXFORMSAUTH" protection="All" path="/" timeout="30" enableCrossAppRedirects="true"/>
    
</authentication>
      
        
<!--<authorization>
            <deny users="?"/>
        </authorization>
-->
            
        
        
<httpModules>
            
<add name="SSOAuthenticateHttpModule" type="SSO.SSOAuthenticateHttpModule"/>
        
</httpModules>
        
<!--
            如果在执行请求的过程中出现未处理的错误,
            则通过 <customErrors> 节可以配置相应的处理步骤。具体说来,
            开发人员通过该节可以配置
            要显示的 html 错误页
            以代替错误堆栈跟踪。

        <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
            <error statusCode="403" redirect="NoAccess.htm" />
            <error statusCode="404" redirect="FileNotFound.htm" />
        </customErrors>
        
-->
    
</system.web>
</configuration>


认证网站,比较简单,有一个负责登陆的页面,我就在上面放了一个Button和一个TxtBox
 1using System;
 2using System.Data;
 3using System.Configuration;
 4using System.Web;
 5using System.Web.Security;
 6using System.Web.UI;
 7using System.Web.UI.WebControls;
 8using System.Web.UI.WebControls.WebParts;
 9using System.Web.UI.HtmlControls;
10
11public partial class _Default : System.Web.UI.Page 
12{
13    protected void Page_Load(object sender, EventArgs e)
14    {
15        if (!Page.IsPostBack)
16        {   
17            //判断是不是已认证通过--这里只是简单写了,具体你是怎么认证的,就怎么写
18            if (Request.IsAuthenticated)
19            {
20                //回到请求认证的网站;
21                ReturnUrl();
22            }

23        
24        }

25        
26    }

27    protected void Button1_Click(object sender, EventArgs e)
28    {
29        FormsAuthentication.SetAuthCookie(TextBox1.Text,false);
30
31        ReturnUrl();
32
33    }

34
35    /// <summary>
36    /// 取得认证信息
37    /// </summary>
38    /// <returns></returns>

39    private String getAuthInfo()
40    {
41        String userName = User.Identity.Name;
42        String tokenValue = "这是一些附加信息,你可以写入角色什么的";//在我的应用中,我写的是一个Token
43        String time = System.DateTime.Now.ToString();
44
45        String v = userName + "$" + tokenValue ;
46
47        return v;
48
49
50    }

51
52    /// <summary>
53    /// 返回请求认证的网站
54    /// </summary>

55    private void ReturnUrl()
56    {
57     
58        String strUrl = Request.QueryString["site"];
59
60        if (String.IsNullOrEmpty(strUrl))
61        {
62            return;
63        }

64
65        strUrl = HttpUtility.UrlDecode(strUrl);
66
67        //取得认证信息
68        String data = getAuthInfo();
69
70        写入签名信息
84
85        Response.Redirect(strUrl);
86  
87    
88    }

89}

90


认证助手类
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.Security.Cryptography;
 5
 6namespace SSO
 7{
 8    public class SSOServer
 9    {
10        private static String PrivateKey = "私钥信息,这个很重要,";
11        
12        /// <summary>
13        /// 签 名用户信息
14        /// </summary>
15        /// <param name="data"></param>
16        /// <returns></returns>

17        public static String SignatueData(String data)
18        {
19            try
20            {
21                //Create a UnicodeEncoder to convert between byte array and string.
22                UnicodeEncoding ByteConverter = new UnicodeEncoding();
23
24                byte[] dataToSignatue = ByteConverter.GetBytes(data);
25
26                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(512);
27                RSA.FromXmlString(PrivateKey);
28
29                String SignadString = Convert.ToBase64String(RSA.SignData(dataToSignatue, new SHA1CryptoServiceProvider()));
30                return SignadString;
31
32            }

33            catch
34            {
35                return String.Empty;
36            }

37        }

38        //把一个字符串Base64编码
39        public static String Base64String(String data)
40        {
41            try
42            {
43                //Create a UnicodeEncoder to convert between byte array and string.
44                UnicodeEncoding ByteConverter = new UnicodeEncoding();
45
46                byte[] dataToBase = ByteConverter.GetBytes(data);
47
48                return Convert.ToBase64String(dataToBase);
49            }

50            catch
51            {
52                return String.Empty;
53            }

54            
55        }

56
57    }

58}

59

posted on 2007-05-21 09:32 junky 阅读(523) 评论(0)  编辑  收藏 所属分类: security


只有注册用户登录后才能发表评论。


网站导航: