mip-inservice-login

说明

登录授权组件

使用登录授权前的准备

登录授权能力基于熊掌号的网页授权机制,开发者进行登录授权开发前,需先成为熊掌号开发者:

配置网页授权域名

为确保验证授权过程的安全,开发者必须在平台预先注册应用所在的域名或URL,作为OAuth2.0检验授权请求中的"redirect_uri"参数。以便保证OAuth2.0在回调过程中,会回调到安全域名。

熊掌号运营中心-开发-开发者设置地址)添加三个网页授权域名:

  • 网站主域名 - 需要在登录组件的域名
  • MIP-Cache 域名:mipcache.bdstatic.com
  • MIP-Cache 站点域名,规则:域名(.换成-).mipcdn.com,如:
    • www.mipengine.org -> www-mipengine-org.mipcdn.com
    • demo.www.mipengine.org -> demo-www-mipengine-org.mipcdn.com  mip-inservice-login 登录授权组件  - 图1

网页授权流程

  • 引导用户进入授权页面同意授权,获取code;
  • 通过code换取网页授权access_token;
  • 刷新接口调用凭据access_token,避免过期;
  • 获取用户基本信息。 若需了解百度账号授权流程的更多内容,请参看熊掌号主体流程说明第三方平台流程说明

组件

引入组件

标题 内容
类型 通用
支持布局 responsive,fixed-height,fill,container,fixed
所需脚本 https://c.mipcdn.com/static/v2/mip-inservice-login/mip-inservice-login.js

注意: 登录授权组件与mip-bind配合使用,且无需在页面额外引入mip-bind组件的脚本。

名词解释

  • 百度账号登录:用户在当前浏览器环境下登录了百度账号
  • 百度账号登出:用户在当前浏览器环境下登出了百度账号
  • 百度账号授权:用户在访问第三方站点时,第三方站点可以通过百度账号登录授权机制,来获取用户基本信息,进而实现自身业务功能。账号授权存在有效期,失效后需要重新授权。
  • 第三方站点登录:用户在当前浏览器环境下登录了第三方站点。当百度账号授权成功后,第三方站点可以使用百度用户的基本信息作为一次站点登录,按照业务逻辑对该登录用户进行管理
  • 第三方站点登出:用户在当前浏览器环境下登出了第三方站点,站点不再持有用户的登录信息
  • 后端:指使用登录授权组件的第三方站点的后端
  • 前端: 指使用登录授权组件的第三方站点的前端

组件样式

当触发组件的登录功能时,根据用户的状态,有以下几种样式形态:

  • 登录授权弹窗:用户在当前浏览器下进行过百度账号登录,但还未在第三方站点进行百度账号授权,当触发组件的登录功能时,将在站点页面上出现登录授权弹窗

  • 登录授权页面:用户在当前浏览器下进行百度账号登录,且未在第三方站点进行百度账号授权,当触发组件的登录功能时,将跳转打开登录授权页

  • 无样式:

    • 已登录第三方站点
    • 用户曾经使用百度账号授权登录过第三方站点,后来登出了,但未登出百度账号,且授权关系未失效,这时触发组件的登录,将直接返回授权code,没有样式

组件流程

流程简易说明

具体场景流程说明

  • 当用户打开或刷新第三方页面时,执行同步登录

  • 当用户在第三方页面点击按钮、链接等交互元素触发登录行为时,执行异步登录

  • 当开启了组件的自动登录(config属性的autologintrue),若访问第三方站点页面的用户未登录,则将执行自动登录逻辑

注意: 同步登录异步登录 是针对发生向后端请求用户数据这一操作的时机而言

