.net core实践系列之SSO-跨域实现
前言
接着上篇的《.net core实践系列之SSO-同域实现》,这次来聊聊SSO跨域的实现方式。这次虽说是.net core实践,但是核心点使用jquery居多。
建议看这篇文章的朋友可以先看上篇《.net core实践系列之SSO-同域实现》做一个SSO大概了解。
源码地址:https://github.com/SkyChenSky/Core.SSO.git
效果图

知识点回顾
实现原则
只要统一Token的产生和校验方式,无论授权与认证的在哪(认证系统或业务系统),也无论用户信息存储在哪(浏览器、服务器),其实都可以实现单点登录的效果
实现关键点
- Token的生成
- Token的共享
- Token校验
Token共享复杂度
- 同域
- 跨域
Token认证方式
- 业务系统自认证
- 转发给认证中心认证
同源策略
所有支持JavaScript 的浏览器,都必须遵守的安全策略,也是浏览器最基本的安全功能。
如果没有处理过发起跨域请求,就算服务器接收到了,响应成功了浏览器也是会拦截的。
同源
指域名,协议,端口相同
目的
浏览器为了阻止恶意脚本获取不同源上的的敏感信息。
跨域请求
然而在实际情况下跨域请求的场景也是存在的,解决方案有两种:
- JSONP
- 响应头设置“Access-Control-Allow-Origin”
Cookie
Cookie的读取和发送也是必须遵循同源策略的。
虽说请求共享可以设置响应头Access-Control-Allow-Credentials、Access-Control-Allow-Origin与Ajax请求属性xhrFields: {withCredentials: true}进行解决,但是!
就算响应头有set-cookie浏览器也是无法正常保存的。
SSO跨域解决方式
针对cookie认证,我唯一能找到的解决方案就是跳转页面。
具体步骤:
- 认证中心登录成功后,请求登录中心接口获得token
- 携带token逐个跳转到业务系统的中转页面。
- 跳转完成后,返回到认证中心登录页面进行引导。
PS:如果哪位朋友有更加好的方案,可以及时与我沟通,非常感谢
实现方式
登录中心授权
<script>
$(function () {
$("#submit").click(function () {
$("#postForm").ajaxSubmit(function (result) {
if (result.success) {
var token = getToken();
if (token) {
var authorizeHostArray = new Array(
"http://www.web1.com/Token/Authorization",
"http://www.web2.com/Token/Authorization"
);
var authorizeHostParams = "";
authorizeHostArray.forEach(function (item) {
authorizeHostParams += "&hostAuthorization=" + item;
});
window.location.href = authorizeHostArray[0] + "?token=" + token + authorizeHostParams;
}
} else {
alert(result.msg);
}
});
}); function getToken() {
var token = null;
$.ajax({
url: "/api/Token",
type: "GET",
async: false,
success: function (d) {
token = d.token;
}
});
return token;
}
});
</script>
业务系统Token保存与注销
public class TokenController : Controller
{
public static TokenCookieOptions CookieOptions { get; set; } public IActionResult Authorization(string token, List<string> hostAuthorization = null)
{
if (CookieOptions == null || string.IsNullOrEmpty(token))
return BadRequest(); HttpContext.Response.Cookies.Append(CookieOptions.Name, token, new CookieOptions
{
Domain = CookieOptions.Domain,
Expires = DateTimeOffset.UtcNow.Add(CookieOptions.Expires),
HttpOnly = CookieOptions.HttpOnly,
IsEssential = CookieOptions.IsEssential,
MaxAge = CookieOptions.MaxAge,
Path = CookieOptions.Path,
SameSite = CookieOptions.SameSite
}); if (hostAuthorization.Any())
hostAuthorization = hostAuthorization.Where(a => !a.Contains(HttpContext.Request.Host.Host)).ToList(); if (!hostAuthorization.Any())
hostAuthorization = new List<string> { "http://www.sso.com" }; return View(new TokenViewData
{
Token = token,
HostAuthorization = hostAuthorization
});
} public IActionResult Logout(List<string> hostAuthorization = null)
{
HttpContext.Response.Cookies.Delete(CookieOptions.Name); if (hostAuthorization.Any())
hostAuthorization = hostAuthorization.Where(a => !a.Contains(HttpContext.Request.Host.Host)).ToList(); if (!hostAuthorization.Any())
hostAuthorization = new List<string> { "http://www.sso.com" }; return View(new TokenViewData
{
HostAuthorization = hostAuthorization
});
}
}
Token生成与认证
与同域的实现的方式一致。
生成与认证是一对的,与之对应的就是AES的加密与解密。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.Name = "Token";
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes();
options.LoginPath = "/Account/Login";
options.LogoutPath = "/Account/Logout";
options.SlidingExpiration = true;
//options.DataProtectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@"D:\sso\key"));
options.TicketDataFormat = new TicketDataFormat(new AesDataProtector());
TokenController.CookieName = options.Cookie.Name;
});
}
internal class AesDataProtector : IDataProtector
{
private const string Key = "!@#13487"; public IDataProtector CreateProtector(string purpose)
{
return this;
} public byte[] Protect(byte[] plaintext)
{
return AESHelper.Encrypt(plaintext, Key);
} public byte[] Unprotect(byte[] protectedData)
{
return AESHelper.Decrypt(protectedData, Key);
}
}
业务系统自主认证的方式,对于系统的代码复用率与维护性都很低。如果想进行转发到认证系统进行认证,可以对[Authorize]进行重写。
大致思路是:
访问业务系统时,由自定义的[Authorize]进行拦截
获取到Token设置到请求头进行HttpPost到认证系统提供的/api/token/Authentication接口
响应给业务系统如果是成功则继续访问,如果是失败则401或者跳转到登录页。
结尾
最近事情比较多,demo与文章写的比较仓促,如果朋友们有更好的实现方式与建议,麻烦在下面评论反馈给我,先在此感谢。
.net core实践系列之SSO-跨域实现的更多相关文章
- .net core实践系列之短信服务-目录
前言 经过两周多的业余时间,终于把该系列的文章写完了.第一次写系列,可能部分关键点并没有覆盖到,如果有疑问的朋友可以随时反馈给我.另外也感谢在我发布文章时给予我方案建议与反馈源码BUG的朋友们.下面是 ...
- .net core实践系列之短信服务-架构设计
前言 上篇<.net core实践系列之短信服务-为什么选择.net core(开篇)>简单的介绍了(水了一篇).net core.这次针对短信服务的架构设计和技术栈的简析. 源码地址:h ...
- .net core实践系列之短信服务-Sikiro.SMS.Api服务的实现
前言 上篇<.net core实践系列之短信服务-架构设计>介绍了我对短信服务的架构设计,同时针对场景解析了我的设计理念.本篇继续讲解Api服务的实现过程. 源码地址:https://gi ...
- .net core实践系列之短信服务-Api的SDK的实现与测试
前言 上一篇<.net core实践系列之短信服务-Sikiro.SMS.Api服务的实现>讲解了API的设计与实现,本篇主要讲解编写接口的SDK编写还有API的测试. 或许有些人会认为, ...
- .net core实践系列之短信服务-Sikiro.SMS.Bus服务的实现
前言 前两篇<.net core实践系列之短信服务-Sikiro.SMS.Api服务的实现>.<.net core实践系列之短信服务-Api的SDK的实现与测试>分别讲解了AP ...
- .net core实践系列之SSO-同域实现
前言 SSO的系列还是以.Net Core作为实践例子与大家分享,SSO在Web方面复杂度分同域与跨域.本篇先分享同域的设计与实现,跨域将在下篇与大家分享. 如有需要调试demo的,可把SSO项目部署 ...
- asp.net core 系列之允许跨域访问-1(Enable Cross-Origin Requests:CORS)
接上篇的允许跨域 4.CORS 策略(Policy)的选项 这里讲解Policy可以设置的选项: 设置允许的访问源 设置允许的HTTP methods 设置允许的请求头(request header) ...
- asp.net core 系列之允许跨域访问2之测试跨域(Enable Cross-Origin Requests:CORS)
这一节主要讲如何测试跨域问题 你可以直接在官网下载示例代码,也可以自己写,我这里直接使用官网样例进行演示 样例代码下载: Cors 一.提供服务方,这里使用的是API 1.创建一个API项目.或者直接 ...
- 来吧学学.Net Core之登录认证与跨域资源使用
序言 学习core登录认证与跨域资源共享是越不过的砍,所以我在学习中同样也遇到啦这两个问题,今天我们就用示例来演示下使用下这2个技术点吧. 本篇主要内容如下: 1.展示一个登录认证的简单示例 2.跨域 ...
随机推荐
- python base64 decode incorrect padding错误解决方法
个人觉得原因应该是不同的语言/base64库编码规则不太统一的问题. python中base64串的长度需为4的整数倍,故对长度不为4整数倍的base64串需要用"='补足 如下代码: da ...
- go 利用orm简单实现接口分布式锁
在开发中有些敏感接口,例如用户余额提现接口,需要考虑在并发情况下接口是否会发生问题.如果用户将自己的多条提现请求同时发送到服务器,代码能否扛得住呢?一旦没做锁,那么就真的会给用户多次提现,给公司带来损 ...
- CsQuery中文编码乱码问题
一.问题描述 InnerHTML 中文显示为Модель 二.解决方法 在初始化CQ对象前,先设置执行以下语句: CsQuery.Config.HtmlEncoder = CsQuery.HtmlEn ...
- MyBatis笔记----mybatis分页
mybatis版本3.4以下 结构 spring-mvc.xml <?xml version="1.0" encoding="UTF-8"?> &l ...
- [20190213]测试服务端打开那些端口.txt
[20190213]测试服务端打开那些端口.txt --//前几天测试使用发送信息到/dev/tcp/ip_address/port,测试端口是否打开.写简单写一个脚本验证看看. $ seq 1 65 ...
- Windows Server 2016-管理站点复制(一)
可以使用Active Directory站点和服务管理单元来管理实现站点间复制拓扑的特定于站点的对象.这些对象存储在Active Directory域服务 (AD DS) 的站点容器中.同一个站点内的 ...
- windows下安装consul
Consul 是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件, 由 HashiCorp 公司用 Go 语言开发, 基于 Mozilla Public License 2.0 的协议进行 ...
- C# -- 使用XmlDocument或XDocument创建xml文件
使用XmlDocument或XDocument创建xml文件 需引用:System.Xml; System.Xml.Linq; 1.使用XmlDocument创建xml(入门案例) static vo ...
- VMare Workstation 安装Ubuntu 虚拟机教程
1.VMware Workstation,选择左上角文件—新建虚拟机,开始新建一台虚拟机,典型的话许多配置为默认设置,因此,这里我选择自定义安装: 2.机硬件兼容性选择默认即可: 3.客户操作系统选择 ...
- LeetCode算法题-Binary Tree Paths(Java实现-3种解法)
这是悦乐书的第199次更新,第206篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第62题(顺位题号是257).给定二叉树,返回所有根到叶路径.例如: 输入: 1 / \ ...