前言
在日常网络冲浪中,很多网站要求我们注册登录的时候,我们都可以选择使用 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 ?
后面的内容
替换
params
中的openid.mode=id_res
为openid.mode=check_authentication
构造校验链接
const validateUrl = `https://steamcommunity.com/openid/login?${params}`;
通过
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 信息就已经全部完成。
结语 & 一些小问题
为保证数据安全性,
ApiKey
应该存储在网站自己的服务器上,所有的构造链接以及校验过程都应该放在后端完成。Steam 社区登录的时候偶尔可能需要用户科学上网,一旦用户不能正常访问 Steam 的登录功能,页面要做好容错处理。