diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 6f0c218974..9c7584f8c4 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -275,6 +275,7 @@ $lang->admin->menu->mail = array('link' => 'Email|mail|index', 'subModule' $lang->admin->menu->clearData = array('link' => 'Clear data|admin|cleardata'); $lang->admin->menu->convert = array('link' => 'Import|convert|index', 'subModule' => 'convert'); $lang->admin->menu->trashes = array('link' => 'Trash|action|trash', 'subModule' => 'action'); +$lang->admin->menu->sso = array('link' => 'SSO|sso|browse', 'subModule' => 'sso'); $lang->convert = new stdclass(); $lang->upgrade = new stdclass(); @@ -282,6 +283,7 @@ $lang->action = new stdclass(); $lang->extension = new stdclass(); $lang->editor = new stdclass(); $lang->mail = new stdclass(); +$lang->sso = new stdclass(); $lang->convert->menu = $lang->admin->menu; $lang->upgrade->menu = $lang->admin->menu; @@ -289,6 +291,7 @@ $lang->action->menu = $lang->admin->menu; $lang->extension->menu = $lang->admin->menu; $lang->editor->menu = $lang->admin->menu; $lang->mail->menu = $lang->admin->menu; +$lang->sso->menu = $lang->admin->menu; /* Groups. */ $lang->menugroup = new stdclass(); diff --git a/module/common/lang/menuOrder.php b/module/common/lang/menuOrder.php index 4a77b827aa..bd9e626afa 100644 --- a/module/common/lang/menuOrder.php +++ b/module/common/lang/menuOrder.php @@ -110,11 +110,13 @@ $lang->admin->menuOrder[5] = 'index'; $lang->admin->menuOrder[10] = 'extension'; $lang->admin->menuOrder[15] = 'editor'; $lang->admin->menuOrder[20] = 'mail'; -$lang->admin->menuOrder[25] = 'convert'; -$lang->admin->menuOrder[30] = 'trashes'; +$lang->admin->menuOrder[25] = 'sso'; +$lang->admin->menuOrder[30] = 'convert'; +$lang->admin->menuOrder[35] = 'trashes'; $lang->convert->menuOrder = $lang->admin->menuOrder; $lang->upgrade->menuOrder = $lang->admin->menuOrder; $lang->action->menuOrder = $lang->admin->menuOrder; $lang->extension->menuOrder = $lang->admin->menuOrder; $lang->editor->menuOrder = $lang->admin->menuOrder; $lang->mail->menuOrder = $lang->admin->menuOrder; +$lang->sso->menuOrder = $lang->admin->menuOrder; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index e9406a873d..bc6d1168af 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -275,6 +275,7 @@ $lang->admin->menu->mail = array('link' => '发信|mail|index', 'subModule' $lang->admin->menu->clearData = array('link' => '清除数据|admin|cleardata'); $lang->admin->menu->convert = array('link' => '导入|convert|index', 'subModule' => 'convert'); $lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action'); +$lang->admin->menu->sso = array('link' => '单点登录|sso|browse', 'subModule' => 'sso'); $lang->convert = new stdclass(); $lang->upgrade = new stdclass(); @@ -282,6 +283,7 @@ $lang->action = new stdclass(); $lang->extension = new stdclass(); $lang->editor = new stdclass(); $lang->mail = new stdclass(); +$lang->sso = new stdclass(); $lang->convert->menu = $lang->admin->menu; $lang->upgrade->menu = $lang->admin->menu; @@ -289,6 +291,7 @@ $lang->action->menu = $lang->admin->menu; $lang->extension->menu = $lang->admin->menu; $lang->editor->menu = $lang->admin->menu; $lang->mail->menu = $lang->admin->menu; +$lang->sso->menu = $lang->admin->menu; /* 菜单分组。*/ $lang->menugroup = new stdclass(); @@ -311,6 +314,7 @@ $lang->menugroup->action = 'admin'; $lang->menugroup->extension = 'admin'; $lang->menugroup->editor = 'admin'; $lang->menugroup->mail = 'admin'; +$lang->menugroup->sso = 'admin'; /* 错误提示信息。*/ $lang->error = new stdclass(); diff --git a/module/common/model.php b/module/common/model.php index 1a86b1a879..45ed64d876 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -130,7 +130,7 @@ class commonModel extends model { if($module == 'user' and strpos('login|logout|deny', $method) !== false) return true; if($module == 'api' and $method == 'getsessionid') return true; - if($module == 'sso') return true; + if($module == 'sso' and strpos('auth|depts|users', $method) !== false) return true; if($this->loadModel('user')->isLogon()) { diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 78c3ed7998..f707009979 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -51,6 +51,8 @@ $lang->moduleOrder[140] = 'tree'; $lang->moduleOrder[145] = 'api'; $lang->moduleOrder[150] = 'file'; $lang->moduleOrder[155] = 'misc'; +$lang->moduleOrder[160] = 'sso'; +$lang->moduleOrder[165] = 'webapp'; $lang->resource = new stdclass(); @@ -615,6 +617,18 @@ $lang->resource->admin->checkDB = 'checkDB'; $lang->admin->methodOrder[0] = 'index'; $lang->admin->methodOrder[5] = 'checkDB'; +/* SSO. */ +$lang->resource->sso = new stdclass(); +$lang->resource->sso->browse = 'browse'; +$lang->resource->sso->create = 'create'; +$lang->resource->sso->edit = 'edit'; +$lang->resource->sso->delete = 'delete'; + +$lang->sso->methodOrder[0] = 'browse'; +$lang->sso->methodOrder[5] = 'create'; +$lang->sso->methodOrder[10] = 'edit'; +$lang->sso->methodOrder[15] = 'delete'; + /* Extension. */ $lang->resource->extension = new stdclass(); $lang->resource->extension->browse = 'browse'; diff --git a/module/sso/config.php b/module/sso/config.php new file mode 100644 index 0000000000..b8c85b1a0c --- /dev/null +++ b/module/sso/config.php @@ -0,0 +1,3 @@ +sso->create->requiredFields = 'title,code,key,ip'; +$config->sso->edit->requiredFields = 'title,key,ip'; diff --git a/module/sso/control.php b/module/sso/control.php index d9d2e69ede..6511fafd64 100644 --- a/module/sso/control.php +++ b/module/sso/control.php @@ -1,21 +1,102 @@ view->title = $this->lang->sso->browse; + $this->view->auths = $this->sso->getAuths(); + $this->display(); + } + + /** + * Create auth. + * + * @access public + * @return void + */ + public function create() + { + if(!empty($_POST)) { - $account = ''; - $password = ''; - if($this->post->account) $account = $this->post->account; - if($this->get->account) $account = $this->get->account; - if($this->post->password) $password = $this->post->password; - if($this->get->password) $password = $this->get->password; + if(!$this->post->title) die(js::alert($this->lang->sso->error->title)); + if(!$this->post->code) die(js::alert($this->lang->sso->error->code)); + if(!$this->post->ip) die(js::alert($this->lang->sso->error->ip)); + + $this->sso->createAuth(); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate(inlink('browse'), 'parent')); + } + $this->view->title = $this->lang->sso->create; + $this->view->key = $this->sso->createKey(); + $this->display(); + } + + /** + * Edit auth. + * + * @param string $code + * @access public + * @return void + */ + public function edit($code) + { + if(!empty($_POST)) + { + if(!$this->post->title) die(js::alert($this->lang->sso->error->title)); + if(!$this->post->ip) die(js::alert($this->lang->sso->error->ip)); + + $this->sso->updateAuth($code); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate(inlink('browse'), 'parent')); } - $user = $this->loadModel('user')->identify($account, $password); + $this->view->auth = $this->sso->getAuth($code); + $this->view->code = $code; + $this->display(); + } + + /** + * Delete auth. + * + * @param string $code + * @param string $confirm + * @access public + * @return void + */ + public function delete($code, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->sso->confirmDelete, inlink('delete', "code=$code&confirm=yes"))); + } + else + { + $this->sso->deleteAuth($code); + die(js::locate(inlink('browse'), 'parent')); + } + } + + /** + * Auth user. + * + * @param string $app + * @access public + * @return void + */ + public function auth($app) + { + $user = $this->sso->identify($app); if($user) { + $dept = $this->loadModel('dept')->getByID($user->dept); + $user->deptName = $dept ? $dept->name : ''; + $response['status'] = 'success'; $response['data'] = json_encode($user); $this->send($response); @@ -26,11 +107,51 @@ class sso extends control $this->send($response); } - public function depts($key) + /** + * Get all departments. + * + * @param string $app + * @access public + * @return void + */ + public function depts($app) { + if($this->post->key) $key = $this->post->key; + if($this->get->key) $key = $this->get->key; + if($this->sso->checkIP($app) and $this->sso->getAppKey($app) == $key) + { + $depts = $this->sso->getAllDepts(); + $response['status'] = 'success'; + $response['data'] = json_encode($depts); + $this->send($response); + } + + $response['status'] = 'fail'; + $response['data'] = 'key error'; + $this->send($response); } - public function users($key) + /** + * Get all users. + * + * @param string $app + * @access public + * @return void + */ + public function users($app) { + if($this->post->key) $key = $this->post->key; + if($this->get->key) $key = $this->get->key; + if($this->sso->checkIP($app) and $this->sso->getAppKey($app) == $key) + { + $depts = $this->sso->getAllUsers(); + $response['status'] = 'success'; + $response['data'] = json_encode($depts); + $this->send($response); + } + + $response['status'] = 'fail'; + $response['data'] = 'key error'; + $this->send($response); } } diff --git a/module/sso/js/common.js b/module/sso/js/common.js new file mode 100644 index 0000000000..c72ce145b0 --- /dev/null +++ b/module/sso/js/common.js @@ -0,0 +1,11 @@ +function createKey() +{ + var chars = '0123456789abcdefghiklmnopqrstuvwxyz'.split(''); + var key = ''; + for(var i=0; i < 32; i++) + { + key += chars[Math.floor(Math.random() * chars.length)]; + } + $('#key').val(key); + return false; +} diff --git a/module/sso/lang/en.php b/module/sso/lang/en.php new file mode 100644 index 0000000000..370bd7ff36 --- /dev/null +++ b/module/sso/lang/en.php @@ -0,0 +1,24 @@ +sso->common = 'SSO'; +$lang->sso->browse = 'Auth list'; +$lang->sso->create = 'Create auth'; +$lang->sso->edit = 'Edit auth'; +$lang->sso->delete = 'Delete auth'; +$lang->sso->code = 'Code'; +$lang->sso->title = 'Name'; +$lang->sso->key = 'Key'; +$lang->sso->ip = 'IP list'; +$lang->sso->createKey = 'Get new key'; + +$lang->sso->confirmDelete = 'Are you sure to delete this auth?'; + +$lang->sso->note = new stdClass(); +$lang->sso->note->title = 'site name'; +$lang->sso->note->code = 'site code'; +$lang->sso->note->ip = "Use comma between two IPs, and support IP segment, for example 192.168.1.*"; + +$lang->sso->error = new stdClass(); +$lang->sso->error->title = 'Please input name'; +$lang->sso->error->code = 'Please input code'; +$lang->sso->error->key = 'Please input key'; +$lang->sso->error->ip = 'Please input IP'; diff --git a/module/sso/lang/zh-cn.php b/module/sso/lang/zh-cn.php new file mode 100644 index 0000000000..9adf48c5d3 --- /dev/null +++ b/module/sso/lang/zh-cn.php @@ -0,0 +1,24 @@ +sso->common = '单点登录'; +$lang->sso->browse = '授权列表'; +$lang->sso->create = '创建授权'; +$lang->sso->edit = '编辑授权'; +$lang->sso->delete = '删除授权'; +$lang->sso->code = '代号'; +$lang->sso->title = '名称'; +$lang->sso->key = '密钥'; +$lang->sso->ip = 'IP列表'; +$lang->sso->createKey = '重新生成密钥'; + +$lang->sso->confirmDelete = '您确定删除该授权吗?'; + +$lang->sso->note = new stdClass(); +$lang->sso->note->title = '授权站点名称'; +$lang->sso->note->code = '授权站点代号'; +$lang->sso->note->ip = "允许该站点使用这些ip访问,多个ip使用逗号隔开。支持IP段,如192.168.1.*"; + +$lang->sso->error = new stdClass(); +$lang->sso->error->title = '名称不能为空'; +$lang->sso->error->code = '代号不能为空'; +$lang->sso->error->key = '密钥不能为空'; +$lang->sso->error->ip = 'IP列表不能为空'; diff --git a/module/sso/lang/zh-tw.php b/module/sso/lang/zh-tw.php new file mode 100644 index 0000000000..e69de29bb2 diff --git a/module/sso/model.php b/module/sso/model.php index 8cf7c30425..e4c9960201 100644 --- a/module/sso/model.php +++ b/module/sso/model.php @@ -1,5 +1,177 @@ config->sso; + unset($auths->create); + unset($auths->edit); + return $auths; + } + /** + * Get auth by code. + * + * @param string $code + * @access public + * @return object + */ + public function getAuth($code) + { + return $this->config->sso->$code; + } + + /** + * Create auth. + * + * @access public + * @return void + */ + public function createAuth() + { + $auth = fixer::input('post')->get(); + $items = new stdClass(); + $items->{$this->post->code} = $auth; + $this->loadModel('setting')->setItems("system.sso", $items); + } + + /** + * Update auth. + * + * @param int $code + * @access public + * @return void + */ + public function updateAuth($code) + { + $auth = fixer::input('post')->get(); + $items = new stdClass(); + $items->$code = $auth; + $this->loadModel('setting')->setItems("system.sso", $items); + } + + /** + * Delete auth. + * + * @param string $code + * @access public + * @return void + */ + public function deleteAuth($code) + { + $this->loadModel('setting')->deleteItems("owner=system&module=sso§ion=$code"); + } + + /** + * Get key of app. + * + * @param string $app + * @access public + * @return object + */ + public function getAppKey($app) + { + return $this->config->sso->$app->key; + } + + /** + * Check ip if is allowed. + * + * @param string $app + * @access public + * @return bool + */ + public function checkIP($app) + { + $ipParts = explode('.', $_SERVER['REMOTE_ADDR']); + $allowIPs = explode(',', $this->config->sso->$app->ip); + + foreach($allowIPs as $allowIP) + { + $allowIPParts = explode('.', $allowIP); + foreach($allowIPParts as $key => $allowIPPart) + { + if($allowIPPart == '*') $allowIPParts[$key] = $ipParts[$key]; + } + if(implode('.', $allowIPParts) == $_SERVER['REMOTE_ADDR']) return true; + } + return false; + } + + /** + * Identify user. + * + * @param string $app + * @access public + * @return bool | object + */ + public function identify($app) + { + if(!$this->checkIP($app)) return false; + + $key = $this->getAppKey($app); + + $account = ''; + $authcode = ''; + if($this->post->account) $account = $this->post->account; + if($this->get->account) $account = $this->get->account; + if($this->post->authcode) $authcode = $this->post->authcode; + if($this->get->authcode) $authcode = $this->get->authcode; + + if(!$account or !$authcode or !$key) return false; + + $user = $this->dao->select('*')->from(TABLE_USER) + ->where('account')->eq($account) + ->andWhere('deleted')->eq(0) + ->fetch(); + + if($user) + { + $code = md5($user->password . $key); + if($code == $authcode) return $user; + } + + return false; + } + + /** + * Create a key. + * + * @access public + * @return string + */ + public function createKey() + { + return md5(rand()); + } + + /** + * Get all departments. + * + * @access public + * @return object + */ + public function getAllDepts() + { + return $this->dao->select('*')->from(TABLE_DEPT)->fetchAll(); + } + + /** + * Get all users. + * + * @access public + * @return object + */ + public function getAllUsers() + { + return $this->dao->select('*')->from(TABLE_USER) + ->where('deleted')->eq(0) + ->fetchAll(); + } } diff --git a/module/sso/view/browse.html.php b/module/sso/view/browse.html.php new file mode 100644 index 0000000000..f1f4209202 --- /dev/null +++ b/module/sso/view/browse.html.php @@ -0,0 +1,35 @@ + +
| sso->title;?> | +sso->code;?> | +sso->key;?> | +sso->ip;?> | +actions;?> | +
|---|---|---|---|---|
| title?> | ++ | key?> | +ip?> | ++ + | +