ASP.NET MVC框架下实现SSO单点登录,核心思路是搭建独立的认证中心,所有业务系统的登录请求都先转发到认证中心处理,验证通过后生成统一票据,业务系统通过校验票据完成用户身份确认,从而实现一次登录多系统通用的效果。

SSO单点登录核心流程
整个单点登录体系包含三个核心角色:认证中心、业务系统A、业务系统B,完整交互流程如下:
- 用户访问业务系统A,未登录则跳转到认证中心登录页
- 用户在认证中心提交账号密码,验证通过后生成加密票据,同时记录用户登录状态
- 认证中心携带票据跳转回业务系统A,业务系统A校验票据合法性,校验通过则创建本地会话,用户登录成功
- 用户后续访问业务系统B,未登录则同样跳转到认证中心,此时认证中心检测到用户已登录,直接生成新票据跳转回业务系统B,业务系统B校验通过后完成登录
认证中心核心实现
登录验证接口
认证中心负责接收用户登录请求,验证账号密码并生成票据,核心代码如下:
// 认证中心登录控制器
public class AuthController : Controller
{
// 登录页面
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
// 登录提交处理
[HttpPost]
public ActionResult Login(string userName, string password, string returnUrl)
{
// 实际项目中替换为真实的账号验证逻辑
if (userName == "test" && password == "123456")
{
// 生成票据,使用用户ID+时间戳+随机字符加密
string token = GenerateToken(userName);
// 记录登录状态到缓存,设置过期时间30分钟
CacheHelper.Set(token, userName, 30);
// 跳转回业务系统,携带票据
if (!string.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl + "?token=" + token);
}
return Content("登录成功");
}
ViewBag.Error = "账号或密码错误";
return View();
}
// 生成加密票据
private string GenerateToken(string userName)
{
string raw = userName + "_" + DateTime.Now.Ticks + "_" + Guid.NewGuid().ToString("N");
// 使用AES加密,实际项目中需要妥善保管密钥
return AESEncryptHelper.Encrypt(raw);
}
}
票据校验接口
业务系统拿到票据后,会调用认证中心的校验接口确认票据合法性,认证中心实现如下:
// 票据校验接口
public ActionResult ValidateToken(string token)
{
if (string.IsNullOrEmpty(token))
{
return Json(new { success = false, msg = "票据为空" }, JsonRequestBehavior.AllowGet);
}
// 从缓存中获取票据对应的用户信息
object userInfo = CacheHelper.Get(token);
if (userInfo == null)
{
return Json(new { success = false, msg = "票据已过期或不存在" }, JsonRequestBehavior.AllowGet);
}
return Json(new { success = true, userName = userInfo.ToString() }, JsonRequestBehavior.AllowGet);
}
业务系统接入实现
登录拦截器
业务系统需要添加全局拦截器,判断用户是否登录,未登录则跳转到认证中心,代码如下:
// 登录拦截器
public class SSOFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// 判断当前用户是否已登录
if (filterContext.HttpContext.Session["UserName"] == null)
{
// 获取当前请求地址,作为登录后的回调地址
string currentUrl = filterContext.HttpContext.Request.Url.ToString();
// 认证中心地址,实际项目中配置在配置文件
string authCenterUrl = "http://sso.ipipp.com/Auth/Login?returnUrl=" + HttpUtility.UrlEncode(currentUrl);
filterContext.Result = new RedirectResult(authCenterUrl);
}
base.OnActionExecuting(filterContext);
}
}
票据回调处理
认证中心跳转回业务系统时,会携带token参数,业务系统需要校验token并创建本地会话:
// 业务系统首页控制器
public class HomeController : Controller
{
// 回调地址,处理认证中心返回的票据
public ActionResult Index(string token)
{
if (!string.IsNullOrEmpty(token))
{
// 调用认证中心校验接口,实际项目中使用HttpClient请求
string validateUrl = "http://sso.ipipp.com/Auth/ValidateToken?token=" + token;
string result = HttpClientHelper.Get(validateUrl);
var jsonResult = JsonConvert.DeserializeObject<JObject>(result);
if (jsonResult["success"].Value<bool>())
{
// 校验通过,创建本地会话
Session["UserName"] = jsonResult["userName"].ToString();
// 可以把用户信息存入本地缓存,减少后续校验请求
return View();
}
else
{
ViewBag.Error = "票据校验失败";
}
}
// 已登录直接返回视图
if (Session["UserName"] != null)
{
return View();
}
return RedirectToAction("Login");
}
}
关键配置与注意事项
- 认证中心与业务系统需要统一加密密钥,保证票据生成与解析的一致性
- 票据缓存过期时间需要与业务系统会话过期时间匹配,避免票据有效但本地会话失效的问题
- 生产环境需要开启HTTPS,避免票据在传输过程中被窃取
- 可以在票据中加入来源系统标识,限制票据只能被指定业务系统使用,提升安全性
- 如果用户注销,需要同时通知认证中心清除全局登录状态,避免单点注销不彻底的问题
单点注销实现
单点注销需要用户退出时,同时清除认证中心的登录状态和所有业务系统的本地会话,核心逻辑如下:
// 业务系统注销接口
public ActionResult Logout()
{
// 清除本地会话
Session.Clear();
// 获取当前用户的票据,实际项目中需要从会话或缓存中获取
string token = Session["Token"] as string;
if (!string.IsNullOrEmpty(token))
{
// 调用认证中心注销接口,清除全局状态
string logoutUrl = "http://sso.ipipp.com/Auth/Logout?token=" + token;
HttpClientHelper.Get(logoutUrl);
}
return RedirectToAction("Index");
}
// 认证中心注销接口
public ActionResult Logout(string token)
{
if (!string.IsNullOrEmpty(token))
{
CacheHelper.Remove(token);
}
return Content("注销成功");
}
ASP.NET_MVCSSO单点登录身份认证修改时间:2026-07-10 19:30:15