前言

在日常网络冲浪中,很多网站要求我们注册登录的时候,我们都可以选择使用 QQ|微信|微博|Github 等作为第三方账号去登录。那么如果我的网站都是游戏相关的内容,我可不可以让用户 使用 Steam 作为第三方账号登录 呢?

问题分析

基于网页浏览器的 OpenID 验证

OpenID 2.0了解更多) 规范所描述,Steam 只是一个 OpenID 的提供者。在网页浏览器内,第三方网站可以使用 OpenID 来获取用户的 SteamID ,用户的 SteamID 可以用来作为第三方网站的登录凭据(登录)或者与第三方网站的既有账户绑定(注册)。

流程描述

当用户希望登录第三方网站并且将自己的账号与 Steam 账号绑定,第三方网站将用户重定向到 Steam 社区的登录授权页面,用户输入 Steam 的登录凭证后,浏览器自动重定向回第三方网站,并将一些额外的 OpenID 数据写入返回的 URL 中。这些数据通过验证之后即可解析出用户的 SteamID 。

具体操作

申请一个用来校验信息的 ApiKey

到这里申请 => steamcommunity

构造用来登录的链接

参数说明:

steamLoginUrl: https://steamcommunity.com/openid/login
returnUrl: Steam社区登录之后重定向的链接,一般为登录之后的网站首页 https://xxx.com
realm: steam社区授权页面显示的第三方网站名称
// 返回的链接
const url = `${steamLoginUrl}?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=checkid_setup&openid.return_to=${returnUrl}&openid.realm=${realm}&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select`;

当用户点击网页上的 Steam 登录标识的时候,浏览器将用户重定向到 url ,在用户授权之后,会回到 returnUrl 页面。

校验Steam返回的数据

当 Steam 成功授权登录返回到我们的 returnUrl 页面之后,页面链接中会带有很多额外信息:

const respUrl = `${returnUrl}?openid.ns=http://specs.openid.net/auth/2.0&openid.mode=id_res&openid.op_endpoint=https://steamcommunity.com/openid/login&openid.claimed_id=https://steamcommunity.com/openid/id/xxxxxxxxxxx&openid.identity=https://steamcommunity.com/openid/id/xxxxxxxxxxx&openid.return_to=https:/%mywebsite.com&openid.response_nonce=2020-08-27T04:44:16Zs4DPZce8qc+iPCe8JgQKB0BiIDI=&openid.assoc_handle=1234567890&openid.signed=signed,op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle&openid.sig=W0u5DRbtHE1GG0ZKXjerUZDUGmc=`;

具体的参数说明可参考steam官方文档

因为返回的参数中带有用户的 SteamID 字段,为了保证信息安全,我们需要对数据进行正确性校验。
定义 params = respUrl ? 后面的内容

  1. 替换 params 中的 openid.mode=id_resopenid.mode=check_authentication

  2. 构造校验链接

    const validateUrl = `https://steamcommunity.com/openid/login?${params}`;
  3. 通过 GET 请求 validateUrl 得到校验结果
    得到一个 text/plain 类型的response:

    ns:http://specs.openid.net/auth/2.0
    is_valid:true

    is_valid:true 表明校验通过。

通过用户的SteamID来获取用户的个人信息

当校验完用户的 Steam 登录之后,我们便可以在返回的数据中获取到用户的 SteamID 。

`openid.identity=https://steamcommunity.com/openid/id/xxxxxxxxxxx(此处则是用户的SteamID)`

通过 Steam 平台开放接口,我们则可以获取到用户的 Steam 个人信息。

GET 请求:

`https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key=${开篇申请的ApiKey}&steamids=${用户的SteamID}`

返回的数据格式:

"response":{  
  "players":[  
     {  
        "steamid":"xxxxxxxxxxx",
        "communityvisibilitystate":1,
        "profilestate":1,
        "personaname":"xxxx",
        "lastlogoff":1556305001,
        "profileurl":"https://steamcommunity.com/profiles/xxxxxxxxxxx/",
        "avatar":"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/32/xxxxxxxxxxx.jpg",
        "avatarmedium":"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/32/xxxxxxxxxxx.jpg",
        "avatarfull":"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/32/xxxxxxxxxxx.jpg",
     }
  ]
}

至此,使用 Steam 作为网站的第三方账号登录并且获取用户的 Steam 信息就已经全部完成。

结语 & 一些小问题

  1. 为保证数据安全性,ApiKey 应该存储在网站自己的服务器上,所有的构造链接以及校验过程都应该放在后端完成。

  2. Steam 社区登录的时候偶尔可能需要用户科学上网,一旦用户不能正常访问 Steam 的登录功能,页面要做好容错处理。