鉴权与授权

优质
小牛编辑
132浏览
2023-12-01

概述

IoT系统使用OAtuh2协议进行接入与授权操作。原生的OAuth2支持Authenticatoin Code,Password,Client Credentials,Implicit四种授权模式。IoT系统扩展了OAuth2协议,以支持更多的接入方式,如基于微信登录的js_code模式,基于短信或邮件验证码的captcha模式。具体来讲,IoT系统支持以下授权模式:

  • Js Code
    适用于微信小程序接入

  • Captcha
    适用于使用短信或者邮件验证码进行接入

  • Password
    适用于传统的用户名和密码登录

  • Client Credentials
    适用于终端设备接入

  • Refresh Token
    适用于接入后刷新验证码

授权

鉴权API统一接口为

POST /api/v1/oauth/token?grant_type=${granty_type}&params

params随着鉴权模式的不同而不同,可能用到的参数如下表:

参数含义备注
grant_type授权类型枚举值,可选js_code/captcha/password/client_credentials/refresh_token
client_id授权的client idclient id应当事先注册在授权服务器中
client_secret client 密钥client secret应当事先存储于授权服务器
username用户名当grant_type为password模式时,需要该字段
password 用户密码当grant_type为password模式时,需要该字段
code代码当grant_tyep为js_code或captcha时需要该字段提供微信登录代码或者验证码
refresh_token刷新令牌当grant_type为refresh_token时,需要该字段提供刷新令牌
scope授权范围OAuth2协议要求的必填字段,可填任意非空值

鉴权成功后会返回如下类似的鉴权结果:

{
    "access_token": "07dc71f9-89b0-45e2-8f62-e9924d664fb3", 
    "token_type": "bearer",
    "refresh_token": "92e70c5d-7974-4b9c-85a0-9bfe67313ff6",
    "expires_in": 23318,
    "scope": "all"
}

响应JSON字段的含义如下:

字段含义
access_token用于后续访问受保护的api的token
token_typetoken的类型,上文中的token是bearer类型
refresh_token更新token,access_token有一个有效期,当access_token过期而refresh_token未过期时,可以使用refresh_token快速获取新的access_token,详见下文的refresh_token接入模式
expires_inaccess_token的过期时间,单位秒
scopeOAuth2协议规定的授权范围,与请求scope参数值保持一致

Js Code接入

使用场景

Js Code接入模式主要用于消费者使用微信小程序进行基于微信的OAuth2登录,以避免用户输入用户名和密码.

请求示例

POST /api/v1/oauth/token?grant_type=js_code&client_id=${client_id}&client_secret=${client_secret}&code=${code}&scope=all
`

注意: 一般来讲js_code模式中的code值只能通过微信拉取.

Password 模式接入

使用场景

Password接入可用于用户基于App或者网站通过用户名和密码登录.

请求示例

POST /api/v1/oauth/token?grant_type=password&client_id=client_id&client_secret=client_secret&username=username&password=password&scope=all
`

Client Credentials 模式接入

使用场景

Client Credentials模式只对客户端如App或者浏览器进行验证,适合不需要用户登录的场景.

请求示例

POST /api/v1/oauth/token?grant_type=client_credentials&client_id=client_id&client_secret=client_secret&scope=all
`

Captcha 模式接入

使用场景

Captcha模式适用于使用短信或者邮件验证码而非密码的场景进行用户接入.

请求示例

POST /api/v1/oauth/token?grant_type=captcha&client_id=client_id&client_secret=client_secret&code=code&scope=all
`

Refresh Token 模式接入

使用场景

Refresh Token模式适用于快速根据刷新token再次获得access_token.

请求示例

POST /api/v1/oauth/token?grant_type=refresh_token&client_id=client_id&client_secret=client_secret&refresh_token=refresh_token&scope=all
`

非url形式请求授权

鉴于将所有的请求参数附着于url导致url过长的问题,可通过将参数封装在请求头和表单中进行解决.

请求头

请求头使用basic方式对客户端信息进行认证,具体格式为

"Authorization": Basic+${space}+Base64(${client_id}:${client_secret})

即Authorization请求头的内容为Basic加空格再加上一段Base64编码,编码的内容为由英文冒号连接的client_id和client_secret字符串.

表单

除去client_id和client_secret的其他所有参数都可以放置到表单中,如下请求

post  /api/v1/oauth/token?grant_type=password&client_id=${client_id}&client_secret=${client_secret}&username=${username}&password=${password}&scope=all

等价于如下请求

curl -X POST \
  '/api/v1/oauth/token' \
  -H 'Authorization: Basic RGV9aHViNm5gdGlvbmTsY2hpca==' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F grant_type=password \
  -F username=${username} \
  -F password=${password} \
  -F scope=all

鉴权

对于IoT系统中的绝大部分API,都需要进行鉴权后才能访问,具体的鉴权方式分为两种

  • 针对浏览器,可直接在URL的query param加上access_token,即:
      GET some/api?access_token=access_token
    
    access_token可由前述鉴权模块获取.
  • 针对App或者命令行工具如wget/curl,需要加上如下HTPP请求头:
      "Authorization": Bearer+${SPACE} + ${access_token}
    

    注: 即Authentication的值是由字符串"Bearer"+空格+获取的access_token组成

如果未携带有效access_token,将会返回如下提示:

{
    "error": "unauthorized",
    "error_description": "Full authentication is required to access this resource"
}