Merge pull request #28 from capricornxl/feature/update_to_layui
应用内授权页面独立
This commit is contained in:
commit
2ae4acbffc
|
@ -181,21 +181,6 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
|
||||
yum install -y redis
|
||||
if [[ $? -eq 0 ]]; then
|
||||
gen_password=$(echo "$(hostname)$(date)" |base64)
|
||||
sed -i 's@^requirepass.*@@g' /etc/redis.conf
|
||||
sed -i "/# requirepass foobared/a requirepass ${gen_password}" /etc/redis.conf
|
||||
systemctl restart redis
|
||||
sed -i "s@REDIS_PASSWORD.*@REDIS_PASSWORD = r'${gen_password}'@g" ${SHELL_FOLDER}/conf/local_settings.py
|
||||
echo "安装 redis-server 成功"
|
||||
echo "Redis Server密码是:${gen_password},可在/etc/redis.conf中查到"
|
||||
else
|
||||
echo "安装 redis-server 失败,请重新运行本脚本再试"
|
||||
fi
|
||||
|
||||
|
||||
##修改PIP源为国内
|
||||
mkdir -p ~/.pip
|
||||
cat << EOF > ~/.pip/pip.conf
|
||||
|
|
|
@ -5,26 +5,33 @@
|
|||
|
||||
# ########## AD配置,修改为自己的
|
||||
# AD主机,可以是IP或主机域名,例如可以是: abc.com或172.16.122.1
|
||||
AD_HOST = r'修改成自己的'
|
||||
LDAP_HOST = r'修改成自己的'
|
||||
|
||||
# AD域控的DOMAIN,例如:比如你的域名是abc.com,那么这里的AD_DOMAIN就是:abc
|
||||
# AD域控的DOMAIN,例如:比如你的域名是abc.com,那么这里的LDAP_DOMAIN就是:abc
|
||||
# NTLM认证必须是domain\username
|
||||
AD_DOMAIN = r'修改成自己的'
|
||||
LDAP_DOMAIN = r'修改成自己的'
|
||||
|
||||
# 用于登录AD做用户信息处理的账号,需要有修改用户账号密码或信息的权限。
|
||||
# AD账号,例如:pwdadmin
|
||||
AD_LOGIN_USER = r'修改成自己的'
|
||||
LDAP_LOGIN_USER = r'修改成自己的'
|
||||
# 密码
|
||||
AD_LOGIN_USER_PWD = r'修改为自己的'
|
||||
LDAP_LOGIN_USER_PWD = r'修改为自己的'
|
||||
|
||||
# BASE DN,账号的查找DN路径,例如:'DC=abc,DC=com',可以指定到OU之下,例如:'OU=RD,DC=abc,DC=com'。
|
||||
BASE_DN = r'修改成自己的'
|
||||
|
||||
# ldap的search_filter,如果需要修改,请保持用户账号部分为 点位符{} (代码中通过占位符引入账号)
|
||||
# 例如,AD的用户账号属性是sAMAccountName,那么匹配的账号请配置成sAMAccountName={}
|
||||
# LDAP中用户账号属性可能是uuid,那么匹配的账号请配置成uuid={}
|
||||
# 默认配置是AD环境的
|
||||
SEARCH_FILTER = r'(&(objectclass=user)(sAMAccountName={}))'
|
||||
|
||||
# 是否启用SSL,
|
||||
# 注意:AD必须使用SSL才能修改密码(这里被坑了N久...),自行部署下AD的证书服务,并颁发CA证书,重启服务器生效。具体教程百度一下,有很多。
|
||||
AD_USE_SSL = True
|
||||
# 注意:AD中必须使用SSL才能修改密码(这里被坑了N久...),自行部署下AD的证书服务,并颁发CA证书,重启服务器生效。具体教程百度一下,有很多。
|
||||
# 如果使用Openldap,这里根据实际情况调整
|
||||
LDAP_USE_SSL = True
|
||||
# 连接的端口,如果启用SSL默认是636,否则就是389
|
||||
AD_CONN_PORT = 636
|
||||
LDAP_CONN_PORT = 636
|
||||
|
||||
# 验证的类型
|
||||
# 钉钉 / 企业微信,自行修改
|
||||
|
@ -53,14 +60,8 @@ WEWORK_AGENT_ID = r'修改为自己的'
|
|||
# 应用的Secret
|
||||
WEWORK_AGNET_SECRET = r'修改为自己的'
|
||||
|
||||
# Redis配置
|
||||
# redis的连接地址,redis://<Ip/Host>:<Port>
|
||||
REDIS_LOCATION = r'redis://127.0.0.1:6379'
|
||||
REDIS_PASSWORD = r'修改为自己的'
|
||||
|
||||
|
||||
# 主页域名,钉钉跳转等需要指定域名,格式:pwd.abc.com。
|
||||
# 如果是自定义安装,请修改成自己的域名
|
||||
HOME_URL = 'PWD_SELF_SERVICE_DOMAIN'
|
||||
# 标题
|
||||
# 平台显示的标题
|
||||
TITLE = 'Self-Service'
|
||||
|
|
305668
log/log.log
305668
log/log.log
File diff suppressed because it is too large
Load Diff
|
@ -5,6 +5,7 @@ import resetpwd.views
|
|||
urlpatterns = {
|
||||
path("favicon.ico", RedirectView.as_view(url='static/img/favicon.ico')),
|
||||
path('', resetpwd.views.index, name='index'),
|
||||
path('auth', resetpwd.views.auth, name='auth'),
|
||||
path('resetPassword', resetpwd.views.reset_password, name='resetPassword'),
|
||||
path('unlockAccount', resetpwd.views.unlock_account, name='unlockAccount'),
|
||||
path('messages', resetpwd.views.messages, name='messages'),
|
||||
|
|
243
readme.md
243
readme.md
|
@ -1,5 +1,5 @@
|
|||
### 初学Django时碰到的一个需求,因为公司中很多员工在修改密码之后,有一些关联的客户端或网页中的旧密码没有更新,导致密码在尝试多次之后账号被锁,为了减少这种让人头疼的重置解锁密码的操蛋工作,自己做了一个自助修改小平台。
|
||||
### 水平有限,代码写得不好,但是能用,有需要的可以直接拿去用。
|
||||
### 代码结构不咋样,但是能用,有需要的可以直接拿去用。
|
||||
#### 场景说明:
|
||||
因为本公司AD是早期已经在用,用户的个人信息不是十分全面,例如:用户手机号。
|
||||
钉钉是后来才开始使用,钉钉默认是使用手机号登录。
|
||||
|
@ -14,11 +14,6 @@
|
|||
如果您的场景不是这样,请按自己的需求修改源代码适配。
|
||||
|
||||
|
||||
### 代码提交到:
|
||||
```
|
||||
master
|
||||
```
|
||||
|
||||
### 提示:
|
||||
```
|
||||
AD必须使用SSL才能修改密码(这里被坑了N久...)
|
||||
|
@ -35,26 +30,31 @@ AD必须使用SSL才能修改密码(这里被坑了N久...)
|
|||
+ 重写了用户账号的格式兼容,现在用户账号可以兼容:username、DOMAIN\username、username@abc.com这三种格式。
|
||||
+ 优化了整体的代码逻辑,去掉一些冗余重复的代码。
|
||||
|
||||
|
||||
### 2022/12/16 -- 更新:
|
||||
+ 修改钉钉、企业微信直接通过企业内部免密登录授权或验证的方式实现用户信息的获取,直接通过软件内部工作平台打开,废弃扫码方式(由于API接口的权限问题,一些关键数据已经不再支持通过扫码获取)
|
||||
|
||||
其它没变化,只修复了这个问题~~~~
|
||||
### 2023/01/15 -- 更新:
|
||||
+ 兼容PC与移动端的显示(使用Layui)
|
||||
+ 修复一些BUG
|
||||
|
||||
|
||||
## 线上环境需要的基础环境:
|
||||
+ Python 3.8.9 (可自行下载源码包放到项目目录下,使用一键安装)
|
||||
+ Nginx
|
||||
+ Uwsgi
|
||||
|
||||
### 钉钉
|
||||

|
||||
### 界面效果
|
||||
|
||||
### 微信
|
||||

|
||||
<img alt="截图10" width="500" src="screenshot/QQ截图20230116152954.png">
|
||||
|
||||
<img alt="截图10" width="500" src="screenshot/212473880-4a59c535-85bb-42d2-a99a-899265c83136.png">
|
||||
|
||||
#### 授权或验证成功之后:
|
||||

|
||||
<img alt="截图10" width="500" src="screenshot/212474222-e1c13e1b-bb6f-4523-b040-24a65055d681.png">
|
||||
|
||||
### 移动端
|
||||
<img alt="截图10" width="500" src="screenshot/212474177-dd68b0c9-81cc-4eb0-9196-e760784e3f69.jpg">
|
||||
<img alt="截图10" width="500" src="screenshot/212474293-0cd60898-22c3-4258-ac4c-dfee52a6cf1e.png">
|
||||
|
||||
## 钉钉必要条件:
|
||||
#### 创建企业内部应用
|
||||
|
@ -62,6 +62,8 @@ AD必须使用SSL才能修改密码(这里被坑了N久...)
|
|||
* 应用需要权限:通讯录只读权限、邮箱等个人信息,范围是全部员工或自行选择
|
||||
* 应用安全域名和IP一定要配置,否则无法返回接口数据。
|
||||
|
||||
> **如果想实现进入应用就自动授权,跳转重置页面,可将回调域名指定向pwd.abc.com/auth**
|
||||
|
||||
参考截图配置:
|
||||

|
||||
|
||||
|
@ -74,10 +76,12 @@ AD必须使用SSL才能修改密码(这里被坑了N久...)
|
|||
> 废弃,已经不再需要,如果之前有配置,可以删除!!
|
||||
|
||||
|
||||
|
||||
## 企业微信必要条件:
|
||||
* 创建应用,记录下企业的CorpId,应用的ID和Secret。
|
||||
|
||||
> **如果想实现进入应用就自动授权,跳转重置页面,可将回调域名指定向pwd.abc.com/auth**
|
||||
|
||||
|
||||
参考截图:
|
||||

|
||||
|
||||
|
@ -100,70 +104,11 @@ AD必须使用SSL才能修改密码(这里被坑了N久...)
|
|||
## 使用脚本自动部署:
|
||||
使用脚本自动快速部署,只适合Centos,其它发行版本的Linux请自行修改相关命令。
|
||||
|
||||
|
||||
### 把整个项目目录上传到新的服务器上
|
||||
|
||||
#### 先修改配置文件,按自己实际的配置修改项目配置文件:
|
||||
修改conf/local_settings.py中的参数,按自己的实际参数修改
|
||||
```` python
|
||||
# ########## AD配置,修改为自己的
|
||||
# AD主机,可以是IP或主机域名,例如可以是: abc.com或172.16.122.1
|
||||
AD_HOST = r'修改成自己的'
|
||||
|
||||
# AD域控的DOMAIN名,例如:abc
|
||||
AD_DOMAIN = r'修改成自己的'
|
||||
|
||||
# 用于登录AD做用户信息处理的账号,需要有修改用户账号密码或信息的权限。
|
||||
# AD账号,例如:pwdadmin
|
||||
AD_LOGIN_USER = r'修改成自己的'
|
||||
# 密码
|
||||
AD_LOGIN_USER_PWD = r'修改为自己的'
|
||||
|
||||
# BASE DN,账号的查找DN路径,例如:'DC=abc,DC=com',可以指定到OU之下,例如:'OU=RD,DC=abc,DC=com'。
|
||||
BASE_DN = r'修改成自己的'
|
||||
|
||||
# 是否启用SSL,
|
||||
# 注意:AD必须使用SSL才能修改密码(这里被坑了N久...),自行部署下AD的证书服务,并颁发CA证书,重启服务器生效。具体教程百度一下,有很多。
|
||||
AD_USE_SSL = True
|
||||
# 连接的端口,如果启用SSL默认是636,否则就是389
|
||||
AD_CONN_PORT = 636
|
||||
|
||||
# 扫码验证的类型
|
||||
# 钉钉 / 企业微信,自行修改
|
||||
# 值是:DING / WEWORK
|
||||
AUTH_CODE_TYPE = 'DING'
|
||||
|
||||
# ########## 钉钉 《如果不使用钉钉扫码,可不用配置》##########
|
||||
# 钉钉企业ID <CorpId>,修改为自己的
|
||||
DING_CORP_ID = '修改为自己的'
|
||||
|
||||
# 钉钉企业内部开发,内部H5微应用或小程序,用于读取企业内部用户信息
|
||||
DING_AGENT_ID = r'修改为自己的'
|
||||
DING_APP_KEY = r'修改为自己的'
|
||||
DING_APP_SECRET = r'修改为自己的'
|
||||
|
||||
# 移动应用接入 主要为了实现通过扫码拿到用户的unionid
|
||||
DING_MO_APP_ID = r'修改为自己的'
|
||||
DING_MO_APP_SECRET = r'修改为自己的'
|
||||
|
||||
|
||||
# ####### 企业微信《如果不使用企业微信扫码,可不用配置》 ##########
|
||||
# 企业微信的企业ID
|
||||
WEWORK_CORP_ID = r'修改为自己的'
|
||||
# 应用的AgentId
|
||||
WEWORK_AGENT_ID = r'修改为自己的'
|
||||
# 应用的Secret
|
||||
WEWORK_AGNET_SECRET = r'修改为自己的'
|
||||
|
||||
# Redis配置
|
||||
# redis的连接地址,redis://<Ip/Host>:<Port>
|
||||
REDIS_LOCATION = r'redis://127.0.0.1:6379'
|
||||
REDIS_PASSWORD = r'12345678'
|
||||
|
||||
# 主页域名,钉钉跳转等需要指定域名,格式:pwd.abc.com。
|
||||
# 如果是自定义安装,请修改成自己的域名
|
||||
HOME_URL = 'PWD_SELF_SERVICE_DOMAIN'
|
||||
````
|
||||
### 执行部署脚本
|
||||
```shell
|
||||
chmod +x auto-install.sh
|
||||
|
@ -180,72 +125,13 @@ chmod +x auto-install.sh
|
|||
|
||||
项目目录下的requestment文件里记录了所依赖的相关python模块,安装方法:
|
||||
>/usr/local/python3/bin/pip3 install -r requestment
|
||||
>
|
||||
等待所有模块安装完成之后进行下一步。
|
||||
|
||||
等待所有模块安装完成之后进行下一步。
|
||||
|
||||
### 按自己实际的配置修改项目配置参数:
|
||||
修改conf/local_settings.py中的参数,按自己的实际参数修改
|
||||
|
||||
```` python
|
||||
# ########## AD配置,修改为自己的
|
||||
# AD主机,可以是IP或主机域名,例如可以是: abc.com或172.16.122.1
|
||||
AD_HOST = r'修改成自己的'
|
||||
|
||||
# AD域控的DOMAIN名,例如:abc
|
||||
AD_DOMAIN = r'修改成自己的'
|
||||
|
||||
# 用于登录AD做用户信息处理的账号,需要有修改用户账号密码或信息的权限。
|
||||
# AD账号,例如:pwdadmin
|
||||
AD_LOGIN_USER = r'修改成自己的'
|
||||
# 密码
|
||||
AD_LOGIN_USER_PWD = r'修改为自己的'
|
||||
|
||||
# BASE DN,账号的查找DN路径,例如:'DC=abc,DC=com',可以指定到OU之下,例如:'OU=RD,DC=abc,DC=com'。
|
||||
BASE_DN = r'修改成自己的'
|
||||
|
||||
# 是否启用SSL,
|
||||
# 注意:AD必须使用SSL才能修改密码(这里被坑了N久...),自行部署下AD的证书服务,并颁发CA证书,重启服务器生效。具体教程百度一下,有很多。
|
||||
AD_USE_SSL = True
|
||||
# 连接的端口,如果启用SSL默认是636,否则就是389
|
||||
AD_CONN_PORT = 636
|
||||
|
||||
# 扫码验证的类型
|
||||
# 钉钉 / 企业微信,自行修改
|
||||
# 值是:DING / WEWORK
|
||||
AUTH_CODE_TYPE = 'DING'
|
||||
|
||||
# ########## 钉钉 《如果不使用钉钉扫码,可不用配置》##########
|
||||
# 钉钉企业ID <CorpId>,修改为自己的
|
||||
DING_CORP_ID = '修改为自己的'
|
||||
|
||||
# 钉钉企业内部开发,内部H5微应用或小程序,用于读取企业内部用户信息
|
||||
DING_AGENT_ID = r'修改为自己的'
|
||||
DING_APP_KEY = r'修改为自己的'
|
||||
DING_APP_SECRET = r'修改为自己的'
|
||||
|
||||
# 移动应用接入 主要为了实现通过扫码拿到用户的unionid
|
||||
DING_MO_APP_ID = r'修改为自己的'
|
||||
DING_MO_APP_SECRET = r'修改为自己的'
|
||||
|
||||
|
||||
# ####### 企业微信《如果不使用企业微信扫码,可不用配置》 ##########
|
||||
# 企业微信的企业ID
|
||||
WEWORK_CORP_ID = r'修改为自己的'
|
||||
# 应用的AgentId
|
||||
WEWORK_AGENT_ID = r'修改为自己的'
|
||||
# 应用的Secret
|
||||
WEWORK_AGNET_SECRET = r'修改为自己的'
|
||||
|
||||
# Redis配置
|
||||
# redis的连接地址,redis://<Ip/Host>:<Port>
|
||||
REDIS_LOCATION = r'redis://127.0.0.1:6379'
|
||||
REDIS_PASSWORD = r'12345678'
|
||||
|
||||
# 主页域名,钉钉跳转等需要指定域名,格式:pwd.abc.com。
|
||||
# 如果是自定义安装,请修改成自己的域名
|
||||
HOME_URL = 'PWD_SELF_SERVICE_DOMAIN'
|
||||
````
|
||||
```
|
||||
|
||||
安装完依赖后,直接执行
|
||||
/usr/local/python3/bin/python3 manager.py runserver x.x.x.x:8000
|
||||
|
@ -254,97 +140,22 @@ HOME_URL = 'PWD_SELF_SERVICE_DOMAIN'
|
|||
|
||||
## 修改uwsig.ini配置:
|
||||
IP和路径按自己实际路径修改
|
||||
````ini
|
||||
[uwsgi]
|
||||
http-socket = PWD_SELF_SERVICE_IP:PWD_SELF_SERVICE_PORT
|
||||
|
||||
chdir = PWD_SELF_SERVICE_HOME
|
||||
|
||||
env=DJANGO_SETTINGS_MODULE=pwdselfservice.settings
|
||||
|
||||
module = pwdselfservice.wsgi:application
|
||||
|
||||
master = true
|
||||
|
||||
processes = 4
|
||||
|
||||
threads = 4
|
||||
|
||||
max-requests = 2000
|
||||
|
||||
chmod-socket = 755
|
||||
|
||||
vacuum = true
|
||||
|
||||
#设置缓冲
|
||||
post-buffering = 4096
|
||||
|
||||
#设置静态文件
|
||||
static-map = /static=PWD_SELF_SERVICE_HOME/static
|
||||
|
||||
#设置日志目录
|
||||
daemonize = PWD_SELF_SERVICE_HOME/log/uwsgi.log
|
||||
````
|
||||
```
|
||||
|
||||
## 通过uwsgiserver启动:
|
||||
其中PWD_SELF_SERVICE_HOME是你自己的服务器当前项目的目录,请自行修改
|
||||
将以下脚本修改完之后,复制到/etc/init.d/,给予执行权限。
|
||||
uwsgiserver:
|
||||
```shell
|
||||
#!/bin/sh
|
||||
|
||||
INI="PWD_SELF_SERVICE_HOME/uwsgi.ini"
|
||||
UWSGI="/usr/share/python-3.6.9/bin/uwsgi"
|
||||
PSID=`ps aux | grep "uwsgi"| grep -v "grep" | wc -l`
|
||||
|
||||
if [ ! -n "$1" ]
|
||||
then
|
||||
content="Usages: sh uwsgiserver [start|stop|restart]"
|
||||
echo -e "\033[31m $content \033[0m"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ $1 = start ]
|
||||
then
|
||||
if [ `eval $PSID` -gt 4 ]
|
||||
then
|
||||
content="uwsgi is running!"
|
||||
echo -e "\033[32m $content \033[0m"
|
||||
exit 0
|
||||
else
|
||||
$UWSGI $INI
|
||||
content="Start uwsgi service [OK]"
|
||||
echo -e "\033[32m $content \033[0m"
|
||||
fi
|
||||
|
||||
elif [ $1 = stop ];then
|
||||
if [ `eval $PSID` -gt 4 ];then
|
||||
killall -9 uwsgi
|
||||
fi
|
||||
content="Stop uwsgi service [OK]"
|
||||
echo -e "\033[32m $content \033[0m"
|
||||
elif [ $1 = restart ];then
|
||||
if [ `eval $PSID` -gt 4 ];then
|
||||
killall -9 uwsgi
|
||||
fi
|
||||
$UWSGI --ini $INI
|
||||
content="Restart uwsgi service [OK]"
|
||||
echo -e "\033[32m $content \033[0m"
|
||||
|
||||
else
|
||||
content="Usages: sh uwsgiserver [start|stop|restart]"
|
||||
echo -e "\033[31m $content \033[0m"
|
||||
fi
|
||||
|
||||
````
|
||||
脚本内的路径按自己实际情况修改
|
||||
请自行修改将脚本修改完之后
|
||||
复制到/etc/init.d/,给予执行权限。
|
||||
执行/etc/init.d/uwsigserver start 启动
|
||||
```
|
||||
|
||||
## 自行部署Nginx,然后添加Nginx配置
|
||||
#### Nginx配置:
|
||||
Nginx Server配置:
|
||||
* proxy_pass的IP地址改成自己的服务器IP
|
||||
* 配置可自己写一个vhost或直接加在nginx.conf中
|
||||
```` nginx
|
||||
``` nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name pwd.abc.com;
|
||||
|
@ -358,5 +169,5 @@ server {
|
|||
}
|
||||
access_log off;
|
||||
}
|
||||
````
|
||||
```
|
||||
- 执行Nginx reload操作,重新加载配置
|
|
@ -91,7 +91,7 @@ def ops_account(ad_ops, request, msg_template, home_url, username, new_password)
|
|||
unlock_status, result = ad_ops.ad_unlock_user_by_account(username)
|
||||
if unlock_status:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "密码己修改成功,请妥善保管。你可以点击返回主页或直接关闭此页面!",
|
||||
'msg': "密码己修改成功,请妥善保管。你可以点击修改密码或直接关闭此页面!",
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
}
|
||||
|
@ -99,8 +99,8 @@ def ops_account(ad_ops, request, msg_template, home_url, username, new_password)
|
|||
else:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "密码未修改/重置成功,错误信息:{}".format(result),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
else:
|
||||
|
@ -115,14 +115,14 @@ def ops_account(ad_ops, request, msg_template, home_url, username, new_password)
|
|||
else:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "账号未能解锁,错误信息:{}".format(result),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
except LDAPException as l_e:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "账号未能解锁,错误信息:{}".format(l_e),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
|
|
@ -43,10 +43,7 @@ scan_params = PARAMS()
|
|||
_ops = scan_params.ops
|
||||
|
||||
|
||||
def index(request):
|
||||
"""
|
||||
用户自行修改密码/首页
|
||||
"""
|
||||
def auth(request):
|
||||
home_url = '%s://%s' % (request.scheme, HOME_URL)
|
||||
corp_id = scan_params.corp_id
|
||||
app_id = scan_params.app_id
|
||||
|
@ -57,6 +54,29 @@ def index(request):
|
|||
app_type = INTEGRATION_APP_TYPE
|
||||
global_title = TITLE
|
||||
|
||||
if request.method == 'GET':
|
||||
code = request.GET.get('code', None)
|
||||
username = request.GET.get('username', None)
|
||||
# 如果满足,说明已经授权免密登录
|
||||
if username and code and request.session.get(username) == code:
|
||||
context = {'global_title': TITLE,
|
||||
'username': username,
|
||||
'code': code,
|
||||
}
|
||||
return render(request, 'reset_password.html', context)
|
||||
return render(request, 'auth.html', locals())
|
||||
else:
|
||||
logger.error('[异常] 请求方法:%s,请求路径%s' % (request.method, request.path))
|
||||
|
||||
|
||||
def index(request):
|
||||
"""
|
||||
用户自行修改密码/首页
|
||||
"""
|
||||
home_url = '%s://%s' % (request.scheme, HOME_URL)
|
||||
scan_app = scan_params.AUTH_APP
|
||||
global_title = TITLE
|
||||
|
||||
if request.method == 'GET':
|
||||
return render(request, 'index.html', locals())
|
||||
else:
|
||||
|
@ -75,8 +95,8 @@ def index(request):
|
|||
logger.error('[异常] 请求方法:%s,请求路径:%s,错误信息:%s' % (request.method, request.path, _msg))
|
||||
context = {'global_title': TITLE,
|
||||
'msg': _msg,
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
# 格式化用户名
|
||||
|
@ -84,8 +104,8 @@ def index(request):
|
|||
if _ is False:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': username,
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
# 检测账号状态
|
||||
|
@ -93,16 +113,16 @@ def index(request):
|
|||
if not auth_status:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': str(auth_result),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
return ops_account(AdOps(), request, msg_template, home_url, username, new_password)
|
||||
else:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "请从主页进行修改密码操作或扫码验证用户信息。",
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'msg': "不被接受的认证信息,请重新尝试认证授权。",
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
||||
|
@ -130,9 +150,9 @@ def reset_password(request):
|
|||
else:
|
||||
logger.error('[异常] 请求方法:%s,请求路径:%s,未能拿到Code。' % (request.method, request.path))
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "错误,临时授权码己失效,请从主页重新开始登录授权..",
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'msg': "错误,临时授权码己失效,请尝试重新认证授权..",
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
try:
|
||||
|
@ -163,8 +183,8 @@ def reset_password(request):
|
|||
if not _:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': email,
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
||||
|
@ -172,8 +192,8 @@ def reset_password(request):
|
|||
if _ is False:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': username,
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
||||
|
@ -189,8 +209,8 @@ def reset_password(request):
|
|||
context = {'global_title': TITLE,
|
||||
'msg': "{},您好,企业{}中未能找到您账号的邮箱配置,请联系HR完善信息。".format(
|
||||
user_info.get('name'), scan_params.AUTH_APP),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
||||
|
@ -215,9 +235,9 @@ def reset_password(request):
|
|||
del request.session[username]
|
||||
else:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "认证已经失效,请从主页重新进行操作。",
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'msg': "认证已经失效,可尝试从重新认证授权。",
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
||||
|
@ -242,8 +262,8 @@ def unlock_account(request):
|
|||
else:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "{},您好,当前会话可能已经过期,请再试一次吧。".format(username),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
||||
|
@ -265,9 +285,9 @@ def unlock_account(request):
|
|||
del request.session[username]
|
||||
else:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': "认证已经失效,请从主页重新进行操作。",
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'msg': "认证已经失效,请尝试从重新进行认证授权。",
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return render(request, msg_template, context)
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 868 KiB |
Binary file not shown.
Before Width: | Height: | Size: 219 KiB |
|
@ -0,0 +1,41 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% block headerjs %}<script type="text/javascript" src="{% static 'js/dingtalk.open.js' %}"></script>{% endblock %}
|
||||
{% block paneltitle %}请稍后,授权信息认证中{% endblock %}
|
||||
{% block middleblock %}
|
||||
{% endblock %}
|
||||
{% block footerjs %}
|
||||
<script src="{% static 'layui/layui.js' %}"></script>
|
||||
<script>
|
||||
layui.use(['form', 'jquery', 'layer'], function () {
|
||||
let layer = layui.layer,
|
||||
$ = layui.jquery;
|
||||
let re_url= ""
|
||||
let index_load = layer.load(1, {shade: 0.4});
|
||||
{% if app_type == 'DING' %}
|
||||
dd.ready(() => {
|
||||
dd.runtime.permission.requestAuthCode({corpId: '{{ corp_id }}'}).then((result) => {
|
||||
re_url = '/resetPassword?code=' + result.code
|
||||
window.parent.parent.location.href=re_url;
|
||||
}).catch(err => {
|
||||
layer.close(index_load)
|
||||
layer.open({
|
||||
title : '出错啦!'
|
||||
,content: err
|
||||
,btn: '关闭'
|
||||
,btnAlign: 'c'
|
||||
,yes: function(){
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
{% elif app_type == 'WEWORK' %}
|
||||
$(function () {
|
||||
re_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={{ app_id }}&agentid={{ agent_id }}&redirect_uri={{ redirect_url }}&response_type=code&scope=snsapi_privateinfo&state=#wechat_redirect"
|
||||
window.parent.parent.location.href=re_url;
|
||||
})
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -34,7 +34,7 @@
|
|||
</div>
|
||||
<div class="layui-form-item a-middle-text">
|
||||
<span class="layui-breadcrumb">
|
||||
<a class="layui-text" id="redirect_url" href=""><i class="layui-icon layui-icon-refresh-3"></i> 重置/解锁账号</a>
|
||||
<a class="layui-text" id="redirect_url" href="/auth"><i class="layui-icon layui-icon-refresh-3"></i> 重置/解锁账号</a>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -53,39 +53,7 @@
|
|||
<script>
|
||||
layui.use(['form', 'jquery', 'layer'], function () {
|
||||
let form = layui.form,
|
||||
layer = layui.layer,
|
||||
$ = layui.jquery;
|
||||
if ('{{ app_type }}' === 'DING') {
|
||||
let re_url= ""
|
||||
window.onload = function () {
|
||||
if (dd.env.platform !== 'notInDingTalk') {
|
||||
dd.ready(() => {
|
||||
dd.runtime.permission.requestAuthCode({corpId: '{{ corp_id }}'}).then((result) => {
|
||||
re_url = '/resetPassword?code=' + result.code
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
}).finally(() => {
|
||||
document.getElementById("redirect_url").setAttribute("href", re_url)
|
||||
})
|
||||
});
|
||||
} else {
|
||||
layer.open({
|
||||
title : '出错啦!'
|
||||
,content: '请在钉钉中打开本页面~~'
|
||||
,btn: '关闭'
|
||||
,btnAlign: 'c'
|
||||
,yes: function(){
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if ('{{ app_type }}' === 'WEWORK') {
|
||||
let re_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={{ app_id }}&agentid={{ agent_id }}&redirect_uri={{ redirect_url }}&response_type=code&scope=snsapi_privateinfo&state=#wechat_redirect"
|
||||
window.onload = function () {
|
||||
document.getElementById("redirect_url").setAttribute("href", re_url)
|
||||
}
|
||||
}
|
||||
form.verify({
|
||||
pass: [
|
||||
/^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[^a-zA-Z0-9]).{8,30}$/,
|
||||
|
@ -94,14 +62,11 @@ layui.use(['form', 'jquery', 'layer'], function () {
|
|||
repass: function (value,item) {
|
||||
if ($('#ensure_password').val() !== $('#new_password').val()) {
|
||||
return '两次输入密码不一致!';
|
||||
}
|
||||
},
|
||||
}},
|
||||
newpass: function (value,item) {
|
||||
if ($('#old_password').val() === $('#password').val()) {
|
||||
return '新旧密码不能重复使用,请修正!';
|
||||
}
|
||||
}
|
||||
});
|
||||
}}});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
<div class="layui-form-item a-middle-text">
|
||||
<span class="layui-breadcrumb">
|
||||
<a class="layui-text" href="/"><i class="layui-icon layui-icon-prev"></i> 返回主页</a>
|
||||
<a class="layui-text" href="/"><i class="layui-icon layui-icon-prev"></i> 修改密码</a>
|
||||
<a class="layui-text" id="redirect_url" href="/unlockAccount?code={{ code }}&username={{ username }}"><i class="layui-icon layui-icon-password"></i> 解锁账号</a>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</div>
|
||||
<div class="layui-form-item a-middle-text">
|
||||
<span class="layui-breadcrumb">
|
||||
<a class="layui-text" href="/"><i class="layui-icon layui-icon-prev"></i> 返回主页</a>
|
||||
<a class="layui-text" href="/"><i class="layui-icon layui-icon-prev"></i> 修改密码</a>
|
||||
<a class="layui-text" id="redirect_url" href="/resetPassword?code={{ code }}&username={{ username }}"><i class="layui-icon layui-icon-refresh-1"></i> 重置密码</a>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import ldap3
|
||||
from ldap3 import *
|
||||
from ldap3.core.exceptions import LDAPInvalidCredentialsResult, LDAPOperationResult, LDAPExceptionError, LDAPException, \
|
||||
LDAPSocketOpenError
|
||||
|
@ -38,8 +37,8 @@ unicodePwd 属性的语法为 octet-string;但是,目录服务预期八进制
|
|||
|
||||
class AdOps(object):
|
||||
|
||||
def __init__(self, auto_bind=True, use_ssl=AD_USE_SSL, port=AD_CONN_PORT, domain=AD_DOMAIN, user=AD_LOGIN_USER,
|
||||
password=AD_LOGIN_USER_PWD,
|
||||
def __init__(self, auto_bind=True, use_ssl=LDAP_USE_SSL, port=LDAP_CONN_PORT, domain=LDAP_DOMAIN, user=LDAP_LOGIN_USER,
|
||||
password=LDAP_LOGIN_USER_PWD,
|
||||
authentication=NTLM):
|
||||
"""
|
||||
AD连接器 authentication [SIMPLE, ANONYMOUS, SASL, NTLM]
|
||||
|
@ -60,7 +59,7 @@ class AdOps(object):
|
|||
def __server(self):
|
||||
if self.server is None:
|
||||
try:
|
||||
self.server = Server(host='%s' % AD_HOST, connect_timeout=1, use_ssl=self.use_ssl, port=self.port,
|
||||
self.server = Server(host='%s' % LDAP_HOST, connect_timeout=1, use_ssl=self.use_ssl, port=self.port,
|
||||
get_info=ALL)
|
||||
except LDAPInvalidCredentialsResult as lic_e:
|
||||
return False, LDAPOperationResult("LDAPInvalidCredentialsResult: " + str(lic_e.message))
|
||||
|
@ -118,7 +117,7 @@ class AdOps(object):
|
|||
# return False, '用户登陆前必须修改密码!'
|
||||
# 设置该账号下次登陆不需要更改密码,再验证一次
|
||||
self.__conn()
|
||||
self.conn.search(search_base=BASE_DN, search_filter='(sAMAccountName={}))'.format(username),
|
||||
self.conn.search(search_base=BASE_DN, search_filter=SEARCH_FILTER.format(username),
|
||||
attributes=['pwdLastSet'])
|
||||
self.conn.modify(self.conn.entries[0].entry_dn, {'pwdLastSet': [(MODIFY_REPLACE, ['-1'])]})
|
||||
return True, self.ad_auth_user(username, password)
|
||||
|
@ -135,7 +134,7 @@ class AdOps(object):
|
|||
"""
|
||||
try:
|
||||
self.__conn()
|
||||
return True, self.conn.search(BASE_DN, '(&(objectclass=user)(sAMAccountName={}))'.format(username),
|
||||
return True, self.conn.search(BASE_DN, SEARCH_FILTER.format(username),
|
||||
attributes=['sAMAccountName'])
|
||||
except Exception as e:
|
||||
return False, "AdOps Exception: {}".format(e)
|
||||
|
@ -148,7 +147,7 @@ class AdOps(object):
|
|||
"""
|
||||
try:
|
||||
self.__conn()
|
||||
self.conn.search(BASE_DN, '(&(objectclass=user)(sAMAccountName={}))'.format(username), attributes=['name'])
|
||||
self.conn.search(BASE_DN, SEARCH_FILTER.format(username), attributes=['name'])
|
||||
return True, self.conn.entries[0]['name']
|
||||
except Exception as e:
|
||||
return False, "AdOps Exception: {}".format(e)
|
||||
|
@ -161,7 +160,7 @@ class AdOps(object):
|
|||
"""
|
||||
try:
|
||||
self.__conn()
|
||||
self.conn.search(BASE_DN, '(&(objectclass=user)(sAMAccountName={}))'.format(username),
|
||||
self.conn.search(BASE_DN, SEARCH_FILTER.format(username),
|
||||
attributes=['distinguishedName'])
|
||||
return True, str(self.conn.entries[0]['distinguishedName'])
|
||||
except Exception as e:
|
||||
|
@ -175,7 +174,7 @@ class AdOps(object):
|
|||
"""
|
||||
try:
|
||||
self.__conn()
|
||||
self.conn.search(BASE_DN, '(&(objectclass=user)(sAMAccountName={}))'.format(username),
|
||||
self.conn.search(BASE_DN, SEARCH_FILTER.format(username),
|
||||
attributes=['userAccountControl'])
|
||||
return True, self.conn.entries[0]['userAccountControl']
|
||||
except Exception as e:
|
||||
|
@ -241,7 +240,7 @@ class AdOps(object):
|
|||
"""
|
||||
try:
|
||||
self.__conn()
|
||||
self.conn.search(BASE_DN, '(&(objectclass=user)(sAMAccountName={}))'.format(username),
|
||||
self.conn.search(BASE_DN, SEARCH_FILTER.format(username),
|
||||
attributes=['lockoutTime'])
|
||||
locked_status = self.conn.entries[0]['lockoutTime']
|
||||
if '1601-01-01' in str(locked_status):
|
||||
|
|
|
@ -163,8 +163,8 @@ class WeWorkOps(AbstractApi):
|
|||
if not _status:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': '获取userid失败,错误信息:{}'.format(ticket_data),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return False, context, ticket_data
|
||||
|
||||
|
@ -173,7 +173,7 @@ class WeWorkOps(AbstractApi):
|
|||
context = {'global_title': TITLE,
|
||||
'msg': '获取用户Ticket失败,当前扫码用户[{}]可能未加入企业!'.format(user_id),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_display': "返回修改密码"
|
||||
}
|
||||
return False, context, user_id
|
||||
|
||||
|
@ -183,8 +183,8 @@ class WeWorkOps(AbstractApi):
|
|||
if not detail_status:
|
||||
context = {'global_title': TITLE,
|
||||
'msg': '获取用户信息失败,错误信息:{}'.format(user_id),
|
||||
'button_click': "window.location.href='%s'" % home_url,
|
||||
'button_display': "返回主页"
|
||||
'button_click': "window.location.href='%s'" % '/auth',
|
||||
'button_display': "重新认证授权"
|
||||
}
|
||||
return False, context
|
||||
return True, user_id, user_info
|
||||
|
|
Loading…
Reference in New Issue