您的位置:首页 > 其它

单点登录(SSO)的一点思考

2010-09-21 14:38 169 查看
这几天稍微关注了一下SOA方面的资料,抛开webservice性能问题不说,就当当这验证问题就让人头疼

考虑到几点:

1、调用方法的时候把用户名密码都带上,显然不太理想,每次都需要传递密码也不太那个安全,而且每次都要验证用户名和密码正确性,麻烦

2、不把用户名和密码带上,怎么知道这次来连接的是谁呢?

由上面2个问题,突然考虑到单点登录,我只登录一次,只把用户和密码传递一次不就行了嘛,听起来不错,可是问题又来了,你下次调用的时候

我怎么知道你已经登录并且有权限呢?于是考虑到 在第一次登录成功的时候返回给你一串加密的字符串,以后你每次来调用我方法的时候,带上

这个已经验证过的字符串不就可以了嘛,听起来还是不错,可是每次调用方法的时候都必须带上这串字符串岂不是还是很累赘?

暂时不考虑那么多了,就怎么先实现以下吧,希望高手们多多给建议。。。

稍微画了下图:



客户端首先需要调用Login方法,去验证服务器(SSO Server)验证,成功后携带ssokey返回,SsoServer保存登陆成功的用户。

客户端调用应用服务器方法时必须携带ssokey,以便应用服务器验证用户是否登陆。

关于 Application Server 和 SSO Server 如何通讯,我想有多种方式可以解决,比如说 Remoting/WebService/Wcf 等。。。。。

当然我们也可以把验证服务器和应用程序服务器放到一台服务器上。。。。

下面就可以通过具体代码来实现了:

为了方便,这里我采用webservice方式来通讯,我建立2个webserviice

  1、SSOServer.asmx

  2、MyApplicationService.asmx

这里 使我的应用也以 webservice的形式发布(SOA嘛。。)

  1、SSOServer.asmx代码如下,其中只包括了 Login(登陆) 和 IsLogin(验证是否已经登录)方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

namespace SSOTest
{
/// <summary>
/// SSOServer 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
[System.Web.Script.Services.ScriptService]
public class SSOServer : System.Web.Services.WebService
{
//key:用户名  value:ssokey
public static Dictionary<string, string> onlineUser = new Dictionary<string, string>();

[WebMethod]
public string Login(string userName, string passWord)
{
//验证用户名密码
if ("huwei".Equals(userName))
{
//
if (onlineUser.ContainsKey(userName))
{
onlineUser.Remove(userName);
}

//成功后生成新的ssokey并返回
string ssokey = Guid.NewGuid().ToString();

onlineUser.Add(userName,ssokey);
return ssokey;
}
return "";
}

//判断是否已经登录
[WebMethod]
public bool IsLogin(string ssokey)
{
return onlineUser.ContainsValue(ssokey);
}
}
}


这里只是简单的测试一下,实际上还有很多需要考虑的因素,比如说 你的 ssokey 保存的时间,总不至于ssokey一直保存着吧

  2、MyApplicationService.asmx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;

namespace SSOTest
{
/// <summary>
/// MyApplicationService 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
[System.Web.Script.Services.ScriptService]
public class MyApplicationService : System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat=ResponseFormat.Json,UseHttpGet=true)]
public string TestMethod(string ssokey)
{
SSOServer server = new SSOServer();
if (server.IsLogin(ssokey))
{
Console.WriteLine("恭喜!认证成功!");

try
{
MySqlHelper helper = new MySqlHelper();
helper.Execute("insert into Friends (firstname,lastname,age,email) values ('fff','lll',22,'aaeeee')");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}

return "恭喜!认证成功!";
}
else
{
Console.WriteLine("抱歉!认证失败!请重新登录");
return "抱歉!认证失败!请重新登录";
}
}
}
}


  3、前台测试一下,采用jquery ajax 来登录,并执行方法

    在 Default.aspx 页面中加入如下脚本

<script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript">
var ssokey = "";

function doLogin(userName, passWord) {
$.ajax({
url: "http://localhost:11143/SSOServer.asmx/Login",
type: "post",
data: "username=" + userName + "&passWord=" + passWord,
success: function (data) {
//alert($(data).find("string").text());
ssokey = $(data).find("string").text();
alert("登录成功");
}
});
}

function doJSON() {
$.ajax({
url: "http://localhost:11143/MyApplicationService.asmx/TestMethod",
data: {ssokey:"'" + ssokey + "'"},
dataType: "JSON",
contentType: "application/json; charset=utf-8",
success: function (data) {
alert(data);
}
});
}
</script>


这里写了 2个方法,一个是登陆方法,首先必须要先登陆获得 ssokey,然后才能成功的执行 方法

总结:

这种方式我觉得还是不太好,毕竟每次执行方法都要检测ssokey是否已经登录,肯定存在浪费的情况,不知道各位高手有没有更好的解决方案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: