理解skill調用
本節來更詳細的討論alexa是如何確定調用哪個skill的。
參考:https://developer.amazon.com/zh/docs/custom-skills/understanding-how-users-invoke-custom-skills.html
明確調用(Specific Request (Intent))
用戶在語音中明確的包含了要調用的skill的名字,雲會給skill發送一個帶有具體intent的 IntentRequest
。用戶可以有很多種表達方式來明確的調用skill,包括疑問句、祈使句等等,甚至不帶具體的請求內容只是呼喚skill的名字。這些都由Alexa來自動處理。Alexa預設了一些調用的表達方式,例如
<some action> <connecting word> <invocation name> e.g.“give me my Taurus horoscope using Daily Horoscopes”
Ask <invocation name> <connecting word> <some action> e.g.“Ask Daily Horoscopes to give me the horoscope for Taurus”
Start <invocation name> and <some action> e.g.“Start Daily Horoscopes and give me the horoscope for Taurus”
這里主要潛在的安全問題就是skill的調用名稱的處理了,惡意skill要與正常skill爭奪誰被調用。
隱式調用(Name-free Interaction)(beta測試功能)
第二種比較有意思的是隱式調用,用戶不需要明確說出想要調用的skill,由Alexa來自動尋找調用合適的skill。大體流程如下:
- 用戶做出請求行為后,Alexa解析請求,並將請求發送給排名靠前的候選skill,向這些skill來發送
CanFulfillIntentRequest
詢問是否可以處理該intent。 - 如果skill實現了
canFulfillIntent
,skill此時不應該做出任何實際操作,包括開關燈、播放音樂等等。 - Alexa收集響應看哪個skill合適,選擇后再發送
IntentRequest
給被選中的skill。 - 收到
IntentRequest
的skill再回復用戶執行具體的操作。
所以,如果skill想要被隱式調用的話,就要實現CanFulfillIntentRequest
接口,userId
不會在調用這個接口的時候就傳入。這就相當於,Alexa會將用戶的intent廣播給所有注冊了的skill,似乎發給惡意的skill會有一些隱私問題,雖然文檔說canFulfillIntent
時不應該做出實際操作,但是skill此時是否可以悄悄地發送用戶的intent? 官網中的CanFulfillIntentRequest 請求例子如下
{
"request": {
"type": "CanFulfillIntentRequest",
"requestId": "...",
"intent": {
"name": "PlaySound",
"slots": {
"Sound": {
"name": "Sound",
"value": "crickets"
}
},
},
"locale": "en-US",
"timestamp": "..."
},
"context": {
"System": {
"application": {
"applicationId": "amzn1.ask.skill.<skill-id-value>"
},
"user": {
"userId": "<user-id-value>"
},
"device": {
"supportedInterfaces": {}
}
}
},
"version": "1.0"
}
skill需要使用canFulfillIntent
來響應Alexa發出的CanFulfillIntentRequest
,設置canFulfill = "YES"/"NO"/"MAYBE"
來表明本skill是否能處理這個用戶的intent。 這個完全也是靠skill自己自覺來回應的,Alexa似乎還沒有能力來進一步的確認skill是不是真的有能力?此外,skill的響應和Alexa系統的請求是如何認證保證不被偽造的?
一個intent響應的例子如下:
{
"version":"1.0",
"response":{
"canFulfillIntent": {
"canFulfill": "YES",
"slots":{
"slotName1": {
"canUnderstand": "YES",
"canFulfill": "YES"
},
"slotName2": {
"canUnderstand": "YES",
"canFulfill": "YES"
}
}
}
}
}
亞馬遜文檔其實在這里給出了答案。亞馬遜發來的JSON里會攜帶一個Application ID,服務端skill的代碼要自己檢查發來的請求中的Application ID是否與自己Skill ID一樣,如果一致才執行,不一致就回復一個HTTP的400 Bad Request
。也就是說Skill的ID是個秘密(像這樣amzn1.ask.skill.661ecf07-280b-41fe-8fe4-8c5fbCCCCCC)。因此,能否找到泄露的Skill ID,或者開發者是否忘記了檢查Skill ID,就是能否偽造Alexa調用Skill請求的關鍵了。