这一篇主要说SAML , 这货老而弥坚 !
SAML 其实算是一种格式规范 , 他的全称是安全断言标记语言(英语:Security Assertion Markup Language,简称SAML,发音sam-el)是一个基于XML的开源标准数据格式 . 而我们应用中的 SAML 是一种宏观实现 ,通过 SAML 格式来传输认证信息 .
通常情况下 , 开发人员解除到的都是 OAuth , 第一印象往往会感觉 SAML 是一个很 '古老' 的协议 , 但是接触多了就会发现 ,SAML 在一些重量级的应用里面随处可见 , 比如 老牌的Windows Server , 其中就大量使用了 SAML 认证 , 这协议确实老而弥坚 .
一句话说清楚 SAML 是什么流程 : IDP Metadata 为 SSO (Server ) 元数据 , SP Metadata 为 Client 元数据 , 元数据文件中包含其本身的认证数据 (认证地址 , 签名 , 公钥等) , Server 和 Client 互相持有对方的元数据 , 通过对方元数据中的公钥进行加密 ,通过签名校验合法性 , 再通过 认证地址进行请求或者回调 .
用一句话来解释其中的关联 : 服务端(客户端) 读取元数据信息, 使用指定的协议 , 通过绑定 , 将断言发送给对方 !
断言 (Assertions) 即信息:
断言是在 SAML 中用来描述认证的对象,其中包括一个用户在什么时间、以什么方式被认证,同时还可以包括一些扩展信息,比如用户的 Email 地址和电话等等。
协议 (Protocol) 即通信:
协议规定如何执行不同的行为。这些行为被细化成一些列的 Request 和 Response 对象,而在这些请求和相应的对象中包含了行为所特别需要的信息。比如,认证请求协议(AuthnRequest Protocol)就规定了一个 SP 如何请求去获得一个被认证的与用户。
绑定 (Binding) 即传输:
绑定定义了 SAML 信息如何使用通信协议被传输的。比如,HTTP 重定向绑定,即声明 SAML 信息将通过 HTTP 重定向消息传输;再比如 SAML SOAP 绑定,声明了通过 SOAP 来传递 SAML 消息。比如上面 AuthnRequest 就声明了 Http-POst 绑定
元数据 (MetaData):
SAML 的元数据是配置数据,其包含关于 SAML 通信各方的信息,比如通信另一方的 ID、Web Service 的 IP 地址、所支持的绑定类型以及通信中实用的密钥等等。
MeteData 文件中总共有四个层次 :
之前说了2点 , 一个是Server/Client 持有双方的元数据 , 一个元数据中包含了详细的证书,密钥信息,具体的元数据文件我们后面再说 , 这里先说说元数据里面的证书 .
可信实体包含公钥的证书会以X.509证书格式发布在metadata中,而对应的私钥则安全保存在本地。
这些密钥被用于消息层面的签名和加密,而SAML消息在传输过程中由TLS协议来进行安全交换。
阶段一 : 当IDP 拿到 SP 的请求时 , 证书的作用并不明显 , 主要有如下的作用
阶段二 : 当 SP 获取 IDP 的反馈时 , SP 会做以下几件事
//IDP MetaData 密钥相关
- signing : 签名
- encryption : 加密
//SP MetaData 密钥相关
- sign : 签名
- encryption : 加密
- ds:Signature : IDP 密钥信息
IDP Metedata 文件参考
<EntityDescriptor
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"
xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" entityID="http://127.0.0.1/samlServer/idp">
<IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.1:protocol urn:mace:shibboleth:1.0">
<Extensions>
<shibmd:Scope regexp="false">scope</shibmd:Scope>
</Extensions>
<KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>...[签名信息]...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<KeyDescriptor use="encryption">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>...[公钥信息]...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<NameIDFormat>urn:mace:shibboleth:1.0:nameIdentifier</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://127.0.0.1/samlServer/idp/profile/SAML2/POST/SLO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://127.0.0.1/samlServer/idp/profile/SAML2/POST/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://127.0.0.1/samlServer/idp/profile/SAML2/Redirect/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://127.0.0.1/sso/idp/profile/SAML2/SOAP/ECP"/>
</IDPSSODescriptor>
</EntityDescriptor>
SP Metedata 文件参考
<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_5p2k1rpmlbr0hphrontb6zwiplqac1xxpzvzdma" entityID="http://127.0.0.1:9081/mfa-client/saml/callback" validUntil="2040-05-07T14:08:50.499Z">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_5p2k1rpmlbr0hphrontb6zwiplqac1xxpzvzdma">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>GSp3lIKMQs70Q6FQYHWFhVaGKJv31AiRTuXOcyO78mk=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
...[IDP签名信息]...
</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
...[IDP公钥信息]...
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<md:Extensions xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport">
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#hmac-sha256"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#hmac-sha384"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#hmac-sha512"/>
<alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<alg:DigestMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#sha384"/>
<alg:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
</md:Extensions>
<md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol urn:oasis:names:tc:SAML:1.0:protocol urn:oasis:names:tc:SAML:1.1:protocol">
<md:Extensions xmlns:init="urn:oasis:names:tc:SAML:profiles:SSO:request-init">
<init:RequestInitiator Binding="urn:oasis:names:tc:SAML:profiles:SSO:request-init" Location="http://127.0.0.1/client/saml/callback?client_name=samlClient"/>
</md:Extensions>
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>...[签名信息]...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>...[公钥信息]...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://127.0.0.1/client/saml/callback?client_name=samlClient&logoutendpoint=true"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign" Location="http://127.0.0.1/client/saml/callback?client_name=samlClient&logoutendpoint=true"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://127.0.0.1/client/saml/callback?client_name=samlClient&logoutendpoint=true"/>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://127.0.0.1/client/saml/callback?client_name=samlClient&logoutendpoint=true"/>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://127.0.0.1/client/saml/callback?client_name=SAML2Client" index="0"/>
<md:AttributeConsumingService index="0">
<md:RequestedAttribute FriendlyName="eduPersonPrincipalName" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/>
</md:AttributeConsumingService>
</md:SPSSODescriptor>
</md:EntityDescriptor>
SAML 中有2个重要的成员 :
SAML 请求流程 :
SAML 中的成员定位
关于 IDP 和 SP 的角色定位 , 与OAuth不同 , 认证中心和资源服务被刻意的区分为了2个概念 ,在这2个概率里面 , 我一直有一个纠结 : 身份信息到底到谁手上?
关于这个其实不需要太纠结 , IDP 里面是存在身份数据的 , 同样 SP 里面也可能存在身份数据 , 通常而言 , IDP是一个认证中心 , 它认证完成后生成的credential在绝大多数下只会包含一个Username , 然后SP会拿着username 去直接使用或者获取更详细的信息
就像很多业务流程一样 , 认证后返回得仅仅是一个ID , 而具体得Userinfo 放在哪 , 按照业务去规划就行
前置条件 : 持有双方的 Metedata
参考 @ www.samltool.com/generic_sso…
之前提到了 , Metedata 中包含了 Server / Client 的访问信息 , 例如 :
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://127.0.0.1/samlServer/idp/profile/SAML2/POST/SLO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://127.0.0.1/samlServer/idp/profile/SAML2/POST/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://127.0.0.1/samlServer/idp/profile/SAML2/Redirect/SSO"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://127.0.0.1/sso/idp/profile/SAML2/SOAP/ECP"/>
其中清楚的声明了访问的地址以及访问的方式 : 例如 urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST 断言说明通过 Post 形式的请求的访问地址 ,urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect 则说明了通过 Redirect (Get) 请求时的访问地址
SAML AuthnRequest 请求格式
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_809707f0030a5d00620c9d9df97f627afe9dcc24" Version="2.0" ProviderName="SP test" IssueInstant="2014-07-16T23:52:45Z" Destination="http://idp.example.com/SSOService.php" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="http://sp.example.com/demo1/index.php?acs">
<saml:Issuer>http://sp.example.com/demo1/metadata.php</saml:Issuer>
<samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"/>
<samlp:RequestedAuthnContext Comparison="exact">
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
</samlp:RequestedAuthnContext>
</samlp:AuthnRequest>
当然实际请求是加密的 :
http://127.0.0.1/samlServer/idp/profile/SAML2/Redirect/SSO?
SAMLRequest=bM441nuRIzAjKeMM8RhegMFjZ4L4xPBHhAfHYqgnYDQnSxC++Qn5IocWuzuBGz7JQmT9C57nxjxgbFIatiqUCQN17aYrLn/mWE09C5mJMYlcV68ibEkbR/JKUQ+2u/N+mSD4/C/QvFvuB6BcJaXaz0h7NwGhHROUte6MoGJKMPE=
&RelayState=http%3A%2F%2F127.0.0.1%2FclientSaml%2Fcallback
参考 @ www.samltool.com/generic_sso…
注意 ,实际请求过程中都是加密 ,去这里可以自己解密看看 --> www.samltool.com/attributes.…
Logout Request : www.samltool.com/generic_slo…
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="ONELOGIN_21df91a89767879fc0f7df6a1490c6000c81644d" Version="2.0" IssueInstant="2014-07-18T01:13:06Z" Destination="http://idp.example.com/SingleLogoutService.php">
<saml:Issuer>http://sp.example.com/demo1/metadata.php</saml:Issuer>
<saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">ONELOGIN_f92cc1834efc0f73e9c09f482fce80037a6251e7</saml:NameID>
</samlp:LogoutRequest>
Logout Response :
<samlp:LogoutResponse xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_6c3737282f007720e736f0f4028feed8cb9b40291c" Version="2.0" IssueInstant="2014-07-18T01:13:06Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_21df91a89767879fc0f7df6a1490c6000c81644d">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
</samlp:LogoutResponse>
//Step 1 : Client → Server :
http://127.0.0.1/samlServer/idp/profile/SAML2/Redirect/SSO?SAMLRequest=....&RelayState=http%3A%2F%2F127.0.0.1%2FclientSaml%2Fcallback
// Step 2 : Server doLogin
// Step 3 : Server → callBack → Client
http://127.0.0.1/2FclientSaml/callback?SAMLRequest=....&RelayState=http%3A%2F%2F127.0.0.1%2FclientSaml%2Fcallback
就像之前说的 ,SAML 往往被一些大厂实践 , 是偏企业级的单点方式 , 一般人接触 , 第一感觉就是复杂 , 但是重量级及意味着更多的功能 ,更企业级的安全性 , 各有各的特色
Assertion :
SAML 消息(XML 文档)的一部分,它提供关于断言主题的事实(通常是关于经过身份验证的用户)。断言可以包含有关身份验证、关联属性或授权决策的信息
Artifact :
标识符,该标识符可用于从标识或使用后台通道绑定的服务提供者检索完整的 SAML 消息
Bnding :
用于传递 SAML 消息的机制。绑定分为前端通道绑定和后端通道绑定,前者使用用户的 web 浏览器进行消息传递(例如 HTTP-POST 或 HTTP-Redirect) ,后者使身份提供者和服务提供者直接通信(例如在 Artifact 绑定中使用 SOAP 调用)
Dscovery :
用于确定应该使用哪个身份提供程序来验证当前与服务提供程序交互的用户
Metadata :
描述一个或多个身份和服务提供者的文档。元数据通常包括实体标识符、公钥、端点 url、支持的绑定和配置文件以及其他功能或需求。身份和服务提供者之间的元数据交换通常是建立联合的第一步
Profile :
用于实现特定用例的协议、断言、绑定和处理指令的标准化组合,如单点登录、单点注销、发现、工件解析
Protocol :
为 SAML 消息定义格式(模式) ,用于实现特定功能,例如从 IDP 请求身份验证、执行单个注销或从 IDP 请求属性
Identity provider (IDP) 身份提供者(IDP) :
知道如何认证用户并使用联邦协议向服务提供者/中继方提供有关其身份的信息的实体
Service provider (SP) 服务供应商 :
您的应用程序与身份提供者通信,以获取与其交互的用户的信息。身份验证状态和用户属性等用户信息是以安全断言的形式提供的
Single Sign-On (SSO) 单点登录(SSO) :
允许访问多个网站的进程,而不需要重复提供身份验证所需的凭证。可以使用各种联邦协议(如 SAML、 WS-Federation、 OpenID 或 OAuth)来实现 SSO 用例。身份验证方式、用户属性、授权决策或安全令牌等信息通常作为单点登录的一部分提供给服务提供者
Single Logout (SLO) 单一登出(SLO) :
在使用单点登录访问的所有资源上处理终止身份验证会话。通常使用的技术包括将用户重定向到每个 SSO 参与者或发送注销 SOAP 消息
阅读量:1827
点赞量:0
收藏量:0