渲染和触发事件逻辑

  • 页面加载完成 - 因未登录,空的用户数据({})渲染页面
  • 页面请求用户信息
    • code - 发送登录数据
      • 错误 - 触发 error 事件
      • 成功
        • 使用 response.data 重新渲染页面
        • 触发 login 事件
    • code
      • 未登录 - 忽略
      • 已登录
        • 使用 response.data 重新渲染页面
        • 触发 login 事件
  • 页面触发 登录组件ID.login 事件
    • 未登录 - 跳转登录授权页面
    • 已登录 - 忽略
  • 页面触发 登录组件ID.logout 事件
    • 未登录 - 忽略
    • 已登录
      • 后端返回 response.data.url
        • 跳转到 response.data.url
      • 后端没有返回 response.data.url
        • 触发 logout 事件
        • 使用空数据({})渲染模板

组件属性

config

说明:组件初始化所必须的配置数据

必选项:是

类型: Object

示例:通过m-bind:config="配置数据"将该属性传入组件,配置数据的示例说明如下,

  1. {
  2. "appid": "12345678", // 熊掌号id,string, 必须
  3. "clientId": "R6HzvBSGAvkFMUrhELUZayfH2No86t1k", // 熊掌号开发者client_id, string,必须
  4. "id": "info", // 数据的键名(key),当登录信息发生变更时,将更新mip-data里以该值为键名(`key`)的对象数据
  5. "isGlobal": false, // 需要更新的mip-data里已id为键名的对象数据是否为 全局数据,默认值false
  6. "autologin": false, // 页面打开后未登录状态下自动跳转登录,常用于必须登录状态下才可以访问的页面, boolean, 默认值false
  7. "endpoint": "https://api.example.com/user/info.php", // 后端源站数据接口链接,需要使用 `https://` 或者 `//开头的源站地址,需要接口支持 HTTPS ,使用 POST 形式发送数据 , 必须
  8. "redirectUri": "https://example.com/xxx.html" // 登录成功后的重定向地址,不传默认跳回原页面
  9. }

其中,endpoint为第三方后端提供的数据接口,组件将通过该接口,查询登录状态、获取用户信息等。

组件方法和事件

登录方法 - <div on="tap:登录组件id.login(redirectUri, origin)">

在其他元素中绑定点击或其他动作时调起登录。

该方法接收两个参数:

  • redirectUri: string,非必须,登录成功后的跳转地址,要求是站内页面。当页面运行在不同环境时(搜索或者原站),跳转链接的形式会不一样,需要开发者自己处理。
  • origin: string,非必须,执行登录时,标识发起登录操作的动作来源,在接受到登录成功的事件里,需要判断触发登录操作的是不是指定动作来源。当同一个页面存在多个触发登录的元素时,设置origin是必要的,因为每个元素在登录后的业务逻辑很可能是不一样的。 调用组件方法时的正确传递参数的方式是<div on="tap:登录组件id.login(参数a,参数b,参数c)></div>。所有参数之间使用英文逗号连接,不要有空格,如果某一个参数为空,就写成<div on="tap:登录组件id.login(,参数b,参数c)></div>。所有参数都会转成字符串传入组件的方法。

注意:

  • 该方法会根据当前用户登录百度账号的状态而打开登录弹层(已登录)或者 重新打开一个登录页面(未登录),在非搜索环境下,如果是打开登录页, 意味着这将导致当前页面未存储的数据丢失,如:表单用户填写内容。
  • 在已经登录成功的情况下,再次触发login方法,该方法不会执行。

登出方法 - <div on="tap:登录组件id.logout">

在其他元素中绑定点击或其他动作时请求登出接口。

注意:该方法不会跳转页面,异步的调用 endpoint 接口去退出,并触发登录组件元素中的 logout:其他组件id.其他组件行为 事件。

登录成功事件 - <mip-inservice-login on="login:其他组件id.其他组件行为">

登录事件包含同步登录成功异步登录成功两种状态:

  • 同步登录成功: 打开页面或者刷新页面时组件能够获取到用户数据
  • 异步登录成功: 由某个交互(如点击按钮)触发的登录操作,登录后当前页面不刷新 可以在登录成功时调用其他组件的组件行为。

