如何从 Ubuntu Touch 应用程序使用 OAuth?

如何从 Ubuntu Touch 应用程序使用 OAuth?

我正在用 QML 编写 Ubuntu Touch 应用程序。我想与 Trello 集成。有两种方法可以在 API 中登录 Trello,其中一种是 OAuth,我打算使用它。从 QML 执行此操作的最佳方法是什么?我宁愿不使用 C++ 后端,但如果这是唯一的方法,我愿意这样做。

答案1

您可以为 Trello 创建一个帐户插件,这样就可以从系统设置中的“在线帐户”面板创建 Trello 帐户。然后您可以使用 Ubuntu.OnlineAccounts QML 模块登录,如下所示:

import QtQuick 2.0
import Ubuntu.OnlineAccounts 0.1

Rectangle {
    width: 400
    height: 300

    AccountServiceModel {
        id: accounts
        service: "trello-board"
    }
    ListView {
        id: listView
        anchors.fill: parent
        model: accounts
        delegate: Item {
            width: parent.width
            height: 60
            AccountService { 
                id: accts
                objectHandle: accountServiceHandle
                onAuthenticated: { console.log("Access token is " + reply.AccessToken) }
                onAuthenticationError: { console.log("Authentication failed, code " + error.code) }
            }    
            Text {
                anchors.fill: parent
                text: providerName + ": " + displayName
                MouseArea {
                    anchors.fill: parent
                    onClicked: accts.authenticate(null)
                }
            }
        }
    }
}

此代码将为您提供 OAuth 令牌。为了首先创建帐户,您需要创建以下文件:

  • /usr/share/accounts/providers/trello.provider
  • /usr/share/accounts/services/trello-board.service
  • /usr/share/accounts/qml-plugins/trello/Main.qml

鉴于 Trello 与 Flickr 和 twitter 一样使用 OAuth 1.0,只需使用 twitter 或 flickr 版本作为模板创建上述文件,并根据需要进行修改(对于 .service 文件,您可以使用flickr-sharing.service);trello.provider您需要按如下方式更改 API 端点:

<setting name="RequestEndpoint">https://trello.com/1/OAuthGetRequestToken</setting>
<setting name="TokenEndpoint">https://trello.com/1/OAuthGetAccessToken</setting>
<setting name="AuthorizationEndpoint">https://trello.com/1/OAuthAuthorizeToken</setting>

当然,请更改其他字段(回调 URL、客户端 ID 和密钥),以匹配您在 Trello 注册应用时设置的字段。如果一切顺利,您将能够从系统设置中的“在线帐户”面板创建 Trello 帐户。

答案2

由于 mardy 使用的方法实际上不适用于 Ubuntu Touch 上的受限应用程序,因此需要自己执行 OAuth 操作。本质上,您需要在 a 中加载登录页面,WebView然后使用onUrlChanged信号拦截响应以提取身份验证令牌。下面是使用StackExchange 自己的 OAuth 实现

OAuth.qml

import QtQuick 2.0
import QtWebKit 3.0
import "OAuth.js" as OAuth

Rectangle {
    height: 750
    width: 500

    Text {
        id: nextState
        visible: false
        anchors.centerIn: parent
        text: "Log in successful!"
    }

    Item {
        id: stackOAuth
        property string nextState: "AuthDone"
        anchors.fill: parent
        Component.onCompleted: OAuth.checkToken()
        property string token: ""
        WebView {
            id: loginView
            visible: false
            anchors.fill: parent
            onUrlChanged: OAuth.urlChanged(url)
        }
        Rectangle {
            height: 50
            width: parent.width
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            Text {
                text: loginView.url
            }
        }

        states: [
            State {
                name: "Login"
                PropertyChanges {
                    target: loginView
                    visible: true
                    url: "https://stackexchange.com/oauth/dialog"+
                         "?redirect_uri=https://stackexchange.com/oauth/login_success"+
                         "&client_id=YOUR_CLIENT_ID&scope=read_inbox"
                }
            },
            State {
                name: "AuthDone"
                PropertyChanges {
                    target: loginView
                    visible: false
                    opacity: 0
                }
                PropertyChanges {
                    target: nextState
                    visible: true
                }
            }
        ]
    }
}

然后,OAuth.js您有代码可以从 url 中提取令牌并从数据库中进行存储/检查:

.import QtQuick.LocalStorage 2.0 as Sql

function urlChanged(url) {
    var authorized = false;
    var mUrl = url.toString();
    var token = "";
    if (mUrl.indexOf("https://stackexchange.com") > -1) {
        var query = mUrl.substring(mUrl.indexOf('#') + 1);
        var vars = query.split("&");
        for (var i=0;i<vars.length;i++) {
            var pair = vars[i].split("=");
            if (pair[0] == "access_token") {
                authorized = true;
                token = pair[1];
                console.log("Found token: " + token)
                saveToken(token);
            }
        }
    }
    if (authorized) {
        stackOAuth.token = token;
        stackOAuth.state = "AuthDone";
    }
}

function saveToken(token) {
    console.log("Saving...")
    var db = Sql.LocalStorage.openDatabaseSync("Token", "1.0", "the token", 1);
    var dataStr = "INSERT INTO Token VALUES(?)";
    var data = [token];
    db.transaction(function(tx) {
        tx.executeSql('CREATE TABLE IF NOT EXISTS Token(token TEXT)');
        tx.executeSql(dataStr, data);
    });
}

function checkToken() {
    var db = Sql.LocalStorage.openDatabaseSync("Token", "1.0", "the token", 1);
    var dataStr = "SELECT * FROM Token";
    db.transaction(function(tx) {
        tx.executeSql('CREATE TABLE IF NOT EXISTS Token(token TEXT)');
        var rs = tx.executeSql(dataStr);
        if (rs.rows.item(0)) {
            stackOAuth.token = rs.rows.item(0).token
            stackOAuth.state = "AuthDone"
            console.log("Auth done...")
        } else {
            stackOAuth.state = "Login"
            console.log("Logging in....")
        }
    });
}

这个例子(或多或少)是诺基亚的旧 QtQuick 1.0 示例升级至 QtQuick 2.0。

相关内容