none
基于Webservice的SSO单点登录系统思路求解答 RRS feed

  • 问题

  • 各位老师好:

        最近公司的几个系统要做一下整合,专门有一台服务器做为Webservice使用,提供身份认证等功能,在一般情况下使用还是可以的,但我想更进一步,做到SSO单点登录方式,如果在浏览器中已经登录了A系统,则输入B系统的地址时,也可自动进入,这二天也上网查了很多资料,但很多问题还是没办法想通,现将遇到的问题陈述一下,还请各位老师帮忙。

    一、各服务器无域名或部分用户不使用域名。因为是内网应用,大家都已经习惯了使用IP地址登录,后来公司设置了一台DNS服务器,但大家还是直接使用收藏夹中的地址,也就是IP地址登录;服务器的网段也不完全相同,部分在10.123.22.*网段,部分在10.123.33.*,部分在10.234.44.*之类

    二、设有三个应用,分别是A、B、C,在三台不同的服务器上,提供统一身份的服务器为S服务器,用户客户端U,现假设系统均为B/S系统,下一步可能会考虑扩大到C/S系统;

    三、U计算机登录A应用,A应用向S服务器发webservice报文,S服务器通过验证后写cookies,;此时U计算机再次登录B应用,B应用向S服务器请求查看用户状态,S服务器读cookies,返回已有U用户登录(这一步失败了,代码如下:)

        <WebMethod(Description:="验证用户登录信息")> _
        Public Function UserLogin(ByVal LogonInfo As String) As XmlDocument
            '验证过程略过
            Dim cookie As New HttpCookie("mysite")
            cookie.Values("uid") = Sid
            cookie.Values("uname") = Suname
            cookie.Expires = DateTime.MinValue
            HttpContext.Current.Response.Cookies.Add(cookie)
            Return HttpContext.Current.Response.Cookies("mysite")("uname") & "登录成功!"
        End Function


        <WebMethod(Description:="验证用户是否已经登录")> _
    Public Function UserStatus(ByVal StatusInfo As String) As XmlDocument
            '前面的过程略过
            '如果用户未留下Cookies
            If String.IsNullOrEmpty(HttpContext.Current.Response.Cookies("mysite")("uid")) Then
                Return "用户未登录过!"
            End If
            Return HttpContext.Current.Response.Cookies("mysite")("uname") & "已登录!"
        End Function

    首先这个cookies写到哪儿去了?还在S服务器上,还是写到A服务器上了?我原以为会写到U客户机上,后来发现好像不是这样,http是无状态的,会不会调用Webservice结束后,cookies就被删除了呢?

    如果在A服务器的应用中,将返回的uid加到B、C应用的URL中,是没有问题的,但如果是客户在浏览器中手动输入怎么处理呢?

    我还想过在数据库中建一个表,用户登录时写入最后活动时间、IP地址,然后有请求时看一下IP地址和最后活动时间来判断是否是本机,这种的话还可以很好的让C/S系统使用,但又有一个问题,内网用户一般来说IP地址是固定的,但万一有使用了小路由的,数台计算机都是同一IP地址怎么判断呢?

    比如QQ,在本机上登录了一个QQ,使用它的服务(QQ官网或可以使用QQ帐号登录的论坛等),它都能准确的知道你是谁,不会因为你在网吧与数十上百人用同一个IP地址就判断错误,无论用户打开的是IE还是Chrome,都能获取已登录的用户,它的原理是如何实现的呢?

    还有,如果U客户端与S服务器之间有防火墙,只能A、B、C服务器访问S服务器,又该如何处理呢?是使用cookies好,还是使用数据库方式好?

    希望老师们给予指点,提供思路或参考文档,谢谢。


    2012年11月19日 6:31

答案

全部回复

  • 不建议用IP,因为IP会动态随机分配,不是固定的。

    我的看法:

    1)你弄一个User表,每一个User应该有一个固定的Id(类似QQ号),用这个号+口令登陆系统。

    2)User表中应该有一个State状态(默认0,表示尚未登陆)。

    3)任何一种方式登录(验证用户Id+口令成功之后),设置State为1(已经登陆)。这样的话其它机器一旦在登陆,则判断State是否1,是1的话不允许再登陆。

    4)这里考虑一点的是:如果Web方式不是通过点击“注销”方式而是直接点击右上角“叉”关闭,那么你应该使用该js或者jQuery方法,利用WebService或者WCF方法把当前用户注销掉:

    $(window).unload(function(){
      alert("Goodbye!");
    });

    2012年11月20日 5:24
  • 谢谢老师,不过我的单点登录的意思并不是说不允许在其他地方登录,而是说在同一台计算机,登录一个系统后,其他系统就不用再输入用户名和密码,可以自动进入。现在需要考虑的问题是如何让其他系统知道此计算机上已经登录了一个用户。
    2012年11月20日 5:58
  • 谢谢老师,不过我的单点登录的意思并不是说不允许在其他地方登录,而是说在同一台计算机,登录一个系统后,其他系统就不用再输入用户名和密码,可以自动进入。现在需要考虑的问题是如何让其他系统知道此计算机上已经登录了一个用户。
    是的,我这种做法也可以保证你已经登录了一个用户——因为一个用户登录,User表的State状态就是True了,其它只要判断状态即可。
    2012年11月21日 2:22
  • 但B系统是如何知道我在本计算机上已经登录并且登录的是U用户呢?因为服务器使用的都是IP地址访问,没办法使用跨子域cookies的方式,而S服务器是A系统通过webservice方式访问的,cookies也写不到本地,甚至U用户的PC还无法访问S服务器。
    2012年11月21日 3:14
  • 你不是只要一个时间只能有一个用户登录么?你还想知道是那个机器在登录?
    2012年11月21日 10:15
  • 你好,

    目前流行的做法是使用OAuth 或者WS-Federation Passive Profile提供SSO.可以使用WIF来做一个SIS,用WS-Federation Passive Profile来实现.这个都是有例子可以参考的. 建议参考:

    http://msdn.microsoft.com/en-us/magazine/ff872350.aspx

    http://www.microsoft.com/en-us/download/details.aspx?id=14347


    Allen Chen [MSFT]
    MSDN Community Support | Feedback to us


    2012年11月26日 3:09
    版主