登录失败事件 - <mip-inservice-login on="error:其他组件id.其他组件行为">

在登录请求后端返回值错误时触发。

登出成功事件 - <mip-inservice-login on="logout:其他组件id.其他组件行为">

在退出登录时(由 on="tap:组件id.logout" 调用触发)调用其他组件的组件行为。

取消自动登录事件 - <mip-inservice-login on="autoLoginCancel:其他组件id.其他组件行为">

自动登录时若用户取消登录(指,在登录页点击mip-shelll上的返回按钮 回到触发登录的页面, 或者 是点击授权弹窗上的取消按钮)时触发。

后端数据说明

以下为后端需要处理的和用户登录操作相关的几个场景下的请求。

页面打开时检查用户数据

执行时机: 每次打开页面时,如果url上没有和授权相关的查询参数(code,redirect_uri),都会发送type=check的请求,向后端查询当前用户的登录状态和数据。

请求:

名称 说明
请求链接 config.endpoint,必须支持https
请求类型 POST
请求参数 {type: 'check', sessionId: '会话凭证'}

未登录返回值说明:

  1. {
  2. "status": 0,
  3. "sessionId": "会话凭证,必须返回",
  4. "data": null
  5. }

已登录返回值,整个返回值的 data 字段将认为是用户数据,并使用MIP.setData到config属性配置的存放用户数据的对应字段里,如info.userInfo,在页面渲染时使用该数据渲染:

  1. {
  2. "status": 0,
  3. "sessionId": "会话凭证,必须返回",
  4. "data": {
  5. "nickname": "mipengine",
  6. "key2": "value2"
  7. }
  8. }

注意:上面 data.nickname 只是示例,具体什么数据请前、后端统一约定。

百度账号登录

执行时机: 1)在当前页面的url地址的查询参数上能正确获取到coderedirect_uri 2)异步登录接口返回了coderedirect_uri的数据。只要满足以上条件,都会发起type=login的请求。

请求:

名称 说明
请求链接 config.endpoint,必须支持https
请求类型 POST
请求参数 {type: 'login', code: '熊掌号授权code', redirect_uri: '回调链接', sessionid: '会话凭证'}

源站后端服务需要使用 coderedirect_uri 参数去请求 获取网页授权 access_token获取授权用户信息 接口,并和源站的用户关联、记录用户登录状态。

其中,sessionid为可选字段,如果能从本地缓存里取到该数据都会带上,后端应结合sessionid和code逻辑 做登录处理,具体请参看常见问题-后端相关部分

处理成功,认为已登录,整个返回值的 data 字段将认为是用户数据,并使用MIP.setData到config属性配置的存放用户数据的对应字段里,如info.userInfo,在页面渲染时使用该数据渲染:

  1. {
  2. "status": 0,
  3. "sessionId": "会话凭证,必须返回",
  4. "data": {
  5. "nickname": "mipengine",
  6. "key2": "value2"
  7. }
  8. }

如果 status 不为 0 触发 error 事件,如:

  1. {
  2. "status": 403
  3. }

退出

请求:

名称 说明
请求链接 config.endpoint,必须支持https
请求类型 POST
请求参数 {type: 'logout'}

返回值说明:

  1. {
  2. "status": 0,
  3. "data": {
  4. "url": "https://www.example.com 退出成功跳转的链接地址 可选",
  5. "title": "主页 自定义标题 可选"
  6. }
  7. }

其他

会话凭证 sessionId

由于在 iOS 对跨域透传 cooke 的限制(https://webkit.org/blog/7675/intelligent-tracking-prevention/),在前端组件请求后端接口时(type=checktype=login),由后端生成当前会话唯一凭证并记录到服务端,把凭证返回前端 response.sessionId,前端组件将在 localStorage 中缓存下来,在下次发后端接口请求时携带该凭证,后端就当优先使用 cookie/session 验证,不存在时获取 POST 参数中的 sessionId 去校验。

注意:本地 localStorage 是以 config.endpoint 为粒度去缓存。

后端需要支持 CORS + withCredentials
  • CORS 文档
  • withCredentials 附带身份凭证的请求 登录组件(mip-inservice-login)已经在前端发送请求时处理了 withCredentials ,需要对应的接口服务响应头设置:

  • Access-Control-Allow-Credentials: true

  • Access-Control-Allow-Origin: 对应请求的 origin 注意: 出于安全考虑请对来源的 origin 进行判断,并正确的返回 Access-Control-Allow-Origin 字段,不能为 *

使用组件示例

基本用法

  • html中使用登录组件
  1. <mip-data>
  2. <script type="application/json">
  3. {
  4. "info": {},
  5. "config": {
  6. appid: '熊掌号id',
  7. clientId: '熊掌号开发者id',
  8. id: 'info',
  9. autologin: false,
  10. endpoint: 'https://www.example.com/api/userinfo.php',
  11. isGlobal: false,
  12. redirectUri: ''
  13. }
  14. }
  15. </script>
  16. </mip-data>
  17. <mip-my-example id="example" m-bind:info="info"></mip-my-example>
  18. <mip-inservice-login
  19. id="log"
  20. m-bind:config="config"
  21. on="login:example.customLogin logout:example.customLogout"
  22. >
  23. </mip-inservice-login>
  24. <script src="https://c.mipcdn.com/static/v2/mip.js"></script>
  25. <script src="https://c.mipcdn.com/static/v2/mip-inservice-login/mip-inservice-login.js"></script>
  26. <script src="https://c.mipcdn.com/extensions/platform/v2/your.site.com/mip-my-example/mip-my-example.js"></script>

mip-my-example组件代码示例:

  1. <template>
  2. <div class="wrap">
  3. <h3>这是一个渲染片段示例</h3>
  4. <p>默认未登录,由用户交互(如点击按钮)触发登录/登出</p>
  5. <hr />
  6. <div v-if="info.isLogin">hi,{{info.userInfo.nickname}},欢迎回来!<span style="color:#f00;" on="tap:log.logout">退出</span></div>
  7. <div v-else>你没有<span style="color:#f00;" on="tap:log.login">登录</span>哦。</div>
  8. </div>
  9. </template>
  10. <script>
  11. export default {
  12. props: {
  13. info: {
  14. type: Object,
  15. required: true
  16. }
  17. },
  18. mounted () {
  19. // 自定义login事件
  20. this.$on('customLogin', event => {
  21. // 这里可以输出登录之后的数据
  22. // 获取用户信息
  23. event.userInfo;
  24. // 后端交互会话标识
  25. event.sessionId;
  26. });
  27. // 自定义exit事件
  28. this.$on('customLogout', event => {
  29. console.log('登出了');
  30. });
  31. }
  32. }
  33. </script>
  • vue组件里使用登录组件
  1. <!--先在html里配置数据,引入相关组件-->
  2. <mip-data>
  3. <script type="application/json">
  4. {
  5. "info": {},
  6. "config": {
  7. appid: '熊掌号id',
  8. clientId: '熊掌号开发者id',
  9. id: 'info',
  10. autologin: false,
  11. endpoint: 'https://www.example.com/api/userinfo.php',
  12. isGlobal: false,
  13. redirectUri: ''
  14. }
  15. }
  16. </script>
  17. </mip-data>
  18. <mip-my-example m-bind:info="info" m-bind:config="config" id="example"></mip-my-example>
  19. <script src="https://c.mipcdn.com/static/v2/mip.js"></script>
  20. <script src="https://c.mipcdn.com/static/v2/mip-inservice-login/mip-inservice-login.js"></script>
  21. <script src="https://c.mipcdn.com/extensions/platform/v2/your.site.com/mip-my-example/mip-my-example.js"></script>

mip-my-example组件代码示例:

  1. <template>
  2. <div class="wrap">
  3. <mip-inservice-login
  4. id="log"
  5. :config="config"
  6. on="login:example.customLogin logout:example.customLogout"
  7. >
  8. </mip-inservice-login>
  9. <h3>这是一个渲染片段示例</h3>
  10. <p>默认未登录,由用户交互(如点击按钮)触发登录/登出</p>
  11. <hr />
  12. <div v-if="info.isLogin">hi,{{info.userInfo.nickname}},欢迎回来!<span style="color:#f00;" on="tap:log.logout">退出</span></div>
  13. <div v-else>你没有<span style="color:#f00;" on="tap:log.login">登录</span>哦。</div>
  14. </div>
  15. </template>
  16. <script>
  17. export default {
  18. props: {
  19. info: {
  20. type: Object,
  21. required: true
  22. },
  23. config: {
  24. type: Object,
  25. required: true
  26. }
  27. },
  28. mounted () {
  29. // 自定义login事件
  30. this.$on('customLogin', event => {
  31. // 这里可以输出登录之后的数据
  32. // 获取用户信息
  33. event.userInfo;
  34. // 后端交互会话标识
  35. event.sessionId;
  36. });
  37. // 自定义exit事件
  38. this.$on('customLogout', event => {
  39. console.log('登出了');
  40. });
  41. }
  42. }
  43. </script>

mip-bind配合使用注意:

  • 必须在mip-inservice-login组件的config属性里设置id 的值,该值与组件id的值可以不一样, 如示例中的info
  • 必须在 <mip-data> 配置数据中设置一个以mip-inservice-loginconfig属性里的id 为键名(key)的对象数据, 如示例中的info
  • 如果这个数据是全局共享数据,需要设置mip-inservice-loginconfig里的isGlobaltrue。共享数据的用法,请参照文档MIP 2.0 的数据和应用
  • 在请求登录(type=login)、检查是否登录(type=check)、退出(type=logout)成功时,会调用 MIP.setData 设置数据,数据结构为:
  1. {
  2. "id": {
  3. "isLogin": Boolean,
  4. "userInfo": Response.data,
  5. "sessionId": String
  6. }
  7. }

实现个人中心

个人中心需要自动登录的功能

  1. <mip-data>
  2. <script type="application/json">
  3. {
  4. "info": {
  5. userInfo: {
  6. "nickname": "",
  7. "province": ""
  8. }
  9. },
  10. "config": {
  11. appid: '熊掌号id',
  12. clientId: '熊掌号开发者id',
  13. id: 'info',
  14. autologin: true,
  15. endpoint: 'https://www.example.com/api/userinfo.php',
  16. isGlobal: false
  17. }
  18. }
  19. </script>
  20. </mip-data>
  21. <mip-inservice-login id="log" m-bind:config="config"></mip-inservice-login>
  22. <ul>
  23. <li>
  24. hi,<span m-text="info.userInfo.nickname"></span>,你上次登录地点为 <span m-text="info.userInfo.province"></span>
  25. </li>
  26. <li>
  27. <a href="/order/list.html" data-type="mip">订单中心</a>
  28. </li>
  29. <li>
  30. <div on="tap:log.logout">退出</div>
  31. </li>
  32. </ul>

说明:

  • mip-inservice-login组件的config属性里,autologin设置为true

综合示例

定制登录成功后的行为

  • 点击用户名,触发登录,登录后回到原页面
  • 点击我的订单,触发登录,登录后跳转到订单页面order.html
  • 点击确认下单,触发登录,登录后执行自定义业务逻辑 代码如下:

  • html

  1. <mip-data>
  2. <script type="application/json">
  3. {
  4. "info": {},
  5. "config": {
  6. appid: '熊掌号id',
  7. clientId: '熊掌号开发者id',
  8. id: 'info',
  9. autologin: false,
  10. endpoint: 'https://www.example.com/api/userinfo.php',
  11. isGlobal: false,
  12. redirectUri: ''
  13. }
  14. }
  15. </script>
  16. </mip-data>
  17. <mip-example-container m-bind:info="info" m-bind:config="config"></mip-example-container>
  18. <script src="https://c.mipcdn.com/static/v2/mip.js"></script>
  19. <script src="https://c.mipcdn.com/static/v2/mip-inservice-login/mip-inservice-login.js"></script>
  20. <script src="https://c.mipcdn.com/extensions/platform/v2/your.site.com/mip-example-container/mip-example-container.js"></script>
  21. <script src="https://c.mipcdn.com/extensions/platform/v2/your.site.com/mip-example/mip-example.js"></script>
  • mip-example-container代码
  1. <template>
  2. <div class="wrap">
  3. <mip-inservice-login
  4. id="log"
  5. :config="config"
  6. on="login:example.customLogin logout:example.customLogout"
  7. ></mip-inservice-login>
  8. <mip-example
  9. id="example"
  10. :info="info"
  11. on="actionPay:log.login(,asynLog) actionOrder:log.login actionName:log.login actionExit:log.logout"
  12. ></mip-example>
  13. </div>
  14. </template>
  15. <script>
  16. export default {
  17. props: {
  18. info: {
  19. type: Object,
  20. required: true,
  21. default () {
  22. return {};
  23. }
  24. },
  25. config: {
  26. type: Object,
  27. required: true,
  28. default () {
  29. return {};
  30. }
  31. }
  32. },
  33. mounted () {
  34. // ...
  35. }
  36. }
  37. </script>
  • mip-example代码
  1. <template>
  2. <div class="wrapper">
  3. <div>
  4. <p @click="jumpDefault" class="text">{{name}}</p>
  5. <p @click="jumpRedirect" class="text">我的订单</p>
  6. <p @click="logout" class="text">退出</p>
  7. </div>
  8. <div>
  9. <p><input type="text" v-model="test" class="input"/></p>
  10. <div @click="jumpCustom" class="text">确认下单</div>
  11. </div>
  12. </div>
  13. </template>
  14. <style scoped>
  15. .wrapper {
  16. margin: 0 auto;
  17. text-align: center;
  18. }
  19. .text {
  20. height: 32px;
  21. line-height: 32px;
  22. font-size: 18px;
  23. margin-bottom: 5px;
  24. }
  25. .input {
  26. height: 30px;
  27. line-height: 30px;
  28. font-size: 16px;
  29. border: 1px solid #f0f0f0;
  30. }
  31. </style>
  32. <script>
  33. export default {
  34. props: {
  35. info: {
  36. type: Object,
  37. required: true,
  38. default () {
  39. return {};
  40. }
  41. }
  42. },
  43. data: function () {
  44. return {
  45. test: ''
  46. }
  47. },
  48. computed: {
  49. name () {
  50. if (this.info.isLogin) {
  51. return this.info.userInfo.nickname
  52. }
  53. else {
  54. return '未登录'
  55. }
  56. }
  57. },
  58. mounted () {
  59. // 监听login
  60. this.$on('customLogin', (e) => {
  61. // 判断当前收到登录成功事件是来自哪个动作触发的
  62. if (e.origin === 'asynLog') {
  63. this.alertTip();
  64. }
  65. });
  66. // 监听logout
  67. this.$on('customLogout', (e) => {
  68. console.log('用户登出了');
  69. });
  70. },
  71. methods: {
  72. jumpDefault () {
  73. if (!this.info.isLogin) {
  74. // 设置登录组件的config属性中,重定向地址:redirectUri为空
  75. MIP.setData({
  76. config: {
  77. redirectUri: ''
  78. }
  79. });
  80. // 在下一个执行时机触发事件
  81. this.$nextTick(function () {
  82. this.$emit('actionName');
  83. });
  84. }
  85. },
  86. jumpRedirect () {
  87. // 如果已经登录,自己处理跳转
  88. if (this.info.isLogin) {
  89. window.MIP.viewer.open('./order.html', {isMipLink: true});
  90. }
  91. else {
  92. // 设置登录组件的config属性中,重定向地址:redirectUri为订单页地址
  93. MIP.setData({
  94. config: {
  95. redirectUri: './order.html'
  96. }
  97. });
  98. // 在下一个执行时机触发事件
  99. this.$nextTick(function () {
  100. this.$emit('actionOrder');
  101. });
  102. }
  103. },
  104. jumpCustom () {
  105. // 如果已经登录,自己处理跳转
  106. if (this.info.isLogin) {
  107. this.alertTip();
  108. }
  109. else {
  110. // 设置登录组件的config属性中,重定向地址:redirectUri为空
  111. MIP.setData({
  112. config: {
  113. redirectUri: ''
  114. }
  115. });
  116. // 在下一个执行时机触发事件
  117. this.$nextTick(function () {
  118. this.$emit('actionPay');
  119. });
  120. }
  121. },
  122. alertTip () {
  123. if (this.test !== '') {
  124. alert('现在我可以跳转到下个页面了');
  125. }
  126. else {
  127. alert('输入框不能为空!')
  128. }
  129. },
  130. logout () {
  131. // 触发登出事件
  132. this.$emit('logout');
  133. }
  134. }
  135. }
  136. </script>

注意:

  • 可以在调用登录组件的login方法时,直接传入重定向地址。本示例通过设置登录组件配置的方式,来修改重定向地址。
  • 已登录的情况下,业务方需要自己处理逻辑,登录组件不会再回调或者跳转到指定地址。
  • nextTick里抛出自定义组件事件,是因为修改配置后,会触发一次dom渲染,但登录组件持有的数据没有更新,所以需要在dom渲染后的下个时间点再执行操作。

常见问题

后端相关

  • 使用登录组件需要后端介入吗? 答: 需要

  • 后端需要完成哪些工作? 答: 后端需要 1)接入熊掌号网页授权,能够获取到百度用户的基本信息 ;2)提供一个供登录组件使用的、支持CORS + withCredentials的接口; 3)对用户在第三方站点的登录信息进行管理(用户名、登录状态)。

  • 在哪配置网页授权回调地址?支持配置多个回调地址吗? 答: 熊掌号运营中心-开发-开发者设置-网页授权域名(地址)。支持。

  • endpoint的作用是什么?是必须的吗? 答:endpoint是后端提供给组件的一个获取用户信息、登录状态的接口,是必须的。

  • 用户数据来自哪里? 答:当访客在第三方站点进行百度账号登录授权后,组件将使用授权code和redirect_uri,向第三方后端接口endpoint发起登录请求,后端使用code换取网页授权access_token,再使用access_token获取百度用户信息

  • 用户数据存在哪? 答:用户数据存在第三方数据库,组件只负责向后端发起请求,获取用户数据和登录状态,组件本身不存储任何用户数据。

  • sessionid的作用是什么,为什么需要它? 答:由于在 iOS 对跨域透传 cooke 的限制(https://webkit.org/blog/7675/intelligent-tracking-prevention/),在组件请求后端接口时(type=checktype=login),由后端生成当前会话唯一凭证并记录到服务端,把凭证返回前端 response.sessionId,前端组件将在 localStorage 中缓存下来,在下次发后端接口请求时携带该凭证,后端就当优先使用 cookie/session 验证,不存在时获取 POST 参数中的 sessionId 去校验。

  • 为什么发起type=login的请求时,还携带有sessionid? 答:发起type=login的条件是1)在当前页面的url地址的查询参数上能正确获取到coderedirect_uri 2)异步登录接口返回了coderedirect_uri的数据。只要满足以上条件,都会发起type=login的请求。所以,当用户从百度登录授权页返回到第三方页面后,将执行type=login,后端成功返回用户信息后,sessionid有值,此时刷新当前页面(因为url上依然有code信息),又会再次发起type=login,并携带sessionid

