Angularjs 使用Laravel和Latcht websocket构建实时应用程序
我正在构建一个封闭的应用程序(用户需要进行身份验证才能使用它)。我无法从我的Latcht会话中识别当前已验证的用户。由于apache不支持长期存在的连接,所以我将LATCHT托管在一个单独的服务器实例上。这意味着我的用户将收到两个会话id。每个连接一个。我希望能够识别两个连接的当前用户 我的客户端代码是基于AngularJS的SPA。对于客户端WS,我使用Autobahn.WS WAMP v1实现。ab框架指定了身份验证的方法:,但具体如何进行 我是否在客户端保存用户名和密码,并在执行登录后重新传输这些信息(顺便说一下,这与我的SPA的其余部分是分开的)?如果是这样,这不是一个安全问题吗 服务器端将接收什么身份验证请求?我找不到任何这样的例子 请帮忙Angularjs 使用Laravel和Latcht websocket构建实时应用程序,angularjs,laravel,websocket,autobahn,ratchet,Angularjs,Laravel,Websocket,Autobahn,Ratchet,我正在构建一个封闭的应用程序(用户需要进行身份验证才能使用它)。我无法从我的Latcht会话中识别当前已验证的用户。由于apache不支持长期存在的连接,所以我将LATCHT托管在一个单独的服务器实例上。这意味着我的用户将收到两个会话id。每个连接一个。我希望能够识别两个连接的当前用户 我的客户端代码是基于AngularJS的SPA。对于客户端WS,我使用Autobahn.WS WAMP v1实现。ab框架指定了身份验证的方法:,但具体如何进行 我是否在客户端保存用户名和密码,并在执行登录后重新
另外,我没有足够的声誉来创建标签“Latcht”,所以我使用Ratchet(Latcht是基于此构建的)。我可以给你一些关于WAMP-CRA的提示,这是指的身份验证机制: WAMP-CRA不通过网络发送密码。它通过一个挑战响应方案工作。客户端和服务器有一个共享的秘密。为了对客户端进行身份验证,服务器将发送一个质询(随机的东西),客户端需要使用该密码进行签名。只有签名会被发回。客户端可能会将机密存储在浏览器本地存储中。它从未发送过
在上面的一个变体中,服务器发送的质询的签名不是在客户机内直接签名的,但是客户机可能允许从Ajax请求创建签名。当客户端已经使用其他方式(例如基于经典cookie)进行了身份验证,然后可以在正在进行身份验证的经典web应用程序中进行签名时,这非常有用。我可以给您一些关于WAMP-CRA的提示,这是指的身份验证机制: WAMP-CRA不通过网络发送密码。它通过一个挑战响应方案工作。客户端和服务器有一个共享的秘密。为了对客户端进行身份验证,服务器将发送一个质询(随机的东西),客户端需要使用该密码进行签名。只有签名会被发回。客户端可能会将机密存储在浏览器本地存储中。它从未发送过
在上面的一个变体中,服务器发送的质询的签名不是在客户机内直接签名的,但是客户机可能允许从Ajax请求创建签名。当客户端已经使用其他方式(例如基于经典cookie)进行了身份验证,然后可以在正在进行身份验证的经典web应用程序中进行签名时,这一点非常有用。创建一个名为AuthenticationService的angularjs服务,在需要时注入,并使用以下方法调用它:
AuthenticationService.check('login_name', 'password');
此代码存在于名为authentication.js的文件中。它假设高速公路已经包括在内。我确实需要大量编辑这段代码,去掉其中所有多余的垃圾,它可能有一两个语法错误,但想法就在那里
angular.module(
'top.authentication',
['top']
)
.factory('AuthenticationService', [ '$rootScope', function($rootScope) {
return {
check: function(aname, apwd) {
console.log("here in the check function");
$rootScope.loginInfo = { channel: aname, secret: apwd };
var wsuri = 'wss://' + '192.168.1.11' + ':9000/';
$rootScope.loginInfo.wsuri = wsuri;
ab.connect(wsuri,
function(session) {
$rootScope.loginInfo.session = session;
console.log("connected to " + wsuri);
onConnect(session);
},
function(code,reason) {
$rootScope.loginInfo.session = null;
if ( code == ab.CONNECTION_UNSUPPORTED) {
console.log(reason);
} else {
console.log('failed');
$rootScope.isLoggedIn = 'false';
}
}
);
function onConnect(sess) {
console.log('onConnect');
var wi = $rootScope.loginInfo;
sess.authreq(wi.channel).then(
function(challenge) {
console.log("onConnect().then()");
var secret = ab.deriveKey(wi.secret,JSON.parse(challenge).authextra);
var signature = sess.authsign(challenge, secret);
sess.auth(signature).then(onAuth, ab.log);
},ab.log
);
}
function onAuth(permission) {
$rootScope.isLoggedIn = 'true';
console.log("authentication complete");
// do whatever you need when you are logged in..
}
}
};
}])
然后,您需要服务器端的代码(正如您所指出的)。我假设您的服务器端web套接字是php编码。我没办法,已经一年多没有用php编写代码了。在我的例子中,我使用python,包括autobahn gear,然后子类WampCraServerProtocol,并替换一些方法(onSessionOpen、getAuthPermissions、getAuthSecret、onAuthenticated和onClose),正如您所想象的,这些是敲门的角代码的“另一面”。我认为autobahn不支持php,因此,您必须自己对身份验证的服务器端进行编程
无论如何,我的后端工作起来更像@oberstat所描述的。我通过老式的https建立身份验证,创建会话cookie,然后执行ajax请求“票证”(这是一个临时名称/密码,我与web身份验证会话关联)。它是一次性名称/密码,必须在几秒钟内使用,否则将消失。关键是我不必保留用户的凭证,我已经有了cookie/会话,我可以创建可以使用的票据。这也有一个很好的副作用,我的ajax会话与我的web套接字会话相关,对其中任何一个会话的查询都归因于后端的同一个会话
-g创建一个名为AuthenticationService的angularjs服务,在需要时注入,并使用以下命令调用它:
AuthenticationService.check('login_name', 'password');
此代码存在于名为authentication.js的文件中。它假设高速公路已经包括在内。我确实需要大量编辑这段代码,去掉其中所有多余的垃圾,它可能有一两个语法错误,但想法就在那里
angular.module(
'top.authentication',
['top']
)
.factory('AuthenticationService', [ '$rootScope', function($rootScope) {
return {
check: function(aname, apwd) {
console.log("here in the check function");
$rootScope.loginInfo = { channel: aname, secret: apwd };
var wsuri = 'wss://' + '192.168.1.11' + ':9000/';
$rootScope.loginInfo.wsuri = wsuri;
ab.connect(wsuri,
function(session) {
$rootScope.loginInfo.session = session;
console.log("connected to " + wsuri);
onConnect(session);
},
function(code,reason) {
$rootScope.loginInfo.session = null;
if ( code == ab.CONNECTION_UNSUPPORTED) {
console.log(reason);
} else {
console.log('failed');
$rootScope.isLoggedIn = 'false';
}
}
);
function onConnect(sess) {
console.log('onConnect');
var wi = $rootScope.loginInfo;
sess.authreq(wi.channel).then(
function(challenge) {
console.log("onConnect().then()");
var secret = ab.deriveKey(wi.secret,JSON.parse(challenge).authextra);
var signature = sess.authsign(challenge, secret);
sess.auth(signature).then(onAuth, ab.log);
},ab.log
);
}
function onAuth(permission) {
$rootScope.isLoggedIn = 'true';
console.log("authentication complete");
// do whatever you need when you are logged in..
}
}
};
}])
然后,您需要服务器端的代码(正如您所指出的)。我假设您的服务器端web套接字是php编码。我没办法,已经一年多没有用php编写代码了。在我的例子中,我使用python,包括autobahn gear,然后子类WampCraServerProtocol,并替换一些方法(onSessionOpen、getAuthPermissions、getAuthSecret、onAuthenticated和onClose),正如您所想象的,这些是敲门的角代码的“另一面”。我认为autobahn不支持php,因此,您必须自己对身份验证的服务器端进行编程
无论如何,我的后端工作起来更像@oberstat所描述的。我通过老式的https建立身份验证,创建会话cookie,然后执行ajax请求“票证”(这是一个临时名称/密码,我与web身份验证会话关联)。它是一次性名称/密码,必须在几秒钟内使用,否则将消失。关键是我不必保留用户的凭证,我已经有了cookie/会话,我可以创建可以使用的票据。这也有一个巧妙的副作用,我的ajax se
class AuthReqController extends BaseTopic {
public function subscribe ($connection, $topic) { }
public function publish ($connection, $topic, $message, array $exclude, array $eligible) { }
public function unsubscribe ($connection, $topic) { }
public function call ($connection, $id, $topic, array $params) {
switch ($topic) {
case 'http://api.wamp.ws/procedure#authreq':
return $this->getAuthenticationRequest($connection, $id, $topic, $params);
case 'http://api.wamp.ws/procedure#auth':
return $this->processAuthSignature($connection, $id, $topic, $params);
}
}
/**
* Process the authentication request
*/
private function getAuthenticationRequest ($connection, $id, $topic, $params) {
$auth_key = $params[0]; // A generated temporary auth key
$tmpUser = $this->getTempUser($auth_key); // Get the key value pair as persisted from the temporary store.
if ($tmpUser) {
$info = [
'authkey' => $tmpUser->username,
'secret' => $tmpUser->secret,
'timestamp' => time()
];
$connection->callResult($id, $info);
} else {
$connection->callError($id, $topic, array('User not found'));
}
return true;
}
/**
* Process the final step in the authentication
*/
private function processAuthSignature ($connection, $id, $topic, $params) {
// This should do something smart to validate this response.
// The session should be ours right now. So store the Auth::user()
$connection->user = Auth::user(); // A null object is stored.
$connection->callResult($id, array('msg' => 'connected'));
}
private function getTempUser($auth_key) {
return TempAuth::findOrFail($auth_key);
}
}