zoukankan      html  css  js  c++  java
  • 单点登录用户认证管理的相关概念

    1.1 token

      token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。

      Token 即使是在计算机领域中也有不同的定义,这里我们说的 token,是指 访问资源 的凭据。例如当你调用 Google API 时,需要带上有效 token 来表明你请求的 合法性。这个 TokenGoogle 给你的,这代表 Google 给你的 授权 使得你有能力访问 API 背后的 资源

      请求 API 时携带 token 的方式也有很多种,通过 HTTP Header 或者 url 参数或者 google 提供的类库都可以:

    • HTTP Header
    GET /drive/v2/files HTTP/1.1
    
    Authorization: Bearer <token>
    Host: www.googleapis.com/
    • URL参数
    GET https://www.googleapis.com/drive/v2/files?token=<token>
    • Python函数库
    from googleapiclient.discovery import build
    drive = build('drive', 'v2', credentials=credentials)

    更具体的说,上面用于调用 APItoken,我们称为细分为 access token。通常 access token 是有 有效期限 的,如果 过期 就需要 重新获取。那么如何重新获取?先看看第一次获取 token 的流程是怎样的:

    1. 首先需要向 Google API 注册一个应用程序,注册完毕之后就会拿到 认证信息credentials)包括 IDsecret。不是所有的程序类型都有 secret

    2. 接下来就要向 Google 请求 access token。这里先忽略一些细节,例如请求参数(当然需要上面申请到的 secret)。重要的是,如果你想访问的是 用户资源,这里就会提醒用户进行 授权

    3. 如果 用户授权 完毕。Google 就会返回 access token。又或者是返回 授权代码authorization code),再通过代码取得 access token

    token 获取到之后,就能够带上 token 访问 API 了。

    注意:在第三步通过 authorization code 兑换 access token 的过程中,Google 并不会仅仅返回 access token,还会返回额外的信息,这其中和之后更新相关的就是 refresh token

    一旦 access token 过期,你就可以通过 refresh token 再次请求 access token

    以上只是大致的流程,并且故意省略了一些额外的概念。比如更新 access token 当然也可以不需要 refresh token,这要根据你的 请求方式 和访问的 资源类型 而定。


    1.2 SSO (Single sign-on)

    Single Sign On,简称就是SSO。它的解释是:在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。

    SSO 是一类 解决方案 的统称,而在具体的实施方面,我们有两种策略可供选择:

    • SAML 2.0

    • OAuth 2.0

    1.3 Authentication VS Authorisation

    • Authentication: 身份鉴别,以下简称 认证;

    • Authorisation: 资源访问 授权。

    认证 的作用在于 认可 你能够访问系统,用于 鉴别访问者 是否是 合法用户;而 授权 用于决定你有访问 哪些资源的权限。

    1.4 Authorization Server/Identity Provider(IdP)

    把负责 认证的服务 称为 AuthorizationServer 或者 IdentityProvider,以下简称 IDP

    1.5 Service Provider(SP)/Resource Server

    把负责 提供资源(API 调用)的服务称为 ResourceServer 或者 ServiceProvider,以下简称 SP

    2 SAML 2.0

     SAML即安全断言标记语言,英文全称是Security Assertion Markup Language。它是一个基于XML的标准,用于在不同的安全域(security domain)之间交换认证和授权数据。 断言是什么?  就是做出判断的语言。

    2.1 SAML 主要包括三个方面:

    1.认证申明。表明用户是否已经认证,通常用于单点登录。

    2.属性申明。表明 某个Subject 的属性。

    3.授权申明。表明 某个资源的权限。

    2.2 SAML应用场景

    图上共有三个角色, 1,SP, 服务提供者。 2, Idp,认证用户并生成断言。 3,就是用户你了, client。

    首先, 你(client)是idp的注册用户, 它有你的用户名和密码,它可以认证你就是你。 其次, SP和Idp两者会被各自的域管理员设置为相互信任对方。并且双方都持有对方的公钥。这是配置好的。第三,有一天,你需要访问sp提供的某个服务,但是sp并不认识你,也没有你的用户名和密码因此不能认证你。 于是就发生了上图所示的8个步骤:

    1. 你去访问sp的某个受保护资源,比如浏览器打开: http://www.apc.com/resource1.aspx.

    2. sp发现你是新来的,没有认证信息。当然不能给你这个页面内容了。 他就会生成一个 saml的认证请求数据包(当然是saml格式的)。把这个请求放在一个html的form的一个隐藏的域中,把这个html form返回给你。 这个form后面有一句javascript自动提交这个form。 二而form的action地址就是 提前配置好的 idp上的一个地址。 

    saml认证请求的数据包可能是这个样子的:

    ==========

    <samlp:AuthnRequest
        xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
        ID="aaf23196-1773-2113-474a-fe114412ab72"
        Version="2.0"
        IssueInstant="2004-12-05T09:21:59"
        AssertionConsumerServiceIndex="0"
        AttributeConsumingServiceIndex="0">
        <saml:Issuer>https://sp.example.com/SAML2</saml:Issuer>
        <samlp:NameIDPolicy
          AllowCreate="true"
          Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
      </samlp:AuthnRequest>

    ==========

    而返回的html from内容大概设这个样子的:它包含了上面的数据包作为其中一个hidden的值。

    =============================

    <form method="post" action="https://idp.example.org/SAML2/SSO/POST" ...>
        <input type="hidden" name="SAMLRequest" value="<samlp:AuthnRequest>.......... </samlp:authnreques>" />
        ... other input parameter....
        <input type="submit" value="Submit" />

    </form>

    <javascript>
    document.form[0].submit();// 后面紧跟一句类似这样的提交代码.
    </javascript>

    =============================

    这些代码一部分是复制过来的, 有些是我现写的, 大家领会意思即可,不要在意那些细节。

    3. 上面的form会被javascript自动提交到idp的某个地址。

    4. idp也需要认证你, 于是返回给你一个认证的页面, 可能使用用户名密码认证,也可以使用ntlm认证等等一切可以认证你的方式。 因为idp保存有你的用户名和密码。

    5. 同上一步,也是认证你的一个过程。

    6. idp在认证你之后。觉得你合法, 于是就为你生成一些断言, 证明你是谁,你有什么权限等等。 并用自己的私钥签名。 然后包装成一个response格式,放在form里返回给你。

    断言的格式大概如下:

    =============

    <saml:Assertion
       xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
       xmlns:xs="http://www.w3.org/2001/XMLSchema"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       ID="b07b804c-7c29-ea16-7300-4f3d6f7928ac"
       Version="2.0"
       IssueInstant="2004-12-05T09:22:05">
       <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer>
       <ds:Signature
         xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...</ds:Signature>
       <saml:Subject>
    ..........
       </saml:Subject>
       <saml:Conditions
    .........
       </saml:Conditions>
       <saml:AuthnStatement
         AuthnInstant="2004-12-05T09:22:00"
         SessionIndex="b07b804c-7c29-ea16-7300-4f3d6f7928ac">
         <saml:AuthnContext>
           <saml:AuthnContextClassRef>
             urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
          </saml:AuthnContextClassRef>
         </saml:AuthnContext>
       </saml:AuthnStatement>
       <saml:AttributeStatement>
         <saml:Attribute
           xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
           x500:Encoding="LDAP"
           NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
           Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
           FriendlyName="eduPersonAffiliation">
           <saml:AttributeValue
             xsi:type="xs:string">member</saml:AttributeValue>
           <saml:AttributeValue
             xsi:type="xs:string">staff</saml:AttributeValue>
         </saml:Attribute>
       </saml:AttributeStatement>
     </saml:Assertion>

    =============

    其中authnstatement认证语句表示你认证成功了。subject表示你是谁。而attributestatement表示你有哪些属性。 还有一个授权语句上面例子中没有。

    Response语句大概如下:

    ============================

     <samlp:Response
        xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
        ID="identifier_2"
        InResponseTo="identifier_1"
        Version="2.0"
        IssueInstant="2004-12-05T09:22:05"
        Destination="https://sp.example.com/SAML2/SSO/POST">
        <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer>
        <samlp:Status>
          <samlp:StatusCode
            Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
        </samlp:Status>
        <saml:Assertion
          xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
          ID="identifier_3"
          Version="2.0"
          IssueInstant="2004-12-05T09:22:05">
          <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer>
          <!-- a POSTed assertion MUST be signed -->
         ....................
        </saml:Assertion>
      </samlp:Response>

    ============================

    正如上面第2步一样,它也会把response包装在一个form里面返回给你,并自动提交给 sp的某个地址。

    ===========

     <form method="post" action="https://sp.example.com/SAML2/SSO/POST" ...>
        <input type="hidden" name="SAMLResponse" value="<samlp:Response>.........</samlp:respons>" />
        <input type="hidden" name="RelayState" value="''token''" />
        ...
        <input type="submit" value="Submit" />
      </form>
    <javascript>
    document.form[0].submit();// 后面紧跟一句类似这样的提交代码.
    </javascript>
     

    ===========

    7. 于是就到了第7步, 这个form被javascript自动提交到sp了。 

    8. sp读到form提交上来的 断言。 并通过idp的公钥验证了断言的签名。 于是信任了断言。 知道你是idp的合法用户了。 所以就最终给你返回了你最初请求的页面了。  http://www.apc.com/resource1.aspx.

    2.3 SAML标准结构

    2.4 SAML缺点

    不能跨平台到手机应用上面

    https://www.cnblogs.com/shuidao/p/3463947.html

    3  OAuth 2.0

    https://www.cnblogs.com/kaleidoscope/p/9507261.html

    3.1 4种基础概念

    • 资源所有人 (Resource Owner)

      可以认为就是上面的QQ账户的所有者。

    • 客户端 (Client)

      客户端是指要使用第三方认证授权服务的一方,也就是上面的 CSDN

    • 资源服务器 (Resource Server)

      这里的资源就是 QQ 昵称,头像和性别等,资源服务器自然是提供这些资源的腾讯的服务器咯!

    • 授权服务器 (Authorization Server)

      这里使用的是 QQ 登录,那么自然我们可以认为 QQ 的登录服务器就是授权服务器了。、

    3.3 运行流程

    (A)用户打开客户端以后,客户端要求用户给予授权。
    (B)用户同意给予客户端授权。
    (C)客户端使用上一步获得的授权,向认证服务器申请令牌。
    (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
    (E)客户端使用令牌,向资源服务器申请获取资源。
    (F)资源服务器确认令牌无误,同意向客户端开放资源。

    3.2 授权获得令牌的四种模式

    3.2.1 授权码模式

     

    (A)用户访问客户端,后者将前者导向认证服务器。
    (B)用户选择是否给予客户端授权。
    (C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
    (D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
    (E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

    相关参数:

    • A步骤中,客户端向AS申请认证的url:
    1. esponse_type:表示授权类型,必选项,此处的值固定为"code"
    2. client_id:表示客户端的ID,必选项
    3. redirect_uri:表示重定向URI,可选项
    4. scope:表示申请的权限范围,可选项
    5. state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

    下面是一个例子。

    GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
    Host: server.example.com
    • C步骤中,服务器回应客户端的URI,包含以下参数:
    1. code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
    2. state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

    下面是一个例子。

    HTTP/1.1 302 Found
    Location: <a href="https://client.example.com/cb">https://client.example.com/cb</a>?code=SplxlOBeZQQYbYS6WxSbIA
    &state=xyz
    • D步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:
    1. grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
    2. code:表示上一步获得的授权码,必选项。
    3. redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
    4. client_id:表示客户端ID,必选项。

    下面是一个例子。

    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
     
    grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
    • E步骤中,认证服务器发送的HTTP回复,包含以下参数:
    1. access_token:表示访问令牌,必选项。
    2. token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
    3. expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
    4. refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
    5. scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

    下面是一个例子。

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    Cache-Control: no-store
    Pragma: no-cache
     
    {
    "access_token":"2YotnFZFEjr1zCsicMWpAA",
    "token_type":"example",
    "expires_in":3600,
    "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
    "example_parameter":"example_value"
    }

    相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。

    3.2.2 简化模式

    简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

    它的步骤如下:

    (A)客户端将用户导向认证服务器。

    (B)用户决定是否给于客户端授权。

    (C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。

    (D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。

    (E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。

    (F)浏览器执行上一步获得的脚本,提取出令牌。

    (G)浏览器将令牌发给客户端。

    相关参数:

    • A步骤中,客户端发出的HTTP请求,包含以下参数:
    1. response_type:表示授权类型,此处的值固定为"token",必选项。
    2. client_id:表示客户端的ID,必选项。
    3. redirect_uri:表示重定向的URI,可选项。
    4. scope:表示权限范围,可选项。
    5. state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

    下面是一个例子。

    GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
    &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
    Host: server.example.com
    • C步骤中,认证服务器回应客户端的URI,包含以下参数:
    1. access_token:表示访问令牌,必选项。
    2. token_type:表示令牌类型,该值大小写不敏感,必选项。
    3. expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
    4. scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
    5. state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

    下面是一个例子。

    HTTP/1.1 302 Found
    Location: <a href="http://example.com/cb">http://example.com/cb</a>#access_token=2YotnFZFEjr1zCsicMWpAA
    &state=xyz&token_type=example&expires_in=3600

    在上面的例子中,认证服务器用HTTP头信息的Location栏,指定浏览器重定向的网址。注意,在这个网址的Hash部分包含了令牌。

    根据上面的D步骤,下一步浏览器会访问Location指定的网址,但是Hash部分不会发送。接下来的E步骤,服务提供商的资源服务器发送过来的代码,会提取出Hash中的令牌。

    3.2.3 密码模式

    密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。

    在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

    它的步骤如下:

    (A)用户向客户端提供用户名和密码。

    (B)客户端将用户名和密码发给认证服务器,向后者请求令牌。

    (C)认证服务器确认无误后,向客户端提供访问令牌。

    相关参数:

    • B步骤中,客户端发出的HTTP请求,包含以下参数:
    1. grant_type:表示授权类型,此处的值固定为"password",必选项。
    2. username:表示用户名,必选项。
    3. password:表示用户的密码,必选项。
    4. scope:表示权限范围,可选项。

    下面是一个例子。

    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
     
    grant_type=password&username=johndoe&password=A3ddj3w

    C步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    Cache-Control: no-store
    Pragma: no-cache
     
    {
      "access_token":"2YotnFZFEjr1zCsicMWpAA",
      "token_type":"example",
      "expires_in":3600,
      "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
      "example_parameter":"example_value"

    整个过程中,客户端不得保存用户的密码。

    3.2.4 客户端模式

    客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

    它的步骤如下:

    (A)客户端向认证服务器进行身份认证,并要求一个访问令牌。

    (B)认证服务器确认无误后,向客户端提供访问令牌。

     相关参数:

    • A步骤中,客户端发出的HTTP请求,包含以下参数:
    1. granttype:表示授权类型,此处的值固定为"clientcredentials",必选项。
    2. scope:表示权限范围,可选项。
    POST /token HTTP/1.1
    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
     
    grant_type=client_credentials

    认证服务器必须以某种方式,验证客户端身份。

    B步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    Cache-Control: no-store
    Pragma: no-cache
     
    {
      "access_token":"2YotnFZFEjr1zCsicMWpAA",
      "token_type":"example",
      "expires_in":3600,
      "example_parameter":"example_value"
    }

     3.4.5 更新令牌

    如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌。

    客户端发出更新令牌的HTTP请求,包含以下参数:

    • granttype:表示使用的授权模式,此处的值固定为"refreshtoken",必选项。
    • refresh_token:表示早前收到的更新令牌,必选项。
    • scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。

    下面是一个例子。

    Host: server.example.com
    Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
    Content-Type: application/x-www-form-urlencoded
     
    grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
  • 相关阅读:
    Hyperledger Fabric 1.0 从零开始(七)——启动Fabric多节点集群
    Hyperledger Fabric 1.0 从零开始(六)——创建Fabric多节点集群
    Hyperledger Fabric 1.0 从零开始(五)——运行测试e2e
    Hyperledger Fabric 1.0 从零开始(四)——Fabric源码及镜像文件处理
    Hyperledger Fabric 1.0 从零开始(三)——环境构建(内网/准离线)
    Hyperledger Fabric 1.0 从零开始(二)——环境构建(公网)
    Hyperledger Fabric 1.0 从零开始(一)
    Springboot 多数据源配置,结合tk-mybatis
    使用mybatis-generator插件结合tk.mybatis自动生成mapper二三事
    使用IDEA创建一个springboot项目
  • 原文地址:https://www.cnblogs.com/yujin123456/p/10896763.html
Copyright © 2011-2022 走看看