所以,type=login时后端处理的逻辑应该是:

  1. sessionid是否存在,
  2. + 如果存在,sessionid是否已过期,
  3. * 如果没过期,直接返回用户数据,
  4. * 如果过期,使用code+redirect_uri发起换取access_token的操作,成功获取百度用户信息后,更新sessionid,并将最新数据返回给组件
  5. + 如果不存在,使用code+redirect_uri发起换取access_token的操作,成功获取百度用户信息后,将最新数据返回给组件
  • 为什么type=login时,也有code+redirect_uri值,但还是返回invalid redirecturi? 答:发起授权时生成code的重定向地址,与后端现在换取accesstoken使用的redirect_uri不一致

  • 回调地址里有特殊字符怎么办? 答:组件传给后端的redirect_uri,使用的是原始值(例如,在组件配置参数里设置的重定向地址),组件不会再做encode处理,如果含有特殊字符(中文、& 等),需要后端自己完成encode,再去换取access_token

前端相关

  • 前端怎么获取到用户数据? 答: 1) 监听组件抛出的login事件,该事件会返回用户数据 2) 通过mip-data里设置的存储用户数据的字段获取,如示例中的info.userInfo.nicknameinfo.isLogin

  • 打开页面就能获取到用户数据吗? 答: 不能,组件每次都是异步向后端查询用户数据,所以页面本身应该做有数据没数据时的显示效果兼容,已达到更好的用户体验。

  • 只有设置为自动登录才能获取到用户数据吗? 答: 不是,组件每次初始化都会像后端查询用户数据,如果后端成功返回了登录态和数据,都会抛出login事件,并更新mip-data里对应的用户数据。当设置为自动登录,但后端返回为未登录状态时,组件就会主动发起登录百度账号的操作。

  • 一个页面能够有多个登录组件吗? 答:不可以,只允许一个登录组件。

  • 一个页面内允许多个操作触发登录吗? 答:可以。

  • 能够指定登录之后的跳转地址吗? 答:可以,1)可以在调起登录login()方法的时候传入redirectUri; 2)修改config配置里的redirectUri

  • 能够指定登录之后除了跳转外的其他行为吗? 答:可以,如果成功登录之后,会抛出login事件,前端可以监听该事件,然后执行自己的逻辑(需要设置origin参数,具体参加文档)。

  • 为什么控制台显示invalid redirecturi? 答:当前配置的授权回调地址不合法,请核对当前的域名或者跳转地址是否已在网页授权回调地址的配置里。

  • 能够定制登录之后的操作行为吗? 答:可以,如果成功登录之后,会抛出login事件,前端可以监听该事件,然后执行自己的逻辑。

  • 为什么发起登录操作时,没有任何显示效果,就跳转页面并且登录成功了呢? 答:因为该用户曾经在第三方网站使用百度账号登录成功过,之后退出了第三方站点(比如sessiond被清除),但没有退出百度账号,授权关系也依然有效,则不需要用户再次操作的情况下,组件就能够获取到授权code,然后携带code信息跳转到 前端设置的登录后的跳转地址

  • 为什么已经成功登录的情况下(userInfo里有用户数据),再次刷新页面,有时有用户数据,有时候没有? 答:组件只有进入视窗内才会被初始化,强烈建议把登录组件尽量靠近<body>标签放置。

其他

  • 如何取消授权? 答:访问该地址,解除应用绑定关系。

  • 能够只登录不授权吗? 答:暂时不支持该功能。

  • 支持在mip1页面下使用吗? 答:不支持。

  • 关注之后在哪能看到? 答: 百度app/简搜app -> 关注中心

changelog

2018-08-23

增加熊掌号关注功能

  • 授权弹窗

  • 登录授权页

原文: https://www.mipengine.org/v2/components/dynamic-content/mip-inservice-